jQuery(location.hash) 可以实现 XSS 吗?

信息安全 xss jQuery
2021-08-18 18:14:58

是否可以在以下代码中利用 XSS?

jQuery(window.location.hash)

在我看来,window.location.hash总是以 hash 开头#,而现代 jQuery 总是将其解释为 ID 选择器。这个对吗?

4个回答

是的,有可能对jQuery(window.location.hash). 请参阅此存档的博客文章,该文章在对另一个 SE 问题的答案的评论中被提及。可以进行 CSS 定时攻击,如博客文章中所述:

如果我们执行选择器*:has(:has(:has(*)) :has(*) :has(*)) input[name=authenticity_token][value^='x'],只有authenticity_token以'x'开头时才会花费很长时间。

恶意站点可以在 iframe 中打开目标站点并查看选择器是否需要很长时间才能匹配。如果input[name=authenticity_token][value^='x']不匹配,选择器将被短路,jQuery 不会检查更昂贵:has(...)的 s。

正如博文中提到的,如果它在同一进程中运行两个站点的浏览器中运行,则可以轻松测量调用受害站点的站点的延迟。(在我看来,即使使用单独的进程,甚至可能会发生定时攻击,因为即使进程是单独安排的,它通常也会减慢计算机的速度。一般来说,写这样的任何页面都可能会出现问题它可能会根据 URL 中的某些内容是否与秘密字符串匹配进行大量处理。)

几年前的补丁952111290试图缓解这个问题,尽管没有声称完全消除 XSS 的可能性。我一直在 jQuery 2.x 中运行一些他们声称仍然存在的漏洞,但它们似乎没有工作,所以我不能肯定地确认和否认你提供的代码是否足以被利用。

对于它的价值,如果你对 jQuery 对象做一些事情,这个漏洞也有可能发生。假设您允许客户提交 HTML,并且客户提交了以下内容:

<div id="xss">alert('xss');<div>

由于某些疯狂的原因,您在显示此 HTML 的页面上有以下代码:

eval(jQuery(window.location.hash).text());

的 URL 哈希#xss会导致触发警报。

所以我可以确认这是可能的,尽管如果不专门编写易受攻击的代码,很难利用这种特殊方式。

我建议在window.location.hash将其传递给 之前对 的值进行验证检查或去除特殊字符jQuery(),并且一如既往地考虑您对 jQuery 对象的操作。

为什么要猜测?只需先用 \w 对其进行消毒,这很容易。如果他们完全控制了 jQuery 行,即使它必须以哈希开头,这似乎是非常可怕的。用鹅的联动9521的话来说

我想问题是这是否是一个如此常见的愚蠢举动,以至于我们需要在这种情况下将 id 选择器优先于 HTML。我可以被说服。

但是,我不确定我们通常如何防止这种情况发生。井号只是文本,字符串是有效的 HTML。用户不应将不受信任的输入传递给可能包含脚本的 $()。

因此,至少有一位 jQuery 开发人员表示,这甚至根本不被视为漏洞——他想让程序员不要这样做。即使您现在不添加它,以后的维护者也可能会注意到这一点并添加window.location.hash.replace(/[^\w]/g, ""). (或者[^\w-]如果您使用连字符)。避免它并没有真正拯救它。当然他们可以减轻它,但我不会让这种态度成为您网络安全背后的主导力量。

我对用户输入的首选是顶部的一个特殊 JS 文件,它处理所有清理输入,并将诸如 window.location.hash 之类的内容存储在已经清理的“UserHash”变量中,并记录了清理,以便其他人知道他们可以假设什么. 我发现不这样做将不可避免地导致以后出现漏洞。有人会认为“哦,这里很安全,所以这里也很安全”,从而使处于半安全边缘的事物陷入了实际的漏洞。

正如 Goose 的回答所提到的,似乎有一些早期版本的 jQuery 容易受到此攻击。

由于 jQuery 函数可以像这样将字符串转换为 DOM 元素...

$(‘<p>Something</p>’);

如果您的代码有:

$(location.hash);

攻击者导致您使用以哈希片段结尾的特制 URL 访问您的页面,例如:

#p=<img src%3D/%20onerror%3Dalert(1)>

然后 jQuery 会将散列解释为 HTML,创建必要的 DOM 元素,并在此过程中实际执行附加到它们的任何 JS 处理程序。

jQuery 的未来版本似乎通过优先考虑 ID 选择器而不是 HTML 来缓解这种情况,因此任何以散列开头的东西都被视为 CSS 选择器,而不是 HTML。