工作问题随笔记录-追加Filter过滤器踩坑记录
作者:互联网
一、使用Filter过滤器无法拦截XSS脚本攻击
1、背景描述:近期接手一个老项目,技术栈十分陈旧,使用Struts2+hibernate+JSP技术栈;老项目被阉割后要给中国移动上线使用,用户质控团队测试发现,系统健壮性存在XSS脚本攻击&表情包等问题;本能考虑使用Filter过滤器,处理XSS脚本攻击和表情包存储报错问题(质控发现的其他问题,本次不做详细说明);
2、问题描述:配置XSS脚本攻击过滤器(网上随处可查到),配置过程十分简单此处不在详述;按照步骤配置完后,验证发现XSS脚本注入时,带有恶意脚本的请求可被过滤到,有些带有恶意脚本的请求无法被过滤掉;开始怀疑人生,瞬间整个人生都不美丽了;此处补充一下XSS过滤器处理机制:使用Filter过滤器,拦截检查用户的访问请求中是否带有恶意攻击脚本,若发现存在恶意脚本,将对请求中的恶意脚本做相关处理,通常是将恶意脚本过滤掉或替换为空字符串;若请求中未发现恶意脚本,过滤器不做任何处理直接放行;
3、问题原因:经排查发现包含附件上传的form表单提交,Filter过滤器完全不起作用;普通的form表单提交,Filter过滤器可以正常起作用;最终定位原因是form表单的enctype属性是导致Filter过滤器失效的根本原因;enctype编码类型为multipart/form-data的类型,Filter过滤器对提交参数不做拦截;
4、form表单的enctype属性:
1)定义和用法:
a>enctype属性规定在发送到服务器之前应该如何对表单数据进行编码。
b>默认地,表单数据会编码为 "application/x-www-form-urlencoded"。就是说,在发送到服务器之前,所有字符都会进行编码(空格转换为 "+" 加号,特殊符号转换为 ASCII HEX 值)。
2)属性名值和对应描述:
application/x-www-form-urlencoded在发送前默认编码所有字符;multipart/form-data:不对字符编码,若使用包含文件上传控件的表单时,必须使用该类型;text/plain:空格转换为 "+" 加号,但不对特殊字符编码。
3)详细说明:
form的enctype属性为编码方式,常用有两种:application/x-www-form-urlencoded和multipart/form-data,
a>当action为get时候,浏览器用x-www-form-urlencoded的编码方式把form数据转换成一个字串(name1=value1&name2=value2...),然后把这个字串增加到url后面,用?分割,加载这个新的url。
b>当action为post时候,浏览器把form表单数据封装到HTTP头信息中,然后发送到server。
c>如果没有type=file的控件,用默认的application/x-www-form-urlencoded就可以了。
d>但是如果有type=file的话,就要用到multipart/form-data了。浏览器会把整个表单以控件为单位分割,并为每个部分加上Content-Disposition(form-data或者file),Content-Type(默认为text/plain),name(控件name)等信息,并加上分割符(boundary)。
5、本人解决办法:
1)查阅材料发现SpringMVC解决办法比较简单只管,方案如下所示:
a)一个请求到达过滤器filter时还未经过spring的请求解析,到达拦截器(interceptor)时请求已经经过spring的解析,而spring对multipart/form-data方式请求已做处理;
b)实现了ServletRequest的org.springframework.web.multipart.MultipartHttpServletRequest.java 类 (这个类的getParameter方法可以获取到multipart/form-data和非multipart/form-data方法上传的参数。
所以我们得出一下解决方案:首先在你的spring配置文件中配置MultipartHttpServletRequest
1 <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" p:defaultEncoding="UTF-8"> 2 <property name="maxUploadSize"> 3 <value>104857600</value> 4 </property> 5 <property name="maxInMemorySize"> 6 <value>4096</value> 7 </property> 8 </bean>
或者使用:springboot注解方式定义bean
然后在filter初始化时注入MultipartResolver
1 // 用于创建MultipartHttpServletRequest 2 private MultipartResolver multipartResolver = null; 3 4 @Override 5 public void init(FilterConfig arg0) throws ServletException { 6 // 注入bean 7 multipartResolver = ((MultipartResolver)ApplicationContextUtil.getContext().getBean("multipartResolver", MultipartResolver.class));
}
最后在dofilter中追加代码:
String contentType = req.getContentType(); if (contentType != null && contentType.contains("multipart/form-data")) { MultipartHttpServletRequest multipartRequest = multipartResolver.resolveMultipart((HttpServletRequest)req); //在这里可以通过multipartRequest 获取参数了 // 把multipartRequest让请求继续执行,之后的所有拦截器和controller都能继续get参数
chain.doFilter(multipartRequest , response);
return; }
然而非常不幸,老项目中使用的技术栈是Struts2,我们无法直接解决,因此只能曲线救国了;
2)首先在前端界面做手脚,form表单提交界面使用js校验,拦截住恶意的脚本(本人已测试使用,没毛病);
1 /** 2 * xss校验函数,返回值:true 表示存在xss漏洞,false:不存在 3 * @param v 4 * @returns {boolean} 5 */ 6 function checkIsXSS(value) { 7 var res1 = (new RegExp("\\b(document|onload|eval|script|img|svg|onerror|javascript|alert)\\b")).test(value); 8 var res2 = (new RegExp("<","g")).test(value); 9 var res3 = (new RegExp(">","g")).test(value); 10 return ((res1 == true) || (res2 == true) || (res3 == true)); 11 }
若只是糊弄质控测试,前端做拦截就够用了;但因为暂时专业的,所以后端也是要做相关拦截滴;
后端采用切面+注解的方式,对controller控制层统一做拦截过滤,若发现请求入参中带有恶意脚本,直接将返回前端文本非法提示语;因代码本身并不复杂,此处不做赘述;
标签:脚本,form,记录,表单,Filter,multipart,过滤器,data 来源: https://www.cnblogs.com/aoshicangqiong/p/16325280.html