首页 » Java » Spring » 正文

在SpringMVC中使用过滤器(Filter)过滤容易引发XSS的危险字符

一 简介

如题所示,如果不在服务端对用户的输入信息进行过滤,然后该参数又直接在前台页面中展示,毫无疑问将会容易引发XSS攻击(跨站脚本攻击),比如说这样:

form表单中有这么一个字段:

然后潜在攻击者在该字段上填入以下内容:

紧接着服务端忽略了“一切来至其他系统的数据都存在安全隐患”的原则,并没有对来至用户的数据进行过滤,导致了直接在前台页面中进行展示。很显然直接弹窗了:

20160925004048

当然,这里仅仅只是一个无伤大雅的弹窗,如果是恶意的攻击者呢?他可能会利用这个漏洞盗取cookie、篡改网页,甚至是配合CSRF漏洞伪造用户请求,形成大规模爆发的蠕虫病毒等等。

比如说远程加载这么一个js将会导致用户的cookie被窃取:

然后将可以在自己搭建的XSS平台中收到信息,比如像这样:

20160925010503

注:因为我在这个demo程序里没有设置cookie,因此cookie那一栏显示为空白

当然,值得庆幸的是,像国内一些主流的浏览器(如:360浏览器、猎豹浏览器)对这类常见的XSS payload都进行了过滤,查看网页源代码可以发现这些危险的字符均使用了鲜艳的红色字体进行了标注,同时该脚本并不能成功地执行:

20160925010820

不过,我发现我使用的IE10和最新版的Firefox都没有进行此项过滤,不得不说是个遗憾

注:我这里只是测试了猎豹、360、IE10以及火狐这四款浏览器,其他的没测试,因此不敢妄加评论

二 使用Filter过滤容易引发XSS的危险字符

(1)自定义一个过滤用的Filter:

(2)在web.xml文件中将该过滤器放在最前面或者是字符编码过滤器之后:

关于这个自定义的过滤器,我觉得有以下几点需要简单说明下:

i)我这里为了方便,没有自己手动写很多过滤规则,只是使用了commons-lang3-3.2.jar 这个jar包中的 StringEscapeUtils 这个方法类来进行过滤。在这个类中有以下几种过滤方法,分别是:escapeJava、escapeEcmaScript、escapeHtml3、escapeHtml4、escapeJson、escapeCsv、escapeEcmaScript 以及 escapeXml。关于这几种方法分别是如何进行过滤的可以自行查阅官方文档或者自己动手写一个简单的Demo进行测试。当然,我这里使用的是escapeXml这个方法进行过滤

ii)因为一个web工程中通常会存在js、CSS、图片这类静态资源目录的,很显然这些目录是不需要进行过滤的。因此我也做了这方面的处理,代码很简单,看看上面的例子就明白了,或者可以看看我的这篇文章:https://www.zifangsky.cn/647.html

iii)关于“在Filter中修改HttpServletRequest中的参数”这个问题,只需要自定义一个类继承与HttpServletRequestWrapper 这个类,然后复写几个方法即可。如果对这方面不太理解的同学可以看看我的这篇文章:https://www.zifangsky.cn/677.html

iv)在上面的过滤器中,我在escapeXSS(String str) 这个方法的后面还针对“# onerror=javascript:alert(123)” 这种语句进行了专门的过滤。不过不过滤的话问题也不大,我觉得最多就是出现个弹窗,因为把尖括号和引号都给转义了,并不能够执行一些比较危险的操作

(3)两个测试的前台页面:

i)form表单页面input.jsp:

ii)结果显示页面show.jsp:

(4)测试用的Controller:

这里的代码逻辑很简单,因此就不多做解释了

(5)测试:

测试的效果如下:

20160925014319

对应的网页源代码是这样的:

20160925014435

可以看出,我们的目标已经成功实现了,本篇文章到此结束

本文共 5 个回复

  • 世纪末 2018/05/26 12:14

    这种吃力不讨好的通杀方案,很容易造成正常请求被过滤的情况,如果以后特殊情况变多,这个过滤器加判断都得加死。 你只需要处理2种情况: 1、简单字段,这种直接在添加时,加正则等类型的字段强校验 2、如果是富文本或评论这种类富文本的,这种字段存入数据库时就做html编码,也就是你说的escapeHtml,输出时正常输出即可。(看一下常见的评论插件实现方案就知道了,eg:多说等)

    • admin 博主 2018/05/28 08:55

      @ 世纪末 的确,实际情况下安全性和实用性需要谨慎权衡,以达到某种平衡。

  • strawbingo 2017/01/24 14:50

    zifang,请教一个问题。 该种过滤方式会过滤所有字符串。 现在加入前台通过form方式提交,字段值实际为一段json串。如果这样过滤的话,解析json串就会出现问题。 请问如何处理这样的问题?在只修改filter,不影响其他代码的前提下。 谢谢。

    • admin 博主 2017/01/24 20:39

      @ strawbingo 你这个问题就需要在filter里面的具体过滤规则那里(PS:escapeXSS())写得稍微复杂一点了,为了不影响json解析你可以不对单双引号进行转义,但是需要对其他一些敏感字符进行转义,如:<、>、src、scripts、insert、execute、select、update、and、or、onerror等等

      • strawbingo 2017/01/25 16:13

        @ admin 多谢回复。 之前尝试过这个方法,但是在调试过程中发现有些时候json串会变化,就没敢使用。 后来定位到其实不是XSS转换的问题。 如第一次前台传递list:[{"createTime":1484113041000,"creator":"400768","flag":1,后台打印显示{"list":["[{\"createTime\":1484113041000,\"creator\":\"400768\",\"flag\":1,。 后台断点,前台超时,页面不关闭,再次点击按钮请求。 此时前台传递变为list:"[{\"createTime\":1484113041000,\"creator\":\"400768\",\"flag\":1,后台打印显示["\"[{\\\"createTime\\\":1484113041000,\\\"creator\\\":\\\"400768\\\",\\\"flag\\\":1。 这是进行转换会报json格式错误。 最终使用方案,传入参数不处理,返回给前台的数据统一进行 StringEscapeUtils.escapeHtml(returnString);转码。

发表评论

*