优化XSS过滤方法,解决一些可能会发生的问题。
This commit is contained in:
@@ -8,6 +8,8 @@ package com.jeesite.common.codec;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.codec.DecoderException;
|
||||
@@ -17,6 +19,7 @@ import org.apache.commons.lang3.StringEscapeUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.jeesite.common.collect.ListUtils;
|
||||
import com.jeesite.common.lang.ExceptionUtils;
|
||||
import com.jeesite.common.lang.StringUtils;
|
||||
|
||||
@@ -183,30 +186,29 @@ public class EncodeUtils {
|
||||
public static String decodeUrl2(String part) {
|
||||
return decodeUrl(decodeUrl(part));
|
||||
}
|
||||
|
||||
|
||||
// 预编译XSS过滤正则表达式
|
||||
private static Pattern p1 = Pattern.compile("<\\s*(script|link|style|iframe)\\s([\\s\\S]+?)<\\/\\s*\\1\\s*>", Pattern.CASE_INSENSITIVE);
|
||||
private static Pattern p2 = Pattern.compile("\\s*on[a-z]+\\s*=\\s*(\"[^\"]+\"|'[^']+'|[^\\s]+)\\s*(?=>)", Pattern.CASE_INSENSITIVE);
|
||||
private static Pattern p3 = Pattern.compile("\\s*(href|src)\\s*=\\s*(\"\\s*(javascript|vbscript):[^\"]+\"|'\\s*(javascript|vbscript):[^']+'|(javascript|vbscript):[^\\s]+)\\s*(?=>)", Pattern.CASE_INSENSITIVE);
|
||||
private static Pattern p4 = Pattern.compile("epression\\((.|\\n)*\\);?", Pattern.CASE_INSENSITIVE);
|
||||
private static List<Pattern> xssPatterns = ListUtils.newArrayList(
|
||||
Pattern.compile("(<\\s*(script|link|style|iframe)([\\s\\S]*?)(>|<\\/\\s*\\1\\s*>))|(</\\s*(script|link|style|iframe)\\s*>)", Pattern.CASE_INSENSITIVE),
|
||||
Pattern.compile("\\s*(href|src)\\s*=\\s*(\"\\s*(javascript|vbscript):[^\"]+\"|'\\s*(javascript|vbscript):[^']+'|(javascript|vbscript):[^\\s]+)\\s*(?=>)", Pattern.CASE_INSENSITIVE),
|
||||
Pattern.compile("\\s*on[a-z]+\\s*=\\s*(\"[^\"]+\"|'[^']+'|[^\\s]+)\\s*(?=>)", Pattern.CASE_INSENSITIVE),
|
||||
Pattern.compile("(eval\\((.|\\n)*\\)|xpression\\((.|\\n)*\\))", Pattern.CASE_INSENSITIVE)
|
||||
);
|
||||
|
||||
/**
|
||||
* XSS 非法字符过滤
|
||||
* 内容以<!--HTML-->开头的用以下规则(保留标签,去掉js脚本):
|
||||
* 1、<\s*(script|link|style|iframe)\s([\s\S]+?)<\/\s*\1\s*>
|
||||
* 2、\s*on[a-z]+\s*=\s*("[^"]+"|'[^']+'|[^\s]+)\s*(?=>)
|
||||
* 3、\s*(href|src)\s*=\s*("\s*(javascript|vbscript):[^"]+"|'\s*(javascript|vbscript):[^']+'|(javascript|vbscript):[^\s]+)\s*(?=>)
|
||||
* 4、epression\((.|\n)*\);?
|
||||
* 其它情况下:进行HTML4编码
|
||||
* XSS 非法字符过滤,内容以<!--HTML-->开头的用以下规则(保留标签)
|
||||
* @author ThinkGem
|
||||
*/
|
||||
public static String xssFilter(String text) {
|
||||
String oriValue = StringUtils.trim(text);
|
||||
if (text != null){
|
||||
String oriValue = StringUtils.trim(text), value = oriValue;
|
||||
value = p1.matcher(value).replaceAll("");
|
||||
value = p2.matcher(value).replaceAll("");
|
||||
value = p3.matcher(value).replaceAll("");
|
||||
value = p4.matcher(value).replaceAll("");
|
||||
String value = oriValue;
|
||||
for (Pattern pattern : xssPatterns) {
|
||||
Matcher matcher = pattern.matcher(value);
|
||||
if (matcher.find()) {
|
||||
value = matcher.replaceAll(StringUtils.EMPTY);
|
||||
}
|
||||
}
|
||||
// 如果开始不是HTML,XML,JOSN格式,则再进行HTML的 "、<、> 转码。
|
||||
if (!StringUtils.startsWithIgnoreCase(value, "<!--HTML-->") // HTML
|
||||
&& !StringUtils.startsWithIgnoreCase(value, "<?xml ") // XML
|
||||
@@ -217,7 +219,7 @@ public class EncodeUtils {
|
||||
value = value.replaceAll("\"", """).replaceAll("<", "<").replaceAll(">", ">");
|
||||
}
|
||||
if (logger.isInfoEnabled() && !value.equals(oriValue)){
|
||||
logger.info("xssFilter: {} to {}", text, value);
|
||||
logger.info("xssFilter: {} <=<=<= {}", value, text);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
@@ -225,7 +227,7 @@ public class EncodeUtils {
|
||||
}
|
||||
|
||||
// 预编译SQL过滤正则表达式
|
||||
private static Pattern p5 = Pattern.compile("(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|(\\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)", Pattern.CASE_INSENSITIVE);
|
||||
private static Pattern sqlPattern = Pattern.compile("(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|(\\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)", Pattern.CASE_INSENSITIVE);
|
||||
|
||||
/**
|
||||
* SQL过滤,防止注入,传入参数输入有select相关代码,替换空。
|
||||
@@ -233,13 +235,48 @@ public class EncodeUtils {
|
||||
*/
|
||||
public static String sqlFilter(String text){
|
||||
if (text != null){
|
||||
String value = p5.matcher(text).replaceAll("");
|
||||
String value = text;
|
||||
Matcher matcher = sqlPattern.matcher(text);
|
||||
if (matcher.find()) {
|
||||
value = matcher.replaceAll(StringUtils.EMPTY);
|
||||
}
|
||||
if (logger.isWarnEnabled() && !value.equals(text)){
|
||||
logger.warn("sqlFilter: {} to {}", text, value);
|
||||
logger.info("sqlFilter: {} <=<=<= {}", value, text);
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// public static void main(String[] args) {
|
||||
// xssFilter("你好,<script>alert(document.cookie)</script>我还在。");
|
||||
// xssFilter("你好,<strong>加粗文字</strong>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,\"><strong>加粗文字</strong>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<iframe src=\"abcdef\"></iframe><strong>加粗文字</strong>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<iframe src=\"abcdef\"/><strong>加粗文字</strong>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<iframe src=\"abcdef\"><strong>加粗文字</strong>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<script type=\"text/javascript\">alert(document.cookie)</script>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<script\n type=\"text/javascript\">\nalert(document.cookie)\n</script>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<script src='' onerror='alert(document.cookie)'></script>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<script type=text/javascript>alert()我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<script>alert(document.cookie)</script>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<script>window.location='url'我还在。");
|
||||
// xssFilter("<!--HTML-->你好,</script></iframe>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,eval(abc)我还在。");
|
||||
// xssFilter("<!--HTML-->你好,xpression(abc)我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<img src='abc.jpg' onerror='location='';alert(document.cookie);'></img>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<img src='abc.jpg' onerror='alert(document.cookie);'/>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<img src='abc.jpg' onerror='alert(document.cookie);'>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<a onload='alert(\"abc\")'>hello</a>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<a href=\"/abc\">hello</a>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<a href='/abc'>hello</a>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<a href='vbscript:alert(\"abc\");'>hello</a>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,<a href='javascript:alert(\"abc\");'>hello</a>我还在。");
|
||||
// xssFilter("<!--HTML-->你好,?abc=def&hello=123&world={\"a\":1}我还在。");
|
||||
// sqlFilter("你好,select * from xxx where abc=def and 1=1我还在。");
|
||||
// sqlFilter("你好,insert into xxx values(1,2,3,4,5)我还在。");
|
||||
// sqlFilter("你好,delete from xxx我还在。");
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user