• 工作问题随笔记录追加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控制层统一做拦截过滤,若发现请求入参中带有恶意脚本,直接将返回前端文本非法提示语;因代码本身并不复杂,此处不做赘述;

  • 相关阅读:
    vim 常用命令
    centos 安装mysql
    centos部署ftp
    centos 6.8部署nginx
    ndk学习16: unix domain socket
    ndk学习14: 进程
    ndk学习13: proc
    ndk学习11: linux内存管理
    ndk学习10: linux文件系统
    ndk学习9: 动态使用共享库
  • 原文地址:https://www.cnblogs.com/aoshicangqiong/p/16325280.html
Copyright © 2020-2023  润新知