应用 onload 事宜监控跨站资本

说到跨站资本监控,首先会联想到『Content Security Policy』。既然 CSP 好用,我们何须本身再搞一套呢。那就先来吐槽下 CSP 的缺点。

现在的 CSP

日记不细致

用过 CSP 的都很忧郁,上报的只需违规的站点名,却没有详细途径。这是缺点,照样特地的设想?

明显,CSP 是为平安定制的,内里的范例天然要严厉制订,不然就会带来新的平安题目。如果支撑细致途径的上报,那又会引出什么题目?

因为 CSP 会上报一切的要求,以至包含重定向的,因而可以用来探测重定向后的地点。如果已登录的用户接见 login.xx.com 会重定向到 xx.com/username,那末进击者设想一个只允许重定向前的划定规矩的页面,用户接见后,重定向后的 URL 就会当作违规地点上报给进击者,这个中就包含了用户名。

如果支撑细致途径的上报,这简直就是灾害,就用来探测的用户隐私信息了。事实上现在只上报主机名,都能举行一些应用,比方这篇 Using Content-Security-Policy for Evil

不过新的范例总是在革新,将来也许只上报重定向前的 URL。但在这之前,我们只能吸收这些鸡肋的上报日记。

划定规矩不天真

CSP 现在只支撑白名单列表,这若干有些枯燥。

更糟的是,差别划定规矩之间没法继承和同享。比方默许有个 default-src 划定规矩,但其他的划定规矩会掩盖它,而不是继承它。这就致使各个划定规矩之间,涌现许多的重复,使得全部字符串变的冗杂。

没法和页面交互

CSP 的监控和上报,是在浏览器背景自动处置惩罚的,没有供应一个事宜供页面举行交互。

如许就只能运用一致体式格局强迫处置惩罚了,而没法交给页面剧本,更好的来自定义处置惩罚。

上报体式格局不可控

如果处置惩罚体式格局有多种挑选,那末一致处置惩罚也无可厚非。

但事实上 CSP 的上报体式格局及花样,没有任何可选余地。只能运用 POST + JSON 的体式格局提交,而且个中的字段异常累坠,以至把划定规矩里的白名单列表也发上来了。

另外,也没法设定一个缓存时候,掌握重复上报的距离。在设置白名单脱漏时,会涌现大批的误报,严峻斲丧资本。

糟蹋带宽

在较新的 Chrome 里,可以运用 meta 标签在前端页面定义 CSP 划定规矩,但其他浏览器现在仍不支撑。

为了可以一致,大多仍运用 HTTP 头部输入的体式格局。因为划定规矩平常都很长,致使每次页面接见,都邑分外增添数百字节。

保护烦琐

如果是经由过程 Web 效劳开启的,那末每次调解战略,都得修正设置以至重启效劳,异常贫苦。

兼容性不高

现在只需高版本的浏览器支撑,而 IE 系列的则险些都没能很好的支撑。

如果某些进击只争对低版本的浏览器,那末很有能够涌现大批脱漏。

模仿的 CSP

道理

事实上在 CSP 涌现的好几年前,就有一个可以监控跨站资本的计划,下面就来分享下。

写过 JS 的都晓得,如果需要给大批元素监听事宜,无需对每一个元素上都举行绑定,只需监听它们的容器即可。当详细的事宜冒泡到容器上,经由过程 event.target 即可获知是哪一个元素发生的。

剧本、图片、框架等元素加载完成时,都邑发生 onload 事宜;而一切元素都位于『文档』这个顶级容器。因而我们监听 document 的 onload 事宜,即可获知一切加载资本的元素。

不过 onload 这个事宜比较特别,没法经由过程冒泡的体式格局来监听。但在 DOM-3 规范模子里,事宜另有一个『捕捉』的观点,这也是为何 addEventListener 有第三个参数的缘由。

我们经由过程事宜捕捉机制,将其拿下,从而监控文档级别的全局 onload 事宜。



<script> document.addEventListener('load', function(e) { console.log(e.target); }, true); </script> <script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script> <iframe src="http://www.baidu.com/"></iframe>

《应用 onload 事宜监控跨站资本》

相似的,如果资本加载失利,会触发 onerror 事宜。我们也可同时将其捕捉,跟踪那些临时不可用的跨站资本。

上风

经由过程剧本的体式格局,就可以更天真的处置惩罚题目了。划定规矩的是非名单,上报体式格局、花样等等,都可以本身来定义。最主要的是,我们可以取得细致的违规 URL 了!

比拟后端设置,前端剧本更新保护起来轻易的多。而且得益于浏览器缓存,无需每次更新设置,节约许多资本。

加强

也许你已发现了,这只能完成 CSP 的 Report-Only 功用,基础没法举行阻拦。而且其他的内联事宜、网络通信等也没有触及。

不过本文的主题已说了,只是监控跨站资本罢了,并不阻拦。事实上,如果可以做到实时发现题目,就很不错了。

如果非得经由过程 JS 来完成阻拦功用,可以参考之前的『XSS 前端防火墙系列』:

虽然可以更严厉的防护,但完成起来更痴肥,机能开支也更大。如果阻拦了平常的营业功用,形成的丧失会更大。

而运用怎样这个小技能,只需几行代码即可完成,机能斲丧忽略不计。

缺点

固然,那末简朴的计划肯定没法周全。

