XSS 前端防火墙(5): 整装待发
到目前为止,我们把能用前端脚本防御 XSS 的方案都列举了一遍。
尽管看起来似乎很复杂累赘,不过那些是理论探讨而已,在实际中未必要都实现。我们的目标只是为了预警,能发现问题就行,并非要做到滴水不漏的程度。
事实上,HTML5 早已制定了一套浏览器 XSS 解决方案 —— Content Security Policy,并且大多主流浏览器实现了这个标准。
既然我们使用前端脚本重新实现一遍,因此得在各个方面占有优势。
兼容性
CSP 目前主流浏览器大多已支持,IE10、11 支持部分功能。对于 IE10 之前的,当然就束手无策了。如果使用前端脚本实现,可根据浏览器的实际能力进退。
对于第一篇介绍的 DOM-XSS,只要支持标准事件模型即可开启,因此兼容 IE9 完全可行。
事实上,IE8 就已开放了浏览器 API 接口,并支持原生访问器的操作。所以,IE8 是支持钩子程序,并能拦截可疑元素。
考虑到实际中,大多情况不做拦截,仅仅上报日志用以预警。对于这样低的需求,任何版本的浏览器都是完全可行的,甚至连 IE6 也没问题。
由于国内 IE 浏览器仍占有相当一部分比例,因此使用前端脚本的方案,能覆盖到更广的用户群体中。
部署
CSP 是通过 HTTP 头部实现的,策略配置储存在 Content-Security-Policy 这个字段里,因此得在 Web 服务器端进行配置。这对一些使用虚拟主机搭建的中小网站来说,配置起来比较麻烦。
而前端实现只需在页面里插入个脚本就行,完全不用关心后端的部署,修改策略也无需重启服务,维护起来容易的多。
不过,未来 CSP 会支持页面部署,通过 meta 标签即可配置策略,因此实用性会大幅提高。
当然,如今面临的各种问题,最终都能通过标准的完善和时代的进步而消失。所以任何方案都只是在解决当下的问题。
性能
毫无疑问,浏览器原生支持的肯定比模拟出来的更有效率。
之前考虑了各种情况,需安装各种事件和钩子,感觉很是累赘。不过,那只是理论上防御最严密的情况,现实中基本只作预警,并不需监控全开。
作为测试,我们还是考虑最严密的情况。根据前几篇文章探讨的结果,我们做一个原型演示。
为了能线下模拟在线产品,同时做了一个 Chrome 插件,将脚本注入到在线页面里:

页面中使用到的脚本、插件、网络通信等,都在控制台里监控到,并且根据策略匹配显示不同的颜色。
再来看性能影响。尽管我们开启了所有的监控,但初始化消耗的时间,仍可接受。(测试环境 i3 2.3G 的笔记本 Win7 64位)
毕竟,JavaScript 的钩子仅仅是修改变量的字段而已,并非像传统语言那样得修改内存权限等等。

当然,这个页面内容比较少,只能看出脚本初始化的情况。
我们换个内容非常多的页面:
由于嵌套了框架页,在讨论钩子的时候我们提到,新的页面环境也需防御,因此触发了多次『主动防御』的初始化。
『静态扫描』的内容,正是被 MutationObserver 捕获的元素。由于页面内容非常多,静态元素也是随着 HTML 文档边下载边展现的。尽管扫描累计时间并不少,但相对整个页面加载的数秒时间,也基本忽略不计了。
『动态扫描』的内容,则是后期通过脚本创建的。随着滚动条往下拉,扫描次数也逐渐增多。由于我们勾住了 createElement ,理论上说调用会慢一些。不过现实中很少会一口气大量调用该方法的,大多使用模板通过 innerHTML 批量创建。
另外,我们还勾住了 setAttribute 这个常用的方法,统计结果和『访问器钩子』一起纳入在『属性检验』里。不过,现实中大多场合并不需要调用这个方法,毕竟从 attribute 到 property 还得经过一次字符串的解析,能直接用 property 则完全没必要去 setAttribute。
而访问器钩子,只有在修改 script、embed 这些元素的 src 属性时才会触发,这些操作本来就很少,因此属性扫描的额外消耗还是可以忽略的。
策略配置
使用脚本最大的优势就在于,其策略可以灵活配置。规则可以动态产生,匹配也不限模式,通配符或是正则都可以。本来一切都是脚本实现的,何去何从完全也可由脚本决定。
当然,为了更好的适应 CSP 标准,我们尽可能的将策略规范与标准靠近,以便相互兼容。
因为脚本的灵活性,我们不仅支持通配符来匹配站点名,正则表达式也是完全支持。同时为了方便测试,调试控制台里可以动态修改策略。
下面,我们找个存在 XSS 的页面,立即来试验下:

刷新,XSS 执行了:

虽然是非同源执行的,但好歹也算个 XSS。我们就那它来测试。
接着开启我们的防火墙,为可执行模块配上白名单策略。只允许当前站点的资源,其他的则拦截,并且发送报警日志:

出现奇迹的时刻到来了。。。

