如何防御CSRF攻击?专家解析

1 人参与

如果说SQL注入是黑客直接对服务器“破门而入”,那么CSRF攻击则更像是一次精心策划的“身份冒用”。攻击者并不窃取你的密码,而是利用你已经登录的身份,在你不知情的情况下,代替你执行恶意操作。这种攻击隐蔽性强,危害巨大,防御它需要一套系统性的策略,而不仅仅是单点修补。

理解攻击的本质:信任的滥用

CSRF的全称是跨站请求伪造。它的核心逻辑在于,浏览器在发起请求时会自动带上目标站点的Cookie,而服务器则默认信任这些带有合法Cookie的请求。攻击者要做的,就是构造一个能触发敏感操作的请求链接或表单,然后诱导已登录的用户去访问或触发它。

举个例子,假设一个银行网站的转账接口是 GET /transfer?to=account&amount=1000。如果用户已经登录,攻击者只需在一个论坛帖子里嵌入一张图片:<img src="http://bank.com/transfer?to=hacker&amount=10000">。当用户浏览这个帖子时,浏览器就会自动发起这个转账请求,并带上用户的登录Cookie。服务器看到合法Cookie,便执行了转账。

防御基石:不可预测的令牌

目前,业界公认最有效、最核心的防御手段是使用Anti-CSRF Token。这个方案彻底颠覆了“仅凭Cookie就信任请求”的默认逻辑。

它的工作原理很简单,但非常有效:

  1. 服务器在用户会话中生成一个随机、不可预测的令牌,同时将这个令牌嵌入到即将返回给用户的表单中(通常是一个隐藏字段)。
  2. 当用户提交表单时,必须将这个令牌一并提交。
  3. 服务器收到请求后,会比对请求中的令牌和会话中存储的令牌是否一致。只有一致,请求才被认为是合法的、来自用户真实意愿的。

这个令牌就像一张“动态口令”,每次表单都是唯一的(或会话期内有效)。攻击者无法提前预知或获取这个令牌,因此他构造的恶意请求就会因为缺少正确的令牌而被服务器拒绝。

<!-- 服务器端生成的表单示例 -->
<form action="/transfer" method="POST">
  <input type="hidden" name="csrf_token" value="7a9f8b3c4d5e6f...">
  <!-- 其他表单字段 -->
  <input type="submit" value="确认转账">
</form>

同源策略的强化:SameSite Cookie属性

除了令牌,我们还可以在Cookie本身上下功夫。现代浏览器支持的 SameSite Cookie属性,是防御CSRF的一件利器。

它可以设置为三个值:

  • Strict:最严格。浏览器只会在同站请求(即当前页面URL与请求目标URL的“站点”相同)中发送此类Cookie。这意味着来自其他站点的链接或表单提交,完全不会携带此Cookie。
  • Lax:默认值,也是目前很多框架的推荐设置。允许在顶级导航(如点击链接)且是安全(如GET)的请求中发送Cookie,但会阻止在跨站点的POST请求或通过 <img><iframe> 等发起的请求中发送。这平衡了安全性和用户体验。
  • None:必须与 Secure 属性(仅通过HTTPS传输)一同使用,允许跨站发送。适用于需要跨站共享登录状态的场景,但需明确知晓CSRF风险。

将关键的身份验证Cookie设置为 SameSite=LaxStrict,可以极大地增加攻击者构造有效恶意请求的难度。

额外的验证层:检查Referer/Origin头部

作为辅助手段,服务器可以检查HTTP请求头中的 RefererOrigin 字段。这两个字段标明了请求的来源页面。

  • Referer:包含了完整的来源URL。
  • Origin:对于跨域请求,包含了来源的协议、域名和端口。

服务器可以验证这些字段是否来自可信的、同源的域名。如果不是,则拒绝请求。不过,这种方法存在局限性:一方面,部分浏览器或用户隐私设置可能不发送 Referer;另一方面,Referer 可能被某些代理或防火墙篡改。因此,它通常作为Token机制的补充,而非替代。

实践中的组合拳

在实际的防御体系中,专家们往往会采用组合策略,形成纵深防御:

  1. 强制实施Anti-CSRF Token:对所有可能改变状态的请求(POST、PUT、DELETE等)进行保护。
  2. 关键Cookie设置SameSite属性:将会话Cookie设置为 SameSite=Lax
  3. 敏感操作二次确认:对于关键业务操作(如转账、修改密码),要求用户再次输入密码或进行短信验证。
  4. 保持框架更新:使用成熟的、积极维护的开发框架(如Spring Security、Django、Laravel等),它们通常内置了经过良好测试的CSRF防护机制,直接启用即可。

防御CSRF,本质上是在教导服务器“多疑”——不要轻易相信任何一个看似合法的请求,必须要求对方出示额外的、动态的凭证。这种“不信任”的设计哲学,正是构建安全网络应用的基石。

参与讨论

1 条评论
  • 废土秃鹫

    这个Token机制在前后端分离的项目里怎么传比较好?

    回复