优化XSS过滤方法,解决一些可能会发生的问题。

This commit is contained in:
thinkgem
2018-08-11 12:59:03 +08:00
parent 099ce0758b
commit 300bbd5f8f

View File

@@ -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);
}
}
// 如果开始不是HTMLXMLJOSN格式则再进行HTML的 "、<、> 转码。
if (!StringUtils.startsWithIgnoreCase(value, "<!--HTML-->") // HTML
&& !StringUtils.startsWithIgnoreCase(value, "<?xml ") // XML
@@ -217,7 +219,7 @@ public class EncodeUtils {
value = value.replaceAll("\"", "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
}
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我还在。");
// }
}