“风不定,人初静,明月落红应满径”
起因
最初因为这样,我们系统被送去检测漏洞,发现了XSS攻击的漏洞。如下图:
在产品描述的地方写上一些JS脚本,我们系统的过滤器不会过滤掉这些脚本。于是,开始了下面的寻找真相过程。
寻找真相
-
首先,上图中的form表中属性为:
<form id="XXX" method="post" enctype="multipart/form-data">
着重说明一下,这里的form表单用到了enctype="multipart/form-data"
属性,但是此表单并没有提交文件。 -
看下我们写的过滤器:
-
但是 但是 。带有
enctype="multipart/form-data"
属性的form表单根本就不会进入上图中的getParameterValues
方法,也就不会替换危险字符了。 -
这个时候,你有两种方法可以选择。第一:把不需要上传文件的form表单中删掉
enctype="multipart/form-data"
属性。那它即是默认的application/x-www-form-urlencoded
形式。
删掉enctype="multipart/form-data"
之后,就能正常进入上面过滤器的getParameterValues
方法,也就可以正常替换了。很明显,我选择的是第二种方法,即修改过滤器。 -
在过滤器中加个判断,如果是文件类型的提交,则把
HttpServletRequest
换成MultipartHttpServletRequest
。就可以过滤了。
// 用于创建MultipartHttpServletRequest
private MultipartResolver multipartResolver = null;
public void init(FilterConfig filterConfig) throws ServletException {
//获取multipartResolver 类
WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
ServletContext context = webApplicationContext.getServletContext();
WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(context);
multipartResolver = (MultipartResolver) ctx.getBean("multipartResolver");
}
public void doFilter(ServletRequest req, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)req;
HttpSession session = request.getSession();
//判断在新增修改时,如果form表中的entype中有multipart/form-data,则把request换成MultipartHttpServletRequest,这样
//才可以获取到form表中的值,并且进行过滤
String enctype = req.getContentType();
if (StringUtils.isNotBlank(enctype) && enctype.contains("multipart/form-data")){
// 返回 MultipartHttpServletRequest 用于获取 multipart/form-data 方式提交的请求中 上传的参数
chain.doFilter(new LocalXssHttpServletRequestWrapper(multipartResolver.resolveMultipart(request),filterChar,replaceChar,splitChar), response);
}else {
chain.doFilter(new LocalXssHttpServletRequestWrapper(request,filterChar,replaceChar,splitChar), response);
}
}
- 但是 但是 。又是一个大大的但是。这样改了之后,在form表单中如果是需要提交文件的时候,浏览器会报400的错误。但是控制台上又没有输出错的时候,这时候需要打开spring的日志:
log4j.logger.org.springframework=debug
。这样才能看到错误是:Required MultipartFile parameter 'file' is not present
。为了解决这个问题,你需要把public Map<String,Object> XXX(HttpServletRequest request,@RequestParam("file") MultipartFile[] files,String state) {}
参数中的file改为required=false
即@RequestParam(value = "file",required = f ) MultipartFile[] files
- 这样之后,你就能正常提交form表单了,并且能够正常的过滤。
- 但是 但是 。问题又来了,文件提交不上去了。参数中的
MultipartFile[] files
为null。。。望大神解答。