使用 JavaScript 防止 JavaScript 执行?

信息安全 Web应用程序 xss javascript 攻击预防
2021-09-07 17:08:00

在对这个处理 XSS 预防的问题发表评论时,@dandavis 建议:

如果您的脚本首先运行,则很容易破坏以下脚本

这个想法是为不支持 CSP 的浏览器提供一个回退,以防止(内联)JavaScript。

我知道可以覆盖现有函数,但我不清楚这究竟是如何工作的。是否有一个简单的解决方案可以 100% 阻止任何进一步的脚本执行?如果没有,是否有适用于大多数情况或大多数浏览器的解决方案(以及为其他上下文/浏览器绕过它们的方法)?

3个回答

这个想法是为不支持 CSP 的浏览器提供一个回退,以防止(内联)JavaScript。

请记住,CSP 不能用作第一道防线。您应该对每个上下文进行正确编码,以防止应用程序中出现 XSS。OWSAP 对此有很好的信息。

话虽如此,如果在您的应用程序中发现并利用 XSS 漏洞(即页面某处的错误或没有编码),CSP 可以成为使 XSS 不那么严重的一个很好的后备方案。

我知道可以覆盖现有函数,但我不清楚这究竟是如何工作的。

这很容易做到。例如XMLHttpRequest = myFunction, 或XMLHttpRequest = null会阻止脚本XMLHttpRequest直接使用。

问题是,如果攻击者可能没有使用该特定功能,并且如果攻击者知道您正在这样做,他可以轻松使用替代方法。虽然可能会覆盖所有功能,但不建议将其作为可靠的解决方案。

是否有一个简单的解决方案可以 100% 阻止任何进一步的脚本执行?

如果您的 . 中有语法错误<script>,那么其中的任何内容都<script>...</script>不会运行。不幸的是,使用 XSS,攻击者可以很容易地启动一个<script>可以正常工作的新程序。

除此之外,还有很多注入 JavaScript 的方法<script>,例如<img onload>onerror.

据我所知,您无法可靠地阻止所有后续 HTML 包含 XSS 执行。

如果没有,是否有适用于大多数情况或大多数浏览器的解决方案(以及为其他上下文/浏览器绕过它们的方法)?

CSP 版本 1 浏览器支持开始变得很好,并且由于 CSP 被设计为无论如何都作为备份(不是第一道防线),您可能可以在那里停止搜索,因为您知道浏览器支持将是一个缩小的问题。

话虽如此,我认为覆盖函数的想法可能对成功大有帮助。从理论上讲,这似乎可以可靠地工作虽然不建议这样做,但我认为这将是一项有趣的研究。我想知道实现起来会有多复杂。

 是否有一个简单的解决方案可以 100% 阻止任何进一步的脚本执行?

不,我不这么认为。每个脚本标签都是独立运行的,因此抛出错误不会停止下一个脚本。alert和公司,也许是同步 AJAX 来防止进一步的脚本运行,但这会锁定整个浏览器。

如果没有,是否有适用于大多数情况或大多数浏览器的解决方案(以及为其他上下文/浏览器绕过它们的方法)?

好吧,您可以尝试通过遍历 window.properties 来清空所有全局变量。然后理论上脚本将无权访问 DOM 来做任何事情。实践中,这可能不会很好地工作,因为并非所有这些属性都是可写的。我怀疑是否有可能删除所有感兴趣的内容。

其他可能的黑客攻击可能是在其他脚本运行之前尝试破坏文档,也许是通过document.write某种方式使用。这将是在未定义的行为和龙的土地上。

代码示例:

每个人都喜欢一个好的代码示例,所以这里是一个我认为很难被击败的示例有效负载。

<iframe name="iwin"></iframe>
<script>
(function() {
    // Due to the name attribute on the iframe, iwin is now
    // an implicit global for the iframe's contentWindow.
    // It should not have been there before the tag was parsed,
    // and the name could be randomized.

    // For legacy IE, to make globals accessible (0_o).
    iwin.execScript && iwin.execScript();

    // PWND, we have new globals.
    var XMLHttpRequest = iwin.XMLHttpRequest;
})();
</script>

我在写该评论时考虑到了 jQuery,因为它很容易意外中断。由于大多数复杂的客户端代码(带有向量的那种)都使用 jQuery,因此导致漏洞的常见 ajax 和模板根本无法在没有它的情况下运行。

JavaScript 的安全模型是基于引用的,这意味着如果你无法触及某些东西,那么它就不存在于代码中。有几个出乎意料的引用,例如constructor.constructor("alert(666)")(),但它们是易于管理的,因为 JS 根本没有提供那么多内置函数(与 php 或 .net 的 lib 相比)。如果您可以隐藏或销毁引用,则删除该功能。道格·克罗克福德( Doug Crockford )对此进行了很多讨论,并且在"use strict"模式中,它在粒度级别上更具可执行性。

  • 您最好重定向到没有脚本标签的页面;非 js 或“lofi”版本(如果有)。

  • 您可以使用带有属性的 100% 大小的 iframesandbox来重新提供没有脚本的页面;我有一个用于兼容性测试的书签(只需制作一个新的 iframe,调整大小并将其设置.srclocation.href)。并非所有浏览器都支持sandbox,因此如果您的目标是减少某种被忽视的 XSS,那么您可能是在抢彼得付钱给保罗。

  • window.stop() 在某些浏览器中工作(肯定是 FF),并且使用它来停止页面加载就地很简单。

  • “把它们都烧掉”;破坏所有内置的全局属性,只留下语言的纯逻辑功能。缺点是document不可修改,这是聪明的对手真正需要的。可能有一种简单的方法来破坏document,但它是一个巨大的向量。