XSS 前端防火墙—内联事件拦截

发表于:2014-7-09 11:40  作者:邹菜头   来源:51Testing软件测试网采编

字体: | 上一篇 | 下一篇 |我要投稿 | 推荐标签:

  尽管按钮上直接绑了一个内联的事件,但事件模型并不买账,仍然得按标准的流程走一遍。capture,target,bubble,模型就是那样固执。
  不过,把那行注释的代码恢复,结果就只剩 capture 了。这个简单的道理大家都明白,也没什么好解释的。
  但仔细揣摩下,这不就是『主动防御』的概念吗?捕获程序运行在内联事件触发之前,并且完全有能力拦截之后的调用。
  上面的 Demo 只是不假思索拦截了所有的事件。如果我们再加一些策略判断,或许就更明朗了:
<button onclick="console.log('xss')">CLICK ME</button>
<script>
document.addEventListener('click', function(e) {
console.log('bubble');
});
document.addEventListener('click', function(e) {
var element = e.target;
var code = element.getAttribute('onclick');
if (/xss/.test(code)) {
e.stopImmediatePropagation();
console.log('拦截可疑事件:', code);
}
}, true);
</script>
Run
  我们先在捕获阶段扫描内联事件字符,若是出现了『xss』这个关键字,后续的事件就被拦截了;换成其他字符,仍然继续执行。同理,我们还可以判断字符长度是否过多,以及更详细的黑白名单正则。
  怎么样,一个主动防御的原型诞生了吧。
  不过,上面的片段还有个小问题,就是把事件的冒泡过程也给屏蔽了,而我们仅仅想拦截内联事件而已。解决办法也很简单,把 e.stopImmediatePropagation() 换成 element.onclick = null 就可以了。
  当然,目前这只能防护 onclick,而现实中有太多的内联事件。鼠标、键盘、触屏、网络状态等等,不同浏览器支持的事件也不一样,甚至还有私有事件,难道都要事先逐一列出并且都捕获吗?是的,可以都捕获,但不必事先都列出来。
  因为我们监听的是 document 对象,浏览器所有内联事件都对应着 document.onxxx 的属性,因此只需运行时遍历一下 document 对象,即可获得所有的事件名。
<img src="*" onerror="console.log('xss')" />
<script>
function hookEvent(onevent) {
document.addEventListener(onevent.substr(2), function(e) {
var element = e.target;
if (element.nodeType != Node.ELEMENT_NODE) {
return;
}
var code = element.getAttribute(onevent);
if (code && /xss/.test(code)) {
element[onevent] = null;
console.log('拦截可疑事件:', code);
}
}, true);
}
console.time('耗时');
for (var k in document) {
if (/^on/.test(k)) {
//console.log('监控:', k);
hookEvent(k);
}
}
console.timeEnd('耗时');
</script>
Run
  现在,无论页面中哪个元素触发哪个内联事件,都能预先被我们捕获,并根据策略可进可退了。

32/3<123>

评 论

论坛新帖

顶部 底部


建议使用IE 6.0以上浏览器,800×600以上分辨率,法律顾问:上海瀛东律师事务所 张楠律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2020, 沪ICP备05003035号
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪公网安备 31010102002173号

51Testing官方微信

51Testing官方微博

扫一扫 测试知识全知道