【前端安全】JavaScript防http劫持与XSS


作为前端,一直以来都知道HTTP劫持XSS跨站脚本(Cross-site scripting)、CSRF跨站请求伪造(Cross-site request forgery)。但是一直都没有深入研究过,前些日子同事的分享会偶然提及,我也对这一块很感兴趣,便深入研究了一番。httphijack.js ,欢迎感兴趣看看顺手点个 star ,本文示例代码,防范方法在组件源码中皆可找到。

接下来进入正文。

可以戳我查看DEMO。(打开页面后打开控制台查看 console.log) 

点击图中这几个按钮,可以看到如下:

这里我们用到了黑名单匹配,下文还会细说。

可以戳我查看DEMO。(打开页面后打开控制台查看 console.log)

 是页面加载一开始就存在的静态脚本(查看页面结构),我们使用 MutationObserver 可以在脚本加载之后,执行之前这个时间段对其内容做正则匹配,发现恶意代码则 removeChild() 掉,使之无法执行。

MDN ,第一句就是:

该特性已经从 Web 标准中删除,虽然一些浏览器目前仍然支持它,但也许会在未来的某个时间停止支持,请尽量不要使用该特性。

虽然不能用,也可以了解一下:

document.addEventListener('DOMNodeInserted', function(e) {
  var node = e.target;
  if (/xss/i.test(node.src) || /xss/i.test(node.innerHTML)) {
    node.parentNode.removeChild(node);
    console.log('拦截可疑动态脚本:', node);
  }
}, true);

然而可惜的是,使用上面的代码拦截动态生成的脚本,可以拦截到,但是代码也执行了:DOMNodeInserted 顾名思义,可以监听某个 DOM 范围内的结构变化,与 MutationObserver 相比,它的执行时机更早。

但是 DOMNodeInserted 不再建议使用,所以监听动态脚本的任务也要交给 MutationObserver

可惜的是,在实际实践过程中,使用 MutationObserver 的结果和 DOMNodeInserted 一样,可以监听拦截到动态脚本的生成,但是无法在脚本执行之前,使用 removeChild 将其移除,所以我们还需要想想其他办法。

可以戳我查看DEMO。(打开页面后打开控制台查看 console.log)

重写 Element.prototype.setAttribute ,就是首先保存原有接口,然后当有元素调用 setAttribute 时,检查传入的 src 是否存在于白名单中,存在则放行,不存在则视为可疑元素,进行上报并不予以执行。最后对放行的元素执行原生的 setAttribute ,也就是 old_setAttribute.apply(this, arguments);

上述的白名单匹配也可以换成黑名单匹配。

CSP

《web前端黑客技术揭秘》

  • XSS 前端防火墙系列1~3
  • 【HTTP劫持和DNS劫持】实际JS对抗
  • 浅谈DNS劫持
  • HTTP Request Hijacking
  • 使用 Javascript 写的一个防劫持组件,已上传到 Github – httphijack.js,欢迎感兴趣看看顺手点个 star ,本文示例代码,防范方法在组件源码中皆可找到。

    另外组件处于测试修改阶段,未在生产环境使用,而且使用了很多 HTML5 才支持的 API,兼容性是个问题,仅供学习交流。

    到此本文结束,如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。