XSS vs CSRF
区分 XSS 与 CSRF 的攻击边界:XSS 让不可信数据进入目标站点的可执行上下文,CSRF 则诱导浏览器携带用户已有身份发出非预期跨站请求;二者的成立条件与主要防御不同。
#synthesis
#growing
#security
#browser
[!info] related notes
- 所属 MOC: 安全 MOC
- 对比对象: XSS 跨站脚本攻击, CSRF
- 相关边界: Same-Origin, SameSite, CSP 内容安全策略
XSS vs CSRF
为什么要一起理解
XSS 和 CSRF 都发生在 Web 安全边界里,也都可能“以用户身份造成损害”,但它们利用的机制不同。
最短模型:
XSS
= 攻击者的内容进入目标站点执行上下文
= Data → Code Boundary 被突破
CSRF
= 攻击者诱导浏览器向目标站点发请求
= 浏览器自动携带已有身份
核心差异
| 维度 | XSS | CSRF |
|---|---|---|
| 攻击核心 | 不可信数据被当成活动内容 / 代码执行 | 非预期请求借用了用户已有认证状态 |
| 攻击代码运行在哪里 | 通常进入目标站点 origin 的页面执行上下文 | 可由攻击者站点发起,不要求获得目标站点脚本执行权 |
| 主要依赖 | 危险 sink、错误转义/净化、可执行内容边界 | 浏览器自动携带 Cookie 等凭证 + 缺少防伪造校验 |
| 典型后果 | 读页面数据、发请求、篡改 UI、窃取脚本可读凭证 | 触发用户并未主动发起的状态修改请求 |
| 主要防御 | 上下文转义、避免危险 sink、sanitization、CSP | SameSite、CSRF Token、Origin/Referer 校验、重新认证等 |
为什么 XSS 往往比 CSRF 获得更强的页面能力
如果攻击者已经在目标 origin 内执行脚本,脚本通常可以:
- 读取页面中 JavaScript 可访问的数据;
- 调用目标站点自己的 API;
- 操作 DOM;
- 模拟大量用户行为。
因此,单纯加 CSRF Token 并不能“修复 XSS”:同源执行的恶意脚本往往可以读取页面已经能够读取的 Token,再发合法形态请求。
为什么 Bearer Header 会改变 CSRF 条件
经典 CSRF 高度依赖“浏览器自动携带认证凭证”。
如果凭证只能由应用 JavaScript 主动加入:
Authorization: Bearer ...
攻击者站点不能仅靠普通跨站表单、图片或导航让浏览器自动附上该自定义 Header,因此经典 Cookie 型 CSRF 条件会发生变化。
但这不意味着“把 Token 放 localStorage 就更安全”:
- CSRF 风险可能下降;
- XSS 直接读取 Token 的风险可能上升。
认证存储要按完整威胁模型选择。
两者可以同时出现
它们不是互斥漏洞。
例如:
- 站点存在存储型 XSS;
- 恶意脚本在目标 origin 执行;
- 脚本直接调用敏感接口。
此时攻击已超出经典 CSRF 的“跨站诱导请求”模型。
判断口诀
遇到攻击场景先问:
攻击者是否让自己的内容进入目标站点执行上下文?
→ 是:优先按 XSS / 注入边界分析
攻击者是否主要依赖浏览器自动携带用户凭证发跨站请求?
→ 是:优先按 CSRF 分析
学习检查
不看正文回答:
- XSS 与 CSRF 分别突破了什么边界?
- 为什么“都有 Cookie”不能说明它们是同一种攻击?
- CSRF Token 为什么能防经典 CSRF,却不能作为 XSS 的主要防线?
- HttpOnly Cookie 对 XSS 和 CSRF 分别有什么作用与局限?
- Bearer Token 放自定义 Header 后,经典 CSRF 条件为什么会变化?
- 为什么 localStorage Token 不能简单归纳成“比 Cookie 更安全”?
- 给一个恶意评论执行脚本和一个恶意网页自动提交转账表单的案例,分别判定攻击类型并说明证据。