CSRF 攻击与防御:从原理到 SameSite Cookie 策略
2026/8/8 5:12:46 网站建设 项目流程

文章目录

    • 一、用一句话讲透原理
    • 二、攻击长什么样(认识即可)
      • 1. 经典:自动提交的表单
      • 2. 图片 / 链接触发的 GET
      • 3. JSON 接口就一定安全吗?
      • 4. 登录 CSRF 与其它变体
    • 三、防御总纲:你要证明“这是用户本人意图”
    • 四、CSRF Token:仍然是基本功
      • 1. 同步器令牌模式
      • 2. 双提交 Cookie(Double Submit)
      • 3. 框架优先
    • 五、Origin / Referer 校验
    • 六、SameSite Cookie:现代浏览器的“半自动防线”
      • 1. SameSite 是干什么的
      • 2. Lax 为什么常常“够用却不够”
      • 3. Strict 的代价
      • 4. None 用在什么地方
      • 5. 和“站”的定义有关
      • 6. SameSite 解决不了什么
    • 七、推荐的组合策略(2020 年代务实版)
      • 对外 Web 应用
      • 纯 API + Bearer Token(前端存内存)
      • Cookie 会话的 SPA
      • 第三方支付回调 / Webhook
    • 八、授权测试怎么测 CSRF
    • 九、常见翻车现场
    • 十、收尾
      • 附:SameSite 选择速查

做安全的人里,有一批人对 CSRF 的第一印象是:“不就是表单里加个 token 吗?”
做业务的人里,另一批人的第一印象是:“我们全是 JSON 接口,好像不太怕。”

两边都只对了一半。CSRF(Cross-Site Request Forgery,跨站请求伪造)的核心从来不复杂——浏览器会在跨站请求里自动带上目标站的 Cookie(在策略允许时)——可一旦碰上 SameSite 默认值变化、前后端分离、移动 WebView、文件上传、GET 误伤业务,坑就会一个个冒出来。


一、用一句话讲透原理

你已经登录了银行站点bank.example,浏览器里躺着会话 Cookie。
你另开一个标签,访问了恶意页evil.example。恶意页可以让你的浏览器向bank.example发起一个请求——比如“转账”。

关键在于:在很多历史默认行为下,浏览器发这个请求时,会自动附带bank.example的 Cookie。服务器若只靠“有没有合法会话 Cookie”判断“是不是用户本人意愿”,就会把跨站伪造的请求当成用户点的。

所以 CSRF 骗的不是密码,是服务器对浏览器自动凭证的信任

和 XSS 对比一下更好记:

XSSCSRF
核心在目标站上下文执行攻击者脚本借用用户浏览器向目标站发请求
要不要目标站有漏洞页通常要有注入点要有“只认 Cookie、不认意愿”的接口
典型结果偷会话、改页面、继续作恶以用户身份完成状态变更

XSS 有时能直接做完 CSRF 能做的事;但没有 XSS 时,CSRF 仍可能单独成立。两者都要防。


二、攻击长什么样(认识即可)

1. 经典:自动提交的表单

恶意页里放一个自动提交到目标站的表单(POST),用户一旦打开恶意页,浏览器就带着 Cookie 把请求打出去。用户可能只看到页面闪一下,账户状态却变了。

2. 图片 / 链接触发的 GET

若危险操作竟然用 GET 就能完成(例如GET /delete?id=1),那一张<img src="...">都可能触发。
这首先是业务接口设计错误:改变状态的操作不该是 GET。即便防了 CSRF,也应改成 POST/PUT/DELETE + 鉴权。

3. JSON 接口就一定安全吗?

不完全。确实,简单 HTML 表单很难发Content-Type: application/json的复杂请求;浏览器的 CORS 预检也会挡一批“跨域读响应”。但 CSRF 关心的往往是请求有没有副作用,不是攻击者能不能读返回值。

仍需小心:

  • 服务端若接受text/plain等方式“擦边”解析出 JSON;
  • 某些接口其实也吃表单编码;
  • 同站点子域被拿下后的“跨站”边界更细;
  • 配合 XSS / 子域接管时,SameSite 与 CORS 模型会更复杂。

结论:前后端分离 ≠ 自动免疫 CSRF,要看 Cookie 怎么带、接口怎么鉴权。

