近期做的一个项目进行渗透测试,检测代码存在存储型Xss漏洞。例如在界面文本域输入
网上搜集的大部分代码都是使用过滤器,并对请求数据进行过滤,重写getParameter(String str)方法。因项目使用的数据结构并非字符串,而是封装的Map,这种方法无法实现该项目的具体需求。反编译看了jar文件,其中有方法getParameterMap()可以使用,只需进行重写即可。
实现该功能,分三步:
第一步,编写过滤器,实现Filter接口,代码如下:
package com.xx;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
public class XSSFilter implements Filter {
@Override
public void init(FilterConfig arg0) throws ServletException {
}
@Override
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(new XssRequestWrappers((HttpServletRequest) request), response);
}
}
第二步,继承HttpServletRequestWrapper,重写方法getParameterMap,代码如下:
package com.xx;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
public class XssRequestWrappers extends HttpServletRequestWrapper {
private CommonsMultipartResolver multiparResolver = new CommonsMultipartResolver();
public XssRequestWrappers(HttpServletRequest request) {
super(request);
String type = request.getHeader("Content-Type");
if (!StringUtils.isEmpty(type) && type.contains("multipart/form-data")) {
MultipartHttpServletRequest multipartHttpServletRequest = multiparResolver.resolveMultipart(request);
Map stringMap = multipartHttpServletRequest.getParameterMap();
if (!stringMap.isEmpty()) {
for (String key : stringMap.keySet()) {
String value = multipartHttpServletRequest.getParameter(key);
XSSUtil.stripXSS(key);
XSSUtil.stripXSS(value);
}
}
super.setRequest(multipartHttpServletRequest);
}
}
@Override
public String[] getParameterValues(String parameter) {
String[] values = super.getParameterValues(parameter);
if (values == null) {
return null;
}
int count = values.length;
String[] encodedValues = new String[count];
for (int i = 0; i < count; i++) {
encodedValues[i] = XSSUtil.stripXSS(values[i]);
}
return encodedValues;
}
@Override
public String getParameter(String parameter) {
String value = super.getParameter(parameter);
return XSSUtil.stripXSS(value);
}
@Override
public String getHeader(String name) {
String value = super.getHeader(name);
return XSSUtil.stripXSS(value);
}
@Override
public Map getParameterMap() {
Map map1 = super.getParameterMap();
Map escapseMap = new HashMap();
Set keys = map1.keySet();
for (String key : keys) {
String[] valArr = map1.get(key);
if (valArr != null && valArr.length > 0) {
String[] escapseValArr = new String[valArr.length];
for (int i = 0; i < valArr.length; i++) {
String escapseVal = XSSUtils.striptXSS(valArr[i]);
escapseValArr[i] = escapseVal;
}
escapseMap.put(key, escapseValArr);
}
}
return escapseMap;
}
}
此处写了一个工具类XSSUtils,现在的做法是替换成空字符,CSDN的是进行转义,比如文字开头的"<"转成<。代码如下:
package com.xx;
import java.util.regex.Pattern;
public class XSSUtils {
public static String striptXSS(String value) {
if (value != null) {
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);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("", Pattern.CASE_INSENSITIVE);
value = scriptPattern.matcher(value).replaceAll("");
scriptPattern = Pattern.compile("