因为我们只监听文档容器,有些还未加入到文档的元素发生的事宜,我们就没法捕捉到了。最典范的就是:

new Image().src = '...'

虽然建立的 HTMLImageElement 对象具有 onload 事宜,然则此时还只是一个离屏元素,事宜就没法对外流传了。

如果非得处理,只能经由过程函数钩子的体式格局监控 URL。

另外,IE9 以下的浏览器不支撑 DOM-3,而 attachEvent 是没法设置捕捉的,因而我们还需一个后备计划。毕竟国内低版本 IE 用户仍有不少,纵然能完成部份功用,也胜于无。

后备

事实上,纵然主流浏览器,有些特别元素并没有 onload 事宜,比方 Flash 插件。

为了填补这些不足,同时尽量坚持简朴高效,我们运用定时轮询的体式格局,对特定元素举行扫描。这里运用一个人人都晓得,但未必都清晰的要领:document.getElementsByTagName。

这个功用都晓得,但返回的范例也许很少揣摩。他返回的并非一个 Array,也不是 NodeList,而是 HTMLCollection。

W3C 范例形貌中,有一个显眼的词 『live』,已道出了这个接口的奇特的地方——它是一个动态的鸠合,能跟着容器内元素的增减而变化。

《应用 onload 事宜监控跨站资本》

因而,我们事前映照出文档容器内的元素,以后即可随时查询鸠合了。

<button id="btn">Load Script</button>


<div id="stat"></div>




<script>
    function log(str) {
        var line = document.createElement('div');
        line.innerHTML = str;
        stat.appendChild(line);
    }

    var colScript = document.getElementsByTagName('script');

    setInterval(function() {
        var display = [];

        for (var i = colScript.length - 1; i >= 0; i--) {
            var el = colScript[i];
            if (el.src) {
                // check url
                display.push(el.src);
            }
        }
        log('num: ' + display.length + ' list:' + display.join(',') );
    }, 1000);

    // [test] load script
    btn.onclick = function() {
        var el = document.createElement('script');
        el.src = 'http://libs.baidu.com/jquery/1.9.0/jquery.js';
        document.body.appendChild(el);
    }
</script>



《应用 onload 事宜监控跨站资本》

除了 SCRIPT,我们还可以监控一切存在风险隐患的元素,比方:EMBED,OBJECT,IFRAME 等等。如许纵然是低版本的 IE 用户,也能介入预警上报了,比起完整没有好的多。

固然,这类简朴要领也很轻易被绕过。如果剧本删除了本身元素,那末我们就没法跟踪到了。而剧本一旦运转就已在内存里,纵然元素节点被移除,依然能继承运转。

不过,关于平常的状况也充足应对了。平常运转商的广告挟制,大多都很落伍。纵然要举行后期匹敌,也可以应用之前的前端防火墙,运用严厉的计划。

扩大信息

见过 CSP 日记的大多都邑很疑心,涌现的这些违规资本,终究位于页面那边。因为没有确实的细节,给排查事情带来很大难题。

毕竟,绝大多数的上报题目,都是没法复现的。它们要么是运转商的广告,或者是浏览器插件。难很经由过程这些日记,来定位题目地点。

既然现在运用本身的剧原本完成,理应带上一些有意义的信息。除了资本范例和细致 URL,我们还需要一个可以定位题目地点的参数——DOM 途径。

《应用 onload 事宜监控跨站资本》

将每层元素的 #id 和 .class 追随标署名,获得一个规范的 CSS 挑选器。经由过程它,即可异常轻易的定位到违规元素,同时也能用于统计和剖析。

比方涌现顶级元素就是 SCRIPT 的,明显这是一个被插进去到 <html> 以外的剧本,很有能够就是运营商注入的广告剧本。

比方涌现 HTML > BODY > ... > DIV.editor-post > SCRIPT 如许帖子容器里的剧本,那末极有多是涌现 XSS 了。平常状况下,用户内容地区并不会涌现剧本元素。

《应用 onload 事宜监控跨站资本》

经由过程细致的上报日记不断学习,后端即可愈来愈精准的剖析出题目地点。

而这些,现在的 CSP 难以完成。

上报体式格局

吸收 CSP 报告的不足的地方,我们运用更天真的体式格局。

关于运营商广告那样的跨站资本,重复上报一样的信息,是毫无意义的,只会糟蹋带宽资本。关于统一类正告,肯定时候内上报一次就后够了。

应用 URL、DOM 途径等信息,可以更轻易的将日记举行客户端去重。经由过程当地存储的纪录,就没必要每次都上报了,在当地纪录违规的次数即可。

关于不严峻的正告,当地也可以累计到肯定的数目再上报。如许多条日记一次发送,即可大幅减轻后端压力。以至还可以斟酌紧缩内容,节约网络带宽。

只需让前端举行负载保护,才不至于大规模布置的场所下,吸收端被海量的误报日记拖垮。

总结

只管 CSP 的初志很优美,但到现在,仍只是能用,并没有做到好用。因而,现实面对的题目,照样得靠本身来处理。

固然,规范的制订原本就是受益于群众的,我们也愿望 CSP 规范能生长的愈来愈好用。

转自:应用 onload 事宜监控跨站资本

    原文作者:小马快跑
    原文地址: https://segmentfault.com/a/1190000002529224
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