站外的可疑模块成功拦截了!同时开始发送预警日志到后台。
日志上报
标准的 CSP 中,上报的格式是固定的,并且信息内容也有限。但对于脚本来说,这些都不是问题,随时可以添加想要获得的信息。
你肯定会觉得,上报的数量不会太多,存在漏洞的毕竟只是少数。不过,广义上的 XSS 未必都是由漏洞引起的。
XSS —— Cross Site Script,只要是页面里的站外的脚本,都可以算是。通常情况下只能由漏洞引起,但在一些特殊的场合,任意页面都可能出现站外脚本,例如之前讨论的流量劫持,或是浏览器插件,都是很常见的情况。
所以,我们除了能在线预警外,还能统计各个地区运行商的广告劫持,以及一些网页外挂插件。
当然,想绕过也是很容易的。只要在流量上过滤了我们的防御脚本,或是屏蔽日志发送,我们都是无从得知的。
后记
事实上,最终的方案已上线。尽管只抽样了极少量的用户,但仍传回上百万的预警日志。几乎所有都是广告劫持和浏览器插件,即使存在漏洞暂时也无法得知,我们不可能一个个去分析复现。因此,我们还需一套高效的复现系统,来帮助我们实现自动化的复现工作。
XSS 前端防火墙(5): 整装待发的更多相关文章
- XSS前端防火墙
前一段时间,在EtherDream大神的博客里看到关于XSS防火墙的一系列文章,觉得很有意思.刚好科创要做一个防火墙,就把XSS前端防火墙作为一个创新点,着手去实现了. 在实现过程中,由于各种原因,比 ...
- XSS 前端防火墙 —— 整装待发
到目前为止,我们把能用前端脚本防御 XSS 的方案都列举了一遍. 尽管看起来似乎很复杂累赘,不过那些是理论探讨而已,在实际中未必要都实现.我们的目标只是为了预警,能发现问题就行,并非要做到滴水不漏的程 ...
- XSS 前端防火墙(1):内联事件拦截
关于 XSS 怎样形成.如何注入.能做什么.如何防范,前人已有无数的探讨,这里就不再累述了.本文介绍的则是另一种预防思路. 几乎每篇谈论 XSS 的文章,结尾多少都会提到如何防止,然而大多万变不离其宗 ...
- XSS 前端防火墙 —— 可疑模块拦截
上一篇介绍的系统,已能预警现实中的大多数 XSS 攻击,但想绕过还是很容易的. 由于是在前端防护,策略配置都能在源代码里找到,因此很快就能试出破解方案.并且攻击者可以屏蔽日志接口,在自己电脑上永不发出 ...
- XSS 前端防火墙(2):可疑模块拦截
由于是在前端防护,策略配置都能在源代码里找到,因此很快就能试出破解方案.并且攻击者可以屏蔽日志接口,在自己电脑上永不发出报警信息,保证测试时不会被发现. 昨天提到最简单并且最常见的 XSS 代码,就是 ...
- XSS 前端防火墙 —— 天衣无缝的防护
上一篇讲解了钩子程序的攻防实战,并实现了一套对框架页的监控方案,将防护作用到所有子页面. 到目前为止,我们防护的深度已经差不多,但广度还有所欠缺. 例如,我们的属性钩子只考虑了 setAttribut ...
- XSS 前端防火墙 —— 无懈可击的钩子
昨天尝试了一系列的可疑模块拦截试验,尽管最终的方案还存在着一些兼容性问题,但大体思路已经明确了: 静态模块:使用 MutationObserver 扫描. 动态模块:通过 API 钩子来拦截路径属性. ...
- XSS 前端防火墙(3):无懈可击的钩子
昨天尝试了一系列的可疑模块拦截试验,尽管最终的方案还存在着一些兼容性问题,但大体思路已经明确了: 静态模块:使用 MutationObserver 扫描. 动态模块:通过 API 钩子来拦截路径属性. ...
- XSS 前端防火墙(4):天衣无缝的防护
例如,我们的属性钩子只考虑了 setAttribute,却忽视还有类似的 setAttributeNode.尽管从来不用这方法,但并不意味人家不能使用. 例如,创建元素通常都是 createEleme ...
随机推荐
- 学了C语言,如何写个程序计算出每个月的第一个星期一对应的日期
在前面,我们分别利用泰勒公式和C标准库中的mktime()函数推算了某个特定日期所对应的星期几,刚做完这些,就又遇到了一个与日期相关的新任务: 老板把每个月例会的时间定在了每个月的第一个星期一,他让我 ...
- Spring框架学习之第7节
配置Bean的细节 ☞尽量使用scope=”singleton”,不要使用prototype,因为这样对我们的性能影响较大 ②如何给集合类型注入值 Java中主要的map,set,list / 数组 ...
- IOS中表视图(UITableView)使用详解
IOS中UITableView使用总结 一.初始化方法 - (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)styl ...
- PHP如何提取img标签属性
extract_attrib是一个提取的图像标签属性的PHP脚本函数,使用正则表达式方法提取. 当你想在HTML的img标签中提取图像数据,这非常有用. 如果你知道如何修改正则表达式,那么同样的功能进 ...
- HTML5之拖拽(兼容IE和非IE)
前世:项目中需要拖动div,然后和某个div进行位置交换,这不是关键,关键是还要保存位置,然后在下次打开的时候按照保存的位置显示.还好本人功力深厚,一下子就想到了用localStorage来保存,事实 ...
- Data Flow ->> Union All
Wrox的<Professional Microsoft SQL Server 2012 Integration Services>一书中再讲Merge的时候有这样一段解释: This t ...
- sublime3配置Quick-X+自动错误提示
sublime3配置 安装Package Control 配置Quick-x API提示 配置Lua自动语法错误提示 sublime3 安装 Package Control View->Show ...
- java 反编译插件 JD-Eclipse 和 JD-IntelliJ
去官网 : http://jd.benow.ca/ 找到 JD-Eclipse 和 JD-IntelliJ,下载,前者安在eclipse上,后者安在as上.
- 使用jQuery插件PrintArea进行html页面打印
在开发系统时,我们一般会有统计分析的功能需求,而现在大多数系统都是使用B/S的形式开发. 所以,html报表打印,并且打印指定内容,成了必要的功能. 开源地址:https://github.com/R ...
- List排序的两种简便方式
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace List ...