From 300bbd5f8f7903f5f56b7b355362c17dd18a9761 Mon Sep 17 00:00:00 2001 From: thinkgem Date: Sat, 11 Aug 2018 12:59:03 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96XSS=E8=BF=87=E6=BB=A4?= =?UTF-8?q?=E6=96=B9=E6=B3=95=EF=BC=8C=E8=A7=A3=E5=86=B3=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E5=8F=AF=E8=83=BD=E4=BC=9A=E5=8F=91=E7=94=9F=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/jeesite/common/codec/EncodeUtils.java | 79 ++++++++++++++----- 1 file changed, 58 insertions(+), 21 deletions(-) diff --git a/common/src/main/java/com/jeesite/common/codec/EncodeUtils.java b/common/src/main/java/com/jeesite/common/codec/EncodeUtils.java index 39a85b3b..07d229a5 100644 --- a/common/src/main/java/com/jeesite/common/codec/EncodeUtils.java +++ b/common/src/main/java/com/jeesite/common/codec/EncodeUtils.java @@ -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 xssPatterns = ListUtils.newArrayList( + Pattern.compile("(<\\s*(script|link|style|iframe)([\\s\\S]*?)(>|<\\/\\s*\\1\\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 非法字符过滤 - * 内容以开头的用以下规则(保留标签,去掉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 非法字符过滤,内容以开头的用以下规则(保留标签) * @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 && !StringUtils.startsWithIgnoreCase(value, "", ">"); } 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("你好,我还在。"); +// xssFilter("你好,加粗文字我还在。"); +// xssFilter("你好,\">加粗文字我还在。"); +// xssFilter("你好,加粗文字我还在。"); +// xssFilter("你好,我还在。"); +// xssFilter("你好,eval(abc)我还在。"); +// xssFilter("你好,xpression(abc)我还在。"); +// xssFilter("你好,我还在。"); +// xssFilter("你好,我还在。"); +// xssFilter("你好,我还在。"); +// xssFilter("你好,hello我还在。"); +// xssFilter("你好,hello我还在。"); +// xssFilter("你好,hello我还在。"); +// xssFilter("你好,hello我还在。"); +// xssFilter("你好,hello我还在。"); +// xssFilter("你好,?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我还在。"); +// } + }