PortSwigger靶场之 DOM XSS in innerHTML sink using source location.search通关秘籍
一、分析题目
这个靶场的目的是让你利用一个位于博客搜索功能中的 DOM 型 XSS (DOM-based Cross-Site Scripting) 漏洞。
它的工作原理和我们上一偏博客遇到的靶场类似,但关键技术细节有所不同:
-
漏洞类型: 仍然是 DOM 型 XSS。攻击发生在用户的浏览器中,由客户端的 JavaScript 代码处理不当引起。
-
数据来源 (Source): 和之前一样,是
location.search
。这意味着不安全的数据来自于 URL 的查询字符串(?
后面的部分),你可以完全控制这部分内容。 -
危险函数 (Sink): 这次不再是
document.write
,而是innerHTML
。-
innerHTML
是一个 DOM 元素的属性,JavaScript 可以用它来设置或获取某个元素(在这个靶场里是一个元素)内部的 HTML 内容。当脚本把一个包含 HTML 标签的字符串赋值给
element.innerHTML
时,浏览器会解析这个字符串并据此生成 DOM 节点。漏洞点:如果将未经过滤的用户输入(比如你的搜索词)直接赋值给
innerHTML
,你输入的恶意 HTML(包括脚本)就会被插入到页面中并可能被执行。总结一下: 这个靶场的场景是,你在搜索框输入内容后,页面上的某段 JavaScript 会获取你输入的词(从 URL 中),然后使用
innerHTML
将类似 “您搜索的结果是:[你的输入]” 这样的内容显示在页面的一个区域里,从而造成了 XSS 漏洞。
二、解决方法
你的目标是构造一个 URL,将恶意的 JavaScript 载荷(payload)放在 URL 的查询参数中,当页面加载时,这段载荷被
innerHTML
写入页面并执行alert()
函数。// 定义一个函数,名为 doSearchQuery function doSearchQuery(query) { // 找到页面上 ID 为 \"searchMessage\" 的元素 // 然后,把这个元素的内部 HTML 内容 (innerHTML) 设置为你传入的 query 值 document.getElementById(\'searchMessage\').innerHTML = query; } // 从当前 URL 中获取名为 \'search\' 的参数值 var query = (new URLSearchParams(window.location.search)).get(\'search\'); // 如果参数存在 if (query) { // 就调用上面的函数,把参数值传进去 doSearchQuery(query); }
这段代码就是漏洞的根源! 它会从 URL 中获取你的输入,然后不经过任何安全处理,直接使用
innerHTML
将其写入到页面中。整个攻击流程总结
-
你在浏览器(或通过 Burp Suite)发起了攻击请求,URL 中包含了恶意 payload:
.../?search=\">alert(1)
。 -
服务器响应,将包含那段有漏洞的 JavaScript 代码的页面返回给浏览器。
-
浏览器执行 JavaScript:
-
浏览器运行红框里的脚本。
-
脚本从 URL 中读取到
search
参数的值,也就是你的恶意 payload\">alert(1)
。 -
doSearchQuery
函数被调用,执行innerHTML = \'\">alert(1)\'
。 -
浏览器将你的恶意字符串当作 HTML 解析并插入到页面中,导致
alert(1)
被执行。
-
-
攻击成功:页面上弹出一个警告框。
但是关键点在于在这里直接使用
alert(1)
未成功成功。因为出于安全考虑,许多现代浏览器阻止通过innerHTML
插入的标签执行。
因此,我们需要使用其他方式来执行 JavaScript,最常用的方法是利用 HTML 事件处理器。
推荐的攻击载荷 (Payload):
一个非常可靠且经典的 payload 是使用
标签和它的onerror
事件:这个 Payload 是如何工作的?
-
: 浏览器会尝试加载一个来源地址为x
的图片。 -
加载失败: 因为
x
并不是一个有效的图片地址,所以加载必定会失败。 -
触发
onerror
事件: 图片加载失败会触发onerror
事件。 -
执行脚本:
onerror
事件中包含的 JavaScript 代码alert(1)
就会被执行。
三、具体步骤:
-
找到靶场中用于搜索的 URL 参数即
search
。 -
将上述的 payload 作为
search
参数的值附加到 URL 后面。 -
构造最终的攻击 URL:
https://[靶场地址]/?search=
-
在浏览器中访问这个 URL。如果页面弹出了警告框,我们成功解决了这个靶场。
四、成功通关
-