这段代码使用 document.location.toString() 是基于 DOM 的 XSS 漏洞吗?

信息安全 xss javascript dom jQuery
2021-08-21 21:25:01

我在多个 Web 应用程序中遇到了以下 JS 代码。我认为这个代码片段受欢迎的原因是这个公认的答案 SO开发人员似乎在使用这段代码很多切换菜单选项卡:

var url = document.location.toString();
if (url.match('#')) {
    $('.nav-tabs a[href="#' + url.split('#')[1] + '"]').tab('show');
}

它基本上在没有任何卫生条件的情况下读取document.location并传递 a 之后的任何内容。#$()

甚至 Burp Suite 的 Active Scanner 也将其报告为 True Positive。

在此处输入图像描述

我试图利用它,但这对我来说似乎是一个误报。我的假设是,由于 JS 将 URL 转换为字符串,因此任何有效负载(包括特殊字符)都将被视为字符串。

在这里发布这个只是为了确定你们是否可以想到任何其他方法来利用它来导致基于 DOM 的 XSS?

2个回答

此代码片段在 jQuery 1.9 之前(以及与 jQuery Migrate 插件结合使用)中易受 XSS 攻击。即使是现在,它至少仍然是一种不好的做法。

$()(shortcut for )的字符串参数jQuery()可以解析为 CSS 选择器或 HTML 代码。将字符串解析为 HTML 意味着存在 XSS 漏洞,就像那样document.write()另一方面,在当前浏览器中不能直接利用 CSS 选择器注入。

v1.9的变更日志解释了他们如何改变解析行为:

在 1.9 之前,如果字符串中的任何位置都有 HTML 标记,则字符串将被视为 HTML 字符串。这有可能导致无意中执行代码并拒绝有效的选择器字符串。从 1.9 开始,只有以小于 ("<") 字符开头的字符串才被认为是 HTML。Migrate 插件可用于恢复 1.9 之前的行为。

由于您的代码片段 ( '.nav-tabs a[href="#' + <payload> + '"]') 中的字符串不以 a 开头<,因此当页面运行当前版本的 jQuery 时,您将无法注入自己的代码。

但是,您仍然应该清理输出。有时,不同的模块(例如 Wordpress 插件)带有它们自己的 jQuery 库,可能会无意中覆盖较新版本并重新引入遗留行为。如果字符串不是字母数字或未包含在预定义链接列表中,则一个简单的解决方法是拒绝该字符串。location.hash

这是 jQuery 中非常常见的 XSS 攻击向量,并且仍然可以影响使用过时版本的 jQuery 的网站。

https://bugs.jquery.com/ticket/9521

基本上,如果一个字符串是一个无效的选择器,jQuery 会假定它是 HTML,并将其解析为 HTML。jQuery 版本 1.9 中, jQuery 通过仅将以 开头的字符串解析为 HTML 来减轻这种风险<,因此在现代 jQuery 中应该是不可能的。

不幸的是,许多网站仍然使用过时的 jQuery 版本(包括 Stack Exchange),由于字体图标库的 HTML 文件中的错误,它启用了半新的 WordPress XSS 攻击。