← [ BACK_TO_NOTES ]

CSRF

CSRF 的攻击原理、成立条件与常见防御方案说明

#frontend #growing #concept #browser

[!info] related notes

CSRF

Overview

  1. 用户输入账号信息请求登录A网站。
  2. A网站验证用户信息,通过验证后返回给用户一个cookie
  3. 在未退出网站A之前,在同一浏览器中请求了黑客构造的恶意网站B
  4. B网站收到用户请求后返回攻击性代码,构造访问A网站的语句
  5. 浏览器收到攻击性代码后,在用户不知情的情况下携带cookie信息请求了A网站。此时A网站不知道这是由B发起的。那么这时黑客就可以进行一下骚操作了!

第3,4步细节

hacker 网站构造代码样例

<img src="https://bank.com/transfer?toAccount=hacker&amount=10000" width="0" height="0" />

浏览器原生支持跨站资源访问,当访问 hacker 网站时,浏览器看到资源地址,就会自动向该服务器发起请求。并且浏览器会自动看是否存在对应网址的 cookie,有的话自动发送。SameSite 决定跨站场景下这个自动携带是否允许。

网络安全相关

挖掘:

  1. 抓取一个正常请求的数据包,如果没有Referer字段和token,那么极有可能存在CSRF漏洞
  2. 如果有Referer字段,但是去掉Referer字段后再重新提交,如果该提交还有效,那么基本上可以确定存在CSRF漏洞。
  3. 利用工具进行CSRF检测。如:CSRFTESTER,CSRF REQUEST BUILDER等

CSRF 攻击成功的三个必要条件

黑客要成功实施 CSRF 攻击,必须同时满足以下条件:

  • 目标网站的接口存在漏洞: 接口完全依赖 Cookie 进行身份验证,且没有其他防伪造措施。
  • 用户处于登录状态: 用户刚刚登录过目标网站,且 Cookie 尚未过期。
  • 能猜出请求的所有参数: 如果转账接口除了需要 toAccount 和 amount,还需要一个用户每次都必须手动输入的支付密码,那 CSRF 就会失败,因为黑客所在的 evil.com 无法读取 bank.com 的数据(受同源策略保护),自然猜不到密码。

防御

  • 验证 HTTP Referer 字段:在 HTTP 头中有一个字段叫 Referer,它记录了该 HTTP 请求的来源地址
  • 在请求地址中添加 token 并验证
  • 在 HTTP 头中自定义属性并验证

这是目前防御 CSRF 最简单、最有效的方法。后端在 Set-Cookie 时,加上 SameSite 属性。SameSite

  • SameSite=Strict: 最严格。只有当前网页的 URL 与请求目标一致时,才会带上 Cookie。也就是说,如果你在 evil.com 发起对 bank.com 的请求,Cookie 绝对不会被带上。CSRF 直接失效。
  • SameSite=Lax(现代浏览器默认值): 稍微放宽一点。允许部分跨站的 GET 请求(比如你通过 <a> 标签从外部网站跳转到 bank.com 时会带 Cookie,保证用户体验),但跨站的 POST、PUT、DELETE 等修改数据的请求,或者通过 AJAX、图片加载发出的 GET 请求,统统不带 Cookie。
  • 注意:虽然现代浏览器默认 Lax,但老旧浏览器可能不支持,所以不能完全依赖它。

防御方案 B:CSRF Token(同步令牌模式,最经典的防御)

如果你的应用架构必须使用 Cookie,且需要兼容老浏览器,这是最标准的做法。

  1. 下发 Token: 用户登录后,服务器生成一个随机的、不可预测的字符串(CSRF Token)。这个 Token 可以通过专门的接口发给前端,或者嵌在 HTML 页面里(如果是 SSR 服务端渲染)。
  2. 请求携带: 前端在发送修改数据的请求(POST/PUT等)时,除了浏览器自动带上的 Cookie 外,还需要手动将这个 CSRF Token 放在请求的 Header(如 X-CSRF-Token)或者请求体(Body)中。
  3. 服务器验证: 服务器收到请求,既验证 Cookie 里的 Session,又验证 Header 里的 CSRF Token 是否正确。
  4. 为什么这能防住? 因为黑客所在的 evil.com 受到浏览器的同源策略 (Same-Origin Policy) 限制,无法通过代码读取到 bank.com 返回的 CSRF Token。黑客只能让浏览器自动带 Cookie,却无法伪造出那个放在 Header 里的随机 Token,请求就会被后端拒绝。

防御方案 C:使用不会被浏览器自动附带的凭证

如果认证凭证必须由应用代码显式放进自定义 Header,例如:

Authorization: Bearer <token>

那么经典 Cookie 型 CSRF 的“浏览器自动携带凭证”前提会发生变化。

但这不是“localStorage 比 Cookie 更安全”的结论:

  • 脚本可读存储更暴露于 XSS;
  • Cookie 可以通过 HttpOnly 降低脚本直接读取凭证的风险;
  • 真实选择应结合 XSS、CSRF、SameSite、CORS、Token 生命周期与客户端架构共同评估。

详细关系见 XSS vs CSRF。

学习检查

不看正文回答:

  1. 经典 CSRF 成立通常依赖哪三个条件?
  2. 为什么浏览器自动携带 Cookie 是经典 CSRF 模型的关键?
  3. SameSite、CSRF Token、Origin/Referer 校验分别在哪一层降低风险?
  4. 为什么 CSRF Token 的有效性依赖攻击者站点无法读取目标站点的随机值?
  5. 把认证改为显式 Authorization Header 后,经典 CSRF 条件发生了什么变化?
  6. 为什么这不能直接推出“把 token 放 localStorage 更安全”?
  7. 给一个跨站自动提交表单案例,指出哪些证据能证明它属于 CSRF,而不是 XSS。
创建于 2026/3/12 更新于 2026/9/30
Digital Biome
Access

键盘导航

j / k / ↑ / ↓
选择对象
Enter / o
打开选择
/ 或 Ctrl+K
全站搜索
i / f / 1–4
筛选当前列表
g → h / l / p / t / a
首页 / 笔记 / 项目 / 工具 / About
r → 1–9
打开所选对象的关联
u
返回上一页
Esc
关闭浮层 / 取消命令;输入框内清空文本