4. 登录 CSRF 与其它变体

还有“强迫用户登录成攻击者账号”一类登录 CSRF,用于后续投毒或追踪。是否划进你们的威胁模型,取决于业务。支付、改密、授权绑定、关闭 MFA 等,一律按高危状态变更保护。


三、防御总纲:你要证明“这是用户本人意图”

会话 Cookie 证明“浏览器里有谁的登录态”;
CSRF 防御要额外证明“这次请求是用户在本站上下文里发起的”。

常见积木:

  1. CSRF Token(同步器令牌 / 双提交 Cookie 等)
  2. 检查 Origin / Referer
  3. SameSite Cookie
  4. 不用 Cookie 做会话(如 Authorization Bearer,注意仍有别的风险)
  5. 关键操作二次确认 / 重新输入密码 / MFA
  6. Get 无副作用

实战里很少只靠一样。SameSite 大幅降低了成本,但不是万能符。


四、CSRF Token:仍然是基本功

1. 同步器令牌模式

服务端给每个会话(或每次表单)下发随机 token,存在服务端会话里。
浏览器提交状态变更时必须带上这个 token(表单隐藏域或自定义头)。
服务端校验 token 与会话绑定一致。

攻击者的站点读不到你的页面内容(受同源策略限制),也就拿不到 token——于是跨站请求缺令牌,被拒。

要点:

  • token 要不可预测、足够长;
  • 验证失败要拒绝,不要“没带也行”;
  • 注意刷新、多标签页、缓存页面导致的 token 过期体验问题;
  • SPA 常见做法:从 cookie 读 token 再复制到 Header(见双提交),或由后端接口下发到前端内存。

2. 双提交 Cookie(Double Submit)

服务端设一个 CSRF Cookie,前端 JS 读取后放到请求头(如X-CSRF-Token)。服务端比较 Cookie 与 Header 是否一致。

它依赖:攻击者不能轻易读写你的 Cookie,也不能在跨站场景下方便地设置你的域 Cookie 并同时控制头(结合现代浏览器策略)。实现细节一错(例如 Cookie 过于宽松、子域可写)就会翻车。框架自带实现通常比手搓安全。

3. 框架优先

Django、Rails、Spring Security、ASP.NET、Laravel 等几乎都有现成 CSRF 中间件。
优先用框架,别在业务里东一块西一块。


五、Origin / Referer 校验

服务端检查OriginReferer是否为本站可信来源。跨站表单请求往往会带上恶意源,或在某些情况下缺失。

优点:实现相对简单,对传统表单 CSRF 有效。
缺点与坑:

  • Referer 可能被隐私策略、浏览器设置裁掉;
  • 误杀:合法无 Referer 的客户端;
  • 只靠 Referer 不如 Origin 清晰;
  • 需维护可信域列表(含多域名站点)。

实操建议:能拿 Origin 先拿 Origin;缺失时策略要明确(拒绝或走额外校验);与 token 组合更稳。


六、SameSite Cookie:现代浏览器的“半自动防线”

1. SameSite 是干什么的

Cookie 的SameSite属性控制:在跨站请求中是否携带该 Cookie

常见值:

含义(直观理解)
Strict跨站请求基本不带这个 Cookie;最严
Lax跨站“导航式”GET 等部分场景可能带;常见跨站 POST 不带
None跨站也可带;但通常要求同时Secure(仅 HTTPS)

浏览器近几年把默认策略收紧(许多场景默认按 Lax 思路处理未声明的 Cookie,具体以浏览器为准)。这让大量“裸 POST + 会话 Cookie”的老式 CSRF自然失效了一大截——好事,但别据此拆掉服务端校验。

2. Lax 为什么常常“够用却不够”

Lax下,用户从外站点开一个链接(顶级导航 GET)进入你的站时,仍可能带上 Cookie——这是为了体验(外链进站保持登录)。
因此:若你的危险操作可用 GET 完成,Lax 挡不住。
再次强调:状态变更用 POST 等,并配合 token。

3. Strict 的代价

更安全,但用户从外部链接点进网站可能呈现未登录,体验受损。高安全后台、管理端可以上 Strict;对 C 端大站,更多用 Lax + CSRF token。

4. None 用在什么地方

