Web 安全
CSRF (跨站请求伪造)
约 3 分钟阅读
最后更新: 2026-02-08
什么是 CSRF (跨站请求伪造)
CSRF (Cross-Site Request Forgery) 是一种攻击手法,使用户的浏览器向已认证的 Web 站点发送非用户本意的请求。攻击者准备一个陷阱网页或邮件,受害者一旦查看,其浏览器就会自动向目标站点发送恶意请求。
由于浏览器会自动为同一域名的请求附加 Cookie,如果受害者处于登录状态,攻击者的请求也会被作为已认证请求处理。密码修改、转账、邮箱地址变更、商品购买等改变状态的操作都会成为攻击目标。
攻击原理与具体示例
CSRF 攻击按以下流程执行。
- 受害者登录目标站点 (例如网上银行),会话 Cookie 保存在浏览器中
- 受害者查看攻击者准备的陷阱页面 (通过邮件链接、论坛帖子等)
- 陷阱页面中嵌入的 HTML 或 JavaScript 从受害者的浏览器向目标站点发送请求
- 浏览器自动附加会话 Cookie,目标站点将其作为合法请求处理
例如,如果转账功能通过 POST /transfer?to=attacker&amount=100000 这样的请求运行,攻击者只需在陷阱页面中嵌入自动提交的表单,就能从受害者账户执行转账。
虽然容易与 XSS 混淆,但 CSRF 的根本区别在于它是从受害者的浏览器伪造合法请求,而非在受害者的浏览器中执行攻击者的脚本。
防御措施的实现
CSRF 防御的核心是引入验证请求是否基于合法用户意图的机制。
CSRF 令牌
服务器在显示表单时生成随机令牌并嵌入隐藏字段。表单提交时验证令牌是否匹配,从而拒绝来自外部站点的伪造请求。令牌对每个会话是唯一的,攻击者无法获知受害者的令牌。
SameSite Cookie 属性
通过设置 Cookie 的 SameSite 属性,可以控制跨站请求是否附加 Cookie。
SameSite=Strict:不为来自外部站点的任何请求附加 Cookie。最安全,但通过外部链接访问时也无法保持登录状态SameSite=Lax:仅为顶级导航 (链接点击) 的 GET 请求附加 Cookie。由于不为 POST 请求附加 Cookie,可以防止大多数 CSRF 攻击SameSite=None:跨站请求也附加 Cookie。必须与Secure属性配合使用
其他防御措施
现代框架中的 CSRF 防护
许多现代 Web 框架内置了 CSRF 防护功能。
- Django:通过
{% csrf_token %}模板标签自动嵌入令牌,并通过中间件进行验证 - Ruby on Rails:通过
protect_from_forgery自动生成和验证 CSRF 令牌 - Spring Security:默认启用 CSRF 保护。自动将
CsrfToken插入表单 - Next.js / SPA:API 路由中结合 SameSite Cookie 和 Origin 头验证。也可考虑通过 WAF 进行额外保护
如果禁用框架的 CSRF 保护,请确认替代措施已可靠实现。在 API 端点排除 CSRF 保护时,前提是切换到 Bearer Token 认证,不使用基于 Cookie 的认证。
常见误解
- GET 请求不会发生 CSRF
- 如果通过 GET 请求实现了状态变更操作 (删除、设置变更等),就会成为 CSRF 的目标。仅通过在 img 标签的 src 属性中设置 URL 就能发送 GET 请求,因此状态变更必须使用 POST/PUT/DELETE 实现。
- 使用 HTTPS 就能防止 CSRF
- HTTPS 提供通信加密和防篡改功能,但与 CSRF 无关。CSRF 是从合法用户的浏览器发送合法请求的攻击,即使通信被加密,攻击仍然成立。
分享