Index: forgon-core/src/main/java/com/forgon/xss/request/XSSServletRequest.java =================================================================== diff -u -r34613 -r34632 --- forgon-core/src/main/java/com/forgon/xss/request/XSSServletRequest.java (.../XSSServletRequest.java) (revision 34613) +++ forgon-core/src/main/java/com/forgon/xss/request/XSSServletRequest.java (.../XSSServletRequest.java) (revision 34632) @@ -2,6 +2,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import javax.servlet.http.HttpServletRequest; @@ -20,14 +21,35 @@ * @since 2019-08-28 */ public class XSSServletRequest extends HttpServletRequestWrapper { + private HttpServletRequest request; + + //要放行的请求地址及参数名称的map + static Map urlToParamNameNoFilterMap = new HashMap(); + static{ + urlToParamNameNoFilterMap.put("/disinfectSystem/baseData/tousseDefinitionAction!saveTousseDefinitionNote.do", "note"); + } + + static Entry matchRequestURI(HttpServletRequest request){ + String uri = request.getRequestURI(); + for(Entry entry :urlToParamNameNoFilterMap.entrySet()){ + if(entry.getKey().contains(uri)){ + return entry; + } + } + return null; + } private CommonsMultipartResolver multiparResolver = new CommonsMultipartResolver(); public XSSServletRequest(HttpServletRequest request) { super(request); + this.request = request; + //QYSRMYY-42 修复渗透测试扫描出来的存储型和反射型XSS漏洞 String type = request.getHeader("Content-Type"); + String requestURI = request.getRequestURI(); if (StringUtils.isNotBlank(type)){ - if(type.contains("multipart/form-data")) { + //文件上传不进行xss处理(因为上传文件会报错) + /*if(type.contains("multipart/form-data")) { MultipartHttpServletRequest multipartHttpServletRequest = multiparResolver.resolveMultipart(request); Map stringMap = multipartHttpServletRequest.getParameterMap(); if (!stringMap.isEmpty()) { @@ -38,21 +60,53 @@ } } super.setRequest(multipartHttpServletRequest); - }else if(type.contains("text/html") || type.contains("application/x-www-form-urlencoded")){ + }else */if(type.contains("text/html") || type.contains("application/x-www-form-urlencoded") || type.contains("text/plain")){ Map map = request.getParameterMap(); if(MapUtils.isNotEmpty(map)){ - map.entrySet().stream().forEach(entry -> { - String name = entry.getKey(); - String value = request.getParameter(name); - XSSFilterUtil.striptXss(value); - }); + Entry uriFilterEntry = matchRequestURI(request); + if(uriFilterEntry == null){ + map.entrySet().stream().forEach(entry -> { + String name = entry.getKey(); + String value = request.getParameter(name); + value = XSSFilterUtil.striptXss(value); + }); + }else{ + String paramName = uriFilterEntry.getValue(); + map.entrySet().stream().forEach(entry -> { + String name = entry.getKey(); + if(!StringUtils.equals(paramName, name)){ + String value = request.getParameter(name); + value = XSSFilterUtil.striptXss(value); + } + }); + } } } + }else{ + Map map = request.getParameterMap(); + if(MapUtils.isNotEmpty(map)){ + map.entrySet().stream().forEach(entry -> { + String name = entry.getKey(); + String value = request.getParameter(name); + value = XSSFilterUtil.striptXss(value); + }); + } } } @Override public String getParameter(String name) { + String contentType = request.getContentType(); + if(StringUtils.isNotBlank(contentType)){ + //用下文的代码可以解决传富文本(带html标签)的参数的问题,但不能解决反射型xss的问题 + Entry uriFilterEntry = matchRequestURI(request); + if(uriFilterEntry != null && !StringUtils.equals(uriFilterEntry.getValue(), name)){ + String value = request.getParameter(name); + return XSSFilterUtil.striptXss(value); + } + return super.getParameter(name); + } + //用下文的代码可以解决反射型xss问题,但不能解决传富文本(带html标签)的参数的问题 return XSSFilterUtil.striptXss(super.getParameter(name)); } @@ -80,12 +134,14 @@ encodedValues[i] = XSSFilterUtil.striptXss(values[i]); } return encodedValues; +// return super.getParameterValues(parameter); } @Override public String getHeader(String name) { String value = super.getHeader(name); return XSSFilterUtil.striptXss(value); +// return super.getHeader(name); } @Override @@ -104,8 +160,8 @@ escapseMap.put(key, escapseValArr); } } - return escapseMap; +// return super.getParameterMap(); } } Index: forgon-core/src/main/java/com/forgon/xss/util/XSSFilterUtil.java =================================================================== diff -u -r34615 -r34632 --- forgon-core/src/main/java/com/forgon/xss/util/XSSFilterUtil.java (.../XSSFilterUtil.java) (revision 34615) +++ forgon-core/src/main/java/com/forgon/xss/util/XSSFilterUtil.java (.../XSSFilterUtil.java) (revision 34632) @@ -22,15 +22,6 @@ */ public static String striptXss(String value){ if(StringUtils.isNotBlank(value)){ - value = value.replaceAll("<", "<"); - value = value.replaceAll(">", ">"); - value = value.replaceAll("prompt", "PROMPT"); - value = value.replaceAll("confirm", "CONFIRM"); - value = value.replaceAll("alert", "ALERT"); - //下面两行会影响正常的json数据传送,暂先注释 - //value = value.replaceAll("\\\"", """); - //value = value.replaceAll("&", "&"); - Pattern scriptPattern = Pattern.compile("",Pattern.CASE_INSENSITIVE); value = scriptPattern.matcher(value).replaceAll(""); scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'",Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); @@ -52,6 +43,16 @@ scriptPattern = Pattern.compile("onload(.*?)=",Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); scriptPattern = Pattern.compile(".*<.*",Pattern.CASE_INSENSITIVE); + + value = value.replaceAll("<", "<"); + value = value.replaceAll(">", ">"); + value = value.replaceAll("prompt", "PROMPT"); + value = value.replaceAll("confirm", "CONFIRM"); + value = value.replaceAll("alert", "ALERT"); + //下面两行会影响正常的json数据传送,暂先注释 + //value = value.replaceAll("\\\"", """); + //value = value.replaceAll("&", "&"); + value = scriptPattern.matcher(value).replaceAll(""); } return value;