跨站需要带 Cookie 的场景:第三方嵌入、某些 SSO、跨站 API(本身就很敏感)。
必须Secure,必须 HTTPS,必须清楚自己在扩大 CSRF 攻击面——此时更要有 token 或其它强校验,不能只靠 SameSite。

5. 和“站”的定义有关

SameSite 里的“站(site)”按 eTLD+1 等规则理解,和“源(origin)”不完全一样。a.example.comb.example.com在 SameSite 看来可能是同站,但在同源策略上不同源。
子域接管、兄弟子域 XSS,会让“同站 Cookie”模型更危险。子域安全与 Cookie 域范围(Domain=)要一起设计。

6. SameSite 解决不了什么

  • 同站内的请求伪造(子域恶意页面打主域接口);
  • 非 Cookie 凭证方案下的其它伪造;
  • 用户已被 XSS 的情况;
  • SameSite=None的跨站带 Cookie 场景;
  • GET 副作用接口在 Lax 下的风险。

所以官方与业界共识接近:SameSite 是显著缓解,不是完整替代 CSRF token。


七、推荐的组合策略(2020 年代务实版)

对外 Web 应用

  1. 会话 Cookie:Secure+HttpOnly+SameSite=Lax(或管理端 Strict);
  2. 所有状态变更:CSRF token 或框架等价物;
  3. 校验 Origin(可作附加层);
  4. GET/HEAD 无副作用;
  5. 改密、转账、授权:二次验证。

纯 API + Bearer Token(前端存内存)

不自动带 Cookie,天然规避经典 CSRF。但要注意 XSS 偷 token、token 存储位置、刷新令牌泄漏。不是“更安全的免费午餐”,是换威胁模型。

Cookie 会话的 SPA

依然按 Cookie 场景防 CSRF:双提交或同步器令牌;别假设 JSON 万能。

第三方支付回调 / Webhook

那是服务端到服务端,应用签名校验,不走浏览器 CSRF 模型。别和浏览器 CSRF 混为一谈。


八、授权测试怎么测 CSRF

  1. 登录受害者账号,抓一条状态变更请求;
  2. 去掉 token / 改坏 token,看是否仍成功——应失败;
  3. 用跨站 HTML 复现(靶场),观察 Cookie 是否带上、结果是否变更;
  4. 检查 Cookie 的 SameSite / Secure / HttpOnly;
  5. 扫一遍危险 GET;
  6. 子域、多域名、跨站 iframe 场景单独评估。

报告里写清:接口、方法、缺了哪层防护、SameSite 现状、修复建议。
不要在真实用户账户上做破坏性演示。


九、常见翻车现场

“我们加了 token,但有的接口忘了。”
全局中间件白名单要极短,且审计。

“Token 放在 Cookie 里,又没校验头,等于没防。”

“全站 SameSite=None 为了嵌入。”
等于主动回到跨站带 Cookie 时代,必须强 token。

“Referer 全拦,APP 内 WebView 误伤。”
要区分客户端,用组合策略。

“有 XSS 还纠结 CSRF。”
先修 XSS;XSS 在时可直接操作用户会话。

“跨域 CORS 配了 Access-Control-Allow-Origin: * 还带凭证。”
这是灾难级配置。带 Cookie 的 CORS 必须精确源,绝不能*


十、收尾

CSRF 的原理薄如纸:浏览器自动递凭证,服务器误当成用户点头。
防住它的思路也稳定:再要一个“只有本站页面才拿得到的证据”——token、严格的源校验,再加上 SameSite 这道浏览器给的缓冲。

SameSite 让今天的默认世界比十年前安全,但它不会替你改掉危险的 GET,不会替你看好SameSite=None,也不会替你防守子域和 XSS。把它当保险杠,把 token 与正确的会话设计当刹车。

今晚若只做一件事:打开浏览器开发者工具,看你们主站会话 Cookie 有没有SameSiteSecure;再随便抓一个改资料/下单请求,看有没有 CSRF token 或等价头。
两眼看完,你就知道自己站在“靠浏览器默默挡着”,还是“纵深真的做了”。


附:SameSite 选择速查

场景更常见选择
普通 C 端站点会话Lax+ CSRF token
高安全后台Strict+ token
必须跨站带 CookieNone; Secure+ 强 token + 极小范围
无 Cookie 会话 APIBearer 等 + 防 XSS

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询