什么是 CSRF 攻击?如何防范?
简化版
CSRF(跨站请求伪造):攻击者诱导已登录用户的浏览器,在用户不知情的情况下,向目标网站发起一个带着用户身份(Cookie 自动携带)的请求,从而冒用身份执行操作(转账、改密码)。根源是浏览器会自动带上目标站的 Cookie。防范核心:验证请求确实来自本站——用 CSRF Token、SameSite Cookie、校验 Origin/Referer。
详细版
攻击原理:
- 用户登录了
bank.com,浏览器存了它的登录 Cookie; - 用户在没退出的情况下,访问了攻击者的网站
evil.com; evil.com页面里藏了一个自动向bank.com发请求的表单/图片(如<img src="bank.com/transfer?to=攻击者&amount=1000">);- 浏览器发这个请求时,自动带上了
bank.com的 Cookie(浏览器的默认行为); bank.com一看 Cookie 有效,以为是用户本人操作,就执行了转账。
关键:攻击者看不到也不需要用户的 Cookie,它只是借用浏览器会自动带 Cookie 的机制,让用户「替自己」发出恶意请求。
防范手段:
- CSRF Token:服务端给每个表单/会话生成一个随机 token,提交时必须带上、服务端校验。
evil.com拿不到这个 token(同源策略挡着),伪造的请求就通不过。 - SameSite Cookie:给 Cookie 设
SameSite=Lax/Strict,让跨站请求不携带该 Cookie,从根上断了 CSRF 的依赖。 - 校验 Origin / Referer:检查请求来源是不是本站,不是就拒绝。
- 关键操作二次验证:转账等敏感操作要求输密码/短信验证码。
完整版教学
一、CSRF 的本质:借用「自动带 Cookie」
理解 CSRF 的钥匙是:浏览器对某个网站的请求,会自动带上该网站的 Cookie,不管这个请求是从哪个页面发起的。
这本是为了方便(你不用每次手动带登录态),但被 CSRF 利用了:攻击者的页面发起一个指向 bank.com 的请求,浏览器照样自动带上 bank.com 的登录 Cookie。于是这个「实际由攻击者发起」的请求,在 bank.com 看来「携带了合法登录态」,就被当成用户本人的操作执行了。
所以 CSRF 攻击者全程不接触用户的 Cookie——它偷的不是凭证,而是用户的「已登录」状态。这也是它和 XSS 的本质区别(XSS 是注入脚本、能偷 Cookie;CSRF 是借用身份、看不到 Cookie)。
二、防御一:CSRF Token(最经典)
既然攻击者能冒用身份,那就加一道它拿不到的凭证:
- 服务端渲染表单时,塞一个随机的 CSRF Token(存在页面里 + 服务端会话里);
- 用户正常提交时带上 token,服务端校验一致才放行;
- 攻击者的
evil.com想伪造请求,但它读不到bank.com页面里的 token(同源策略禁止跨站读取),所以伪造的请求缺 token 或 token 错误,被拒绝。
核心逻辑:用一个「只有本站页面才拿得到」的随机 token,证明请求确实来自本站。
三、防御二:SameSite Cookie(现代首选)
SameSite 是 Cookie 的一个属性,直接控制「跨站请求要不要带这个 Cookie」:
SameSite=Strict:完全不跨站携带——从别的站点发起的请求一律不带该 Cookie,最安全,但体验略差(从外链点进来也不带登录态);SameSite=Lax(现代浏览器默认):大部分跨站请求不带 Cookie,只有安全的顶级导航(如点链接跳转的 GET)才带——挡住了绝大多数 CSRF;SameSite=None:跨站也带(需配Secure),用于确实要跨站的场景。
设成 Lax/Strict 后,evil.com 发起的跨站请求根本不携带 bank.com 的 Cookie,CSRF 从根上失效。这是现代最省事的防御。
四、防御三:校验来源 + 敏感操作加固
- 校验 Origin / Referer:请求头里的
Origin/Referer标明了请求从哪个页面发起,服务端检查它是不是本站,不是就拒绝。简单但不总可靠(Referer 可能被隐藏)。 - 关键操作二次验证:转账、改密码这类高危操作,额外要求输入密码、短信验证码——即使 CSRF 发出了请求,没有二次验证也执行不了。
实践中常多管齐下:SameSite 兜底 + 关键接口加 CSRF Token + 敏感操作二次验证。
五、常见误区
- ❌ 以为 CSRF 是偷 Cookie——它不接触 Cookie,只是借用浏览器自动带 Cookie 的机制冒用身份。
- ❌ 把 CSRF 和 XSS 混——XSS 注入脚本(能偷 Cookie、执行任意脚本),CSRF 冒用身份发请求(看不到 Cookie)。
- ❌ 以为验证码框内容就能防 CSRF——要防的是「请求来自本站」,靠 Token/SameSite,不是普通表单校验。
- ❌ 以为 GET 请求安全——
<img src>、<a>都能发 GET,所以改数据的操作绝不能用 GET(详见「GET 和 POST 的区别」那道题)。
六、常见误区与追问
| 考点 | 正确口径 |
|---|---|
| 攻击前提 | 用户已登录目标站,浏览器自动带 Cookie |
| 攻击动作 | 第三方页面诱导浏览器发起敏感请求 |
| 防护 | CSRF Token、SameSite、校验 Origin/Referer |
<form action="https://bank.example/transfer" method="POST">
<input name="to" value="attacker">
<input name="amount" value="1000">
</form>
<script>document.forms[0].submit()</script>
CSRF 利用的是浏览器自动带凭证,不需要偷到 Cookie 内容。Token 的价值在于攻击站拿不到合法随机值。
- 误区:只要用 POST 就不会有 CSRF。 攻击页面可以自动提交表单或发起请求,POST 本身不是防护。
- 误区:CSRF 必须读取响应。 攻击目标通常是让浏览器发出状态变更请求,读不到响应也可能成功。
- 误区:有验证码就一定安全。 验证码可增加成本,但接口仍应有 Token、SameSite 和来源校验。
- 追问:CSRF Token 为什么有效? Token 随页面或会话生成,攻击站无法读取同源页面中的随机 Token。
- 追问:SameSite 有哪些值?
Strict更严格,Lax兼顾部分跳转,None必须配合 Secure。 - 追问:CSRF 和 XSS 谁更危险? XSS 可读取页面并发起同源请求,常能绕过 CSRF Token,因此必须同时防。
七、加强记忆
CSRF(跨站请求伪造)诱导已登录用户的浏览器向目标站发带 Cookie 的请求,冒用身份执行操作——根源是浏览器自动携带目标站 Cookie(攻击者不接触 Cookie,只借用登录态)。防范:CSRF Token(攻击者跨站读不到)、SameSite Cookie(跨站不带 Cookie,现代首选)、校验 Origin/Referer、敏感操作二次验证。它和 XSS 的区别:CSRF 借身份、XSS 注脚本偷 Cookie。