PortSwigger靶场之DOM XSS in document.write sink using source location.search通关秘籍

发布于:2025-09-01 ⋅ 阅读:(18) ⋅ 点赞:(0)

一、靶场描述

这个靶场在搜索查询的跟踪功能中,包含一个基于DOM的跨站脚本(DOM-based XSS)漏洞。

该漏洞的产生是因为网站使用了一个名为 document.write 的 JavaScript 函数,这个函数会把数据直接写入到页面中。而写入的数据来源于 location.search,也就是网站 URL 中问号 (?) 之后的部分,这部分内容是你可以完全控制的。

衍生一下,标签<img>是在在网页中插入图片的意思,主要属性包括:

  • src:图片的地址,必填,比如:src="example.jpg"
  • alt:图片无法显示时的替代文本
  • width、height:设置图片大小
<img src="logo.png" alt="网站LOGO" width="100" height="50">

其中:
<img src=xxx οnerrοr=" ">:当src="xxx" 是不存在或无法加载的资源时,浏览器会触发 onerror 事件,可以利用图片加载失败触发 JavaScript 执行

<img src=xxx οnlοad=" ">:当src="xxx" 是有效且能正常加载的资源时,浏览器会触发 onload 事件,可以利用图片加载成功触发 JavaScript 执行

我们访问/resources/images/tracker.gif可以访问

所以本靶场可以利用图片加载成功触发 JavaScript 执行通关,但是主要使用的是下面三、攻击思路,这种也是一种办法。

" onload="alert(1)"

当你的输入被拼接到原始代码中后,最终生成的HTML字符串变成了:

<img src="/resources/images/tracker.gif?searchTerms="" onload="alert(1)">

二、漏洞原理详解

1、基于DOM的跨站脚本 (DOM-based XSS):

  • 这是一种特殊的XSS攻击。与存储型和反射型XSS不同,DOM型XSS的攻击载荷(payload)不一定会发送到服务器。

  • 整个攻击过程发生在用户的浏览器端。具体来说,是页面的客户端JavaScript代码,在处理数据时不够安全,导致了漏洞。

  • 在这个靶场中,流程是这样的:

    a. 浏览器加载页面的合法JavaScript代码。

    b. 这段代码从URL中读取数据 (通过 location.search)。

    c. 代码没有对读取到的数据进行安全处理(过滤或编码),就直接使用 document.write 将其写入到页面的文档对象模型(DOM)中。

    d. 如果URL中包含了恶意脚本,这个脚本就会被写入页面并执行。

2、危险函数 (Sink):

document.write这是一个非常经典的导致DOM-XSS的函数。它会把传入的字符串当作HTML来解析并插入到文档流中。如果字符串里包含 <script> 标签,浏览器就会执行它。

3、数据来源 (Source):

location.search这是指URL中从 ? 开始的所有内容(查询字符串)。例如,在 http://example.com/search?query=apple 这个URL中, location.search 的值就是 ?query=apple。攻击者可以随意构造这个部分。

4、解决目标

要成功完成这个靶场,你需要构造一个特殊的URL。当这个URL被访问时,它能够触发DOM-XSS漏洞,并成功执行 alert 函数(即在浏览器中弹出一个警告框)。

三、攻击思路:

在输入框随便输入字符串,发现我们的输入被拼接到url,然后函数 document.write() 将从url中获取的search参数写入页面中

这是一段 JavaScript 代码,它的主要功能是跟踪用户在网站上的搜索行为,但它包含一个严重的安全漏洞。

1、代码详解

<script>
    // 定义一个名为 trackSearch 的函数,它接收一个参数叫 query
    function trackSearch(query) {
        // 使用 document.write 向页面写入一段 HTML 代码
        document.write(
            // 这段 HTML 是一个 <img> 图像标签
            // 图像的源(src)指向一个跟踪像素(tracker.gif)
            // 关键在于,它把用户输入的搜索词(query)作为参数拼接到了图像的 URL 后面
            '<img src="/resources/images/tracker.gif?searchTerms=' + query + '">'
        );
    }

    // 从当前页面的 URL 中获取名为 'search' 的参数值
    // 例如,如果 URL 是 https://example.com/?search=1
    // 那么 query 变量的值就是 '1'
    var query = (new URLSearchParams(window.location.search)).get('search');
    // 判断 query 是否存在 (即 URL 中是否有 'search' 参数)
    if (query) {
        // 如果存在,就调用上面定义的 trackSearch 函数,并将获取到的搜索词传进去
        trackSearch(query);
    }
</script>

2、功能总结

这段代码的目的是:

  1. 从当前页面的 URL 地址栏里,寻找一个名为 search 的参数 (例如: .../?search=关键词)。

  2. 如果找到了这个参数,就把它的值(也就是用户搜索的关键词)取出来。

  3. 然后,它会动态地在页面上创建一个看不见的图像(一个1x1像素的跟踪GIF)。这个图像的 URL 地址会把用户的搜索关键词作为 searchTerms 参数附加上去。

  4. 当浏览器尝试加载这个图像时,就会向服务器发送一个请求,服务器通过分析这个请求日志,就能知道用户刚刚搜索了什么关键词,从而实现搜索行为跟踪。

3、严重的安全问题 (DOM-based XSS)

这段代码最关键的问题在于它使用了 document.write() 函数来处理从URL中获取的用户输入,并且没有任何安全过滤

一个攻击者可以构造一个恶意的 URL,如下所示:

https://[网站地址]/?search="><script>alert('XSS')</script>

当用户访问这个 URL 时,代码的执行流程会变成这样:

  1. query 变量获取到的值是:"><script>alert('XSS')</script>

  2. trackSearch 函数被调用,document.write() 执行的内容就变成了:

    <img src="/resources/images/tracker.gif?searchTerms=""><script>alert('XSS')</script>">
    
  3. 浏览器在解析这段 HTML 时,会先闭合 <img> 标签,然后遇到 <script> 标签,就会立即执行里面的 JavaScript 代码,导致弹出一个警告框。

结论: 这段代码实现了一个简单的搜索跟踪功能,但由于直接将 URL 参数写入页面,导致了严重的基于DOM的跨站脚本(DOM-XSS)漏洞,允许攻击者在网站上执行任意脚本。

你需要将一个恶意的JavaScript载荷(payload)放在URL的查询字符串中。当页面上的脚本读取这个查询字符串并用 document.write 将其写入页面时,你的脚本就会被执行。

一个典型的攻击URL会类似这样:

https://......./?search=<script>alert('XSS')</script>

至此,成功通关。


网站公告

今日签到

点亮在社区的每一天
去签到