evil.comhidden formBROWSERauto-sendsbank cookiesbank.comtransfer $cookie-authenticated request without consent

跨站请求伪造

11 最小阅读量安全

跨站点请求伪造是一种漏洞,其中恶意页面使您的浏览器向您登录的站点提交请求 - 使用您的凭据,执行未经您授权的操作。 SameSite cookie 已经关闭了大部分历史攻击面,但只要 cookie 验证状态更改操作,底层类仍然很重要。

完整的文章正文以英文提供如下。

跨站点请求伪造(CSRF,有时称为 XSRF 或“sea-surf”) 利用网站对用户浏览器的信任。攻击者看不到您的 cookie,但浏览器会在每次请求时自动将它们发送到它们所属的源。如果攻击者可以触发您的浏览器向您登录的站点发出请求,则该站点会看到经过身份验证的请求 - 即使攻击者发起了该请求。

经典攻击

想象一家通过简单的 GET 请求处理转账的银行:https://bank.example/transfer?to=Bob&amount=1000。您已登录银行。攻击者通过电子邮件向您发送一个链接或托管一个带有指向 的图像标签的页面 https://bank.example/transfer?to=Attacker&amount=10000。您的浏览器加载图像;银行看到来自您会话的经过身份验证的请求;

这个具体例子大多是历史性的——银行不再通过 GET 处理转账——但模式是通用的。任何仅通过会话 cookie 进行身份验证的状态更改请求都可能存在 CSRF 漏洞。

什么使 CSRF 成为可能

三个基础:

  • Cookie 会自动发送。 浏览器不请求许可; cookies 属于源头,并且随每个请求一起传送到该源头,无论请求是在哪里发起的。
  • HTML 可以触发跨源请求。 图像标签、表单提交、脚本标签和各种其他元素都可以针对任何 URL。
  • 服务器在不验证意图的情况下对请求进行操作。 服务器看到经过身份验证的请求;如果没有明确的 CSRF 保护,它会处理该操作。

标准防御

  • CSRF 令牌(同步器令牌)。 服务器包含每种形式的随机令牌。提交的内容必须包含令牌。攻击者的恶意页面无法读取token(同源策略),因此伪造请求失败。现代 Web 框架会自动生成和验证令牌。
  • SameSite cookies。 标记为 SameSite=Lax(自 2020 年起在现代浏览器中默认)的 Cookie 不会在除顶级导航之外的跨站点请求上发送。 SameSite=Strict 甚至更严格。这是过去五年中降低 CSRF 风险的最大单一变化。
  • Origin 和 Referer 标头验证。 服务器可以检查 Origin 标头是否与预期来源匹配。跨站请求有不同的Origin,允许拒绝。
  • 双提交cookie。服务器在cookie和单独的请求参数中都设置一个值;验证者检查它们是否匹配。无需服务器端会话状态即可工作。
  • 对敏感操作进行重新身份验证。 对高价值操作进行密码确认、MFA 质询或逐步身份验证。同时击败 CSRF 和其他几种攻击类别。

SameSite cookies 革命

2020 年之前,每个跨站点请求都携带目标站点的 cookie — 包括来自恶意页面的状态更改请求。 SameSite=Lax 使跨站点 cookie 成为例外而不是规则。主要浏览器在 2020-2021 年默认为 Lax,影响是巨大的:大多数偶然的 CSRF 漏洞一夜之间变得不可利用。

问题:SameSite=Lax 仍然允许顶级导航上的 cookie(全页面重定向)。通过点击链接触发的状态改变操作仍然可以携带cookie。防御很好,但不完整。

SameSite=Strict 完全阻止了这种情况。权衡:它破坏了依赖于跨站点导航(单点登录、OAuth 后重定向)的登录流程。大多数主要站点默认使用 Lax,仅对最敏感的 cookie 使用 Strict。

CSRF 和 API

现代 API 通常通过授权标头(承载令牌)而不是 cookie 进行身份验证。 CSRF 不适用,因为浏览器不会自动在跨源请求中包含任意标头。 CSRF 问题很大程度上属于 cookie 身份验证系统。

但是,混合某些流的 cookie 和其他流的令牌的 API 可能具有微妙的 CSRF 表面。一致地使用其中之一。

CSRF 和 CORS

CORS(跨源资源共享)定义浏览器何时允许 JavaScript 读取跨源请求。 CSRF是关于请求是否是sent,带有cookie。它们相关但又不同:

  • CSRF 防止恶意页面引起请求
  • CORS 防止恶意页面读取响应

CSRF 攻击不需要读取响应 - 它只需要服务器执行操作。浏览器尽职尽责地发出请求并获得响应;恶意页面可能看不到它,但损害已经造成。 CORS 无法修复 CSRF.

著名的 CSRF 事件

  • Netflix 队列操纵 (2006). 研究人员发现,精心设计的 IMG 标签可以在无需您参与的情况下将电影添加到您的 Netflix 队列中。该修复是第一个广泛使用的CSRF令牌。
  • YouTube帐户接管变体在2000年代后期。
  • GitHub存储库删除通过CSRF在2012年(很快修复)。
  • 许多WordPress插件CSRF每年都会报告 漏洞;插件生态系统仍在大规模生产它们。

对于 2026 年的开发人员

  • 使用具有内置 CSRF 保护的框架(Django、Rails、Spring、Laravel 都有)
  • 在每个状态更改请求上验证 CSRF 令牌
  • Set SameSite=Lax (或对会话 cookie 严格要求
  • 对于 API,尽可能使用承载令牌而不是 Cookie
  • 需要对高风险操作进行重新身份验证
  • 不要单独依赖 Origin/Referer — 某些客户端省略这些标头

对于用户

您无法直接防御 CSRF——这是一个服务器端错误。现代浏览器默认设置 (SameSite=Lax) 有很大帮助,但您依赖于您登录的每个站点都已实施保护。仅在需要时保持登录状态;不使用时退出敏感帐户;并信任现代主要站点 - 他们都在其威胁模型中处理了 CSRF。

常见问题

SameSite cookies 杀死了 CSRF 吗?
大幅减少但并未消除。 SameSite=Lax(现代默认设置)允许在顶级导航上使用跨站点 cookie。 SameSite=Strict 也可以防止这种情况,但会破坏合法的流量。 CSRF 代币仍然是推荐的防御方式; SameSite 是一个补充层。
CSRF 与 XSS 有何不同?
XSS 将恶意代码注入受信任的站点,并以其权限执行。 CSRF 欺骗浏览器向受信任的站点发送请求,而不注入任何内容。 XSS 可以做 CSRF 能做的一切,甚至更多。它们是不同的攻击机制。
我可以在自己的应用程序中测试 CSRF 吗?
是的。尝试提交删除或更改令牌的表单;如果操作成功,您就拥有了 CSRF。在 Chrome 中使用 SameSite 强制进行测试;一些遗留框架具有未经实际验证的 CSRF 令牌。手动审核非常简单。
单页应用需要CSRF保护吗?
如果他们通过 cookie 进行身份验证,是的。如果它们通过存储在客户端 (localStorage) 的不记名令牌进行身份验证,则它们不易受到 CSRF 攻击,但更容易受到 XSS 攻击。两个攻击面都很重要;选择您的身份验证机制时要考虑到两者。
CSRF 还在 OWASP 前 10 名吗?
由于广泛的框架级缓解措施和 SameSite cookie 默认值,它在 2021 年跌出了前 10 名。它仍然位于 OWASP 重大漏洞列表中;流行率下降了,但根本机制却没有下降。
CSRF 解释:当网站欺骗您的浏览器代表您行事时