前言
深入接触 xss 注入是从排查业务的广告注入开始,以前对 xss 注入片面认为是页面输入的安全校验漏洞导致一系列的问题,通过对 zjcqoo 的《XSS 前端防火墙》系列文章,认识到自己其实对 XSS 注入的认识还真是半桶水。
捣蛋的运营商
由于 xss 注入的范围太广,本文仅对网关劫持这一方面的 XSS 注入进行讨论。
这里读者有个小小的疑问,为什么我要选网关劫持进行讨论?因为网关劫持可以大面积范围进行有效控制。
曾经,有这样一道风靡前端的面试题(当然我也现场笔试过):当你在浏览器地址栏输入一个URL后回车,将会发生的事情?其实本文不关心请求发到服务端的具体过程,但是我关心的时,服务端响应输出的文档,可能会在哪些环节被注入广告?手机、路由器网关、网络代理,还有一级运营商网关等等。所以,无论如何,任何网页都得经过运营商网关,而且最调(zui)皮(da)捣(e)蛋(ji)的,就是通过运营商网关。
另外, 也提醒大家,如果手机安装了一些上网加速软件、网络代理软件或设置网络代理 IP,会有安全风险,也包括公共场所/商家的免费 WIFI。
前端防火墙的实践
经过近一段时间通过对 zjcqoo 的《XSS 前端防火墙》六板斧的反复琢磨理解,基本上防御措施可以归为两大类:一种是从协议上屏蔽,一种是从前端代码层面进行拦截移除。通过 zjcqoo 提出的几种注入防御方式,进行几个月的实践观察,对广告注入方式大概可以归为两种:完全静态注入、先静态注入后动态修改(创建)。
1. 完全静态注入
完全内联 js、css、和 dom,不管是 body 内外,甚是恶心,而且如果是在监控脚本前面注入的,还可以抢先执行,造成防御不起作用。注入的 DOM 也无法清除。
2. 先静态注入后动态修改
这种可以分为几种:一种是异步请求接口数据再生成 DOM 注入,一种是修改 iframe 源地址进行引入,另外一种是修改 script 源地址,请求执行 js 再异步获取数据或生成 DOM。
监控数据观察分析
对 zjcqoo 提出的几种防御方式的实践,前一个月主要是花在优化检测脚本和增加白名单过滤脏数据方面,因为这块事情只能利用业余时间来搞,所以拖的时间有点久。白名单这块的确是比较繁琐,很多人以为分析下已知的域名就 ok 了,其实不然,云龙在这篇 iframe 黑魔法就提到移动端 Native 与 web 的通信机制,所以在各种 APP 上,会有各种 iframe 的注入,而且是各种五花八门的协议地址,也包括 chrome。
监控拿到的数据很多,但是,由于对整个广告注入黑产行业的不熟悉,所以,有必要借助 google 进行查找研究,发现,运营商大大地狡猾,他们自己只会注入自己业务的广告,如 4G 免费换卡/送流量/送话费,但是商业广告这块蛋糕他们会拱手让人?答案是不可能,他们会勾结其他广告代理公司,利用他们的广告分发平台(运营商被美名为广告系统平台提供商)进行广告投放然后分成…
对于用户投诉,他们一般都是认错,然后对这个用户加白名单,但是他们对其他用户还是继续作恶。对于企业方面的投诉,如果影响到他们的域名,如果你没有确凿的证据,他们就会用各种借口摆脱自己的责任,如用户手机中毒等等,如果你有确凿的证据,还得是他们运营商自己的域名或者 IP,否则他们也无法处理。他们还是一样的借口,用户手机中毒等等。
除非你把运营商的域名或 IP 监控数据列给他看,他才转变态度认错,但是这仅仅也是之前我们提到的流量话费广告,对于第三方广告代理商的广告,还是没法解决,这些第三方广告代理商有广告家、花生米、XX 传媒等等中小型广告商,当然也不排除,有的是“个体户广告商”。
从另一方面来看,由于使用的是古老的 http 协议,这种明文传输的协议,html 内容可以被运营商一清二楚地记录下来,页面关键字、访问时间、地域等用户标签都可以进行采集,说到这,你可能已经明白了一个事(隐私侵犯已经见怪不怪了)——大数据分析+个性化推荐,在 google 一查,运营商还真有部署类似于 iPush 网络广告定向直投这样的系统,而且广告点击率也出奇的高,不排除会定向推送一些偏黄色的图片或游戏。
另外,数据分析中发现一些百度统计的接口请求,也在一些 js 样本中发现百度统计地址,猜测很有可能是这种广告平台利用百度统计系统做数据分析,如定向投放用户 PV 统计,广告效果统计等等。
监控数据分析也扯这么多了,我们还是回来看怎么做防御措施吧!
防御措施介绍
全站 HTTPS + HSTS
开启 HTTPS,可以加强数据保密性、完整性、和身份校验,而 HSTS (全称 HTTP Strict Transport Security)可以保证浏览器在很长时间里都会只用 HTTPS 访问站点,这是该防御方式的优点。但是,缺点和缺陷也不可忽略。
互联网全站HTTPS的时代已经到来 一文已有详细的分析,加密解密的性能损耗在服务端的损耗和网络交互的损耗,但是移动端浏览器和 webview 的兼容性支持却是个问题,比如 Android webview 需要固件4.4以上才支持,iOS safari 8 以上也才支持,而 UC 浏览器目前还不支持。
而目前推动团队所有业务支持 HTTPS 难度也是相当高,部分 302 重定向也有可能存在 SSLStrip,更何况 UC 浏览器还不支持这个协议,很容易通过 SSLStrip 进行劫持利用,虽然运营商大部分情况下不会这么干,但是我还是坚定怀疑他们的节操。由于我国宽带网络的基本国情,短时间指望速度提升基本上不可能的,就算总理一句话,但哪个运营商不想赚钱?所以,业务性能的下降和业务安全,需要进行权衡利弊。
Content Security Policy(简称 CSP)
CSP 内容安全策略,属于一种浏览器安全策略,以可信白名单作机制,来限制网站中是否可以包含某来源内容。兼容性支持同样是个问题,比如 Android webview 需要固件4.4以上才支持,iOS safari 6 以上支持,幸运的是 UC 浏览器目前支持 1.0 策略版本,具体可以到 CANIUSE 了解。目前对 CSP 的使用仅有不到两周的经验而已,下面简单说说其优缺点。
缺点:
- CSP 规范也比较累赘,每种类型需要重新配置一份,默认配置不能继承,只能替换,这样会导致整个 header 内容会大大增加。
- 如果业务中有爬虫是抓取了外部图片的话,那么 img 配置要么需要枚举各种域名,要么就信任所有域名。
- 3. 移动端 web app 页面,如果有存在 Native 与 web 的通信,那么 iframe 配置只能信任所有域名和协议了。
- 4. 一些业务场景导致无法排除内联 script 的情况,所以只能开启 unsafe-inline
- 5. 一些库仍在使用 eval,所以避免误伤,也只能开启 unsafe-eval
- 6. 由于 iframe 信任所有域名和协议,而 unsafe-inline 开启,使得整个防御效果大大降低
优点:
- 通过 connect/script 配置,我们可以控制哪些 外部域名异步请求可以发出,这无疑是大大的福音,即使内联 script 被注入,异步请求仍然发不出,这样一来,除非攻击者把所有的 js 都内联进来,否则注入的功能也运行不了,也无法统计效果如何。
- 通过 reportUri 可以统计到攻击类型和 PV,只不过这个接口的设计不能自定义,上报的内容大部分都是鸡肋。
- object/media 配置可以屏蔽一些外部多媒体的加载,不过这对于视频播放类的业务,也会误伤到。
- 目前 UC 浏览器 Android 版本的客户端和 web 端通信机制都是采用标准的 addJavascriptInterface 注入方式,而 iPhone 版本已将 iframe 通信方式改成 ajax 方式(与页面同域,10.5 全部改造完成),如果是只依赖 UC 浏览器的业务,可以大胆放心使用,如果是需要依赖于第三方平台,建议先开启 reportOnly,将一些本地协议加入白名单,再完全开启防御。
总的来说吧,单靠 CSP 单打独斗显然是不行,即使完全开启所有策略,也不能完成消除注入攻击,但是作为纵深防御体系中的一道封锁防线,价值也是相当有用的。
前端防火墙拦截
前端防火墙显然适合作为第一道防线进行设计,可以预先对一些注入的内联 js 代码、script/iframe 源引用进行移除,同时对 script/iframe 源地址修改做监控移除。
基本设计逻辑大概如下:
详细的实现逻辑,参考zjcqoo 的《XSS 前端防火墙》系列文章。
缺点:
- 如果是在监控脚本执行前,注入的脚本已经执行,显然后知后觉无法起防御作用了。
- 一些 DOM 的注入显然无能为力。
优点:
- 可以针对 iframe 做一些自定义的过滤规则,防止对本地通信误伤。
- 可以收集到一些注入行为数据进行分析。
双剑合璧
即使是单纯的 DOM 注入,显然无法满足更高级功能的使用,也会使运营商的广告分发平台效果大打折扣。如果单独其中一种方式进行使用,也只是发挥了一招一式的半成功力,如果是双手互搏,那也可以发挥成倍的功力。
而前端防火墙再加上 CSP 安全策略,双剑合璧,则可以大大降低广告注入带来的负面效果,重则造成广告代码严重瘫痪无法运行:在监控脚本后注入广告脚本,基本上可以被前端防火墙封杀殆尽,即使有漏网之鱼,也会被 CSP 进行追杀,不死也残。
即使在监控脚本运行前注入,通过 CSP content-src 策略,可以拦截白名单域名列表外的接口请求,使得广告代码的异步请求能力被封杀,script-src 策略,也可以封杀脚本外链的一些外部请求,进一步封杀异步脚本引用,frame-src 策略无论先后创建的 iframe,一律照杀。
侥幸者躲过了初一,却躲不过十五,前端防火墙拍马赶到,照样封杀无误,唯一的路径只有注入 DOM 这一方式,别忘了,只要开启 img-src 策略配置,广告代码只剩下文字链。虽然是一个文字链广告,但点击率又能高到哪去呢?
如果你是 node 派系,小弟附上《辟邪剑谱》 helmet 一本,如果你的业务有涉及到 UCBrowser,更有《辟邪剑谱之 UC 版》helmet-csp-uc 。
所谓道高一尺魔高一丈,既然我们有高效的防御措施,相信他们不久也会探索出反防御方式,如此,我们也需要和这帮人斗智斗勇,一直等到 HTTP/2 规范的正式落地。