是否应该对所有 post 请求进行 CSRF 检查?

Should a CSRF check be done on all post requests?

据我了解,应该对任何更改状态的请求进行 CSRF 检查。

如果是这种情况,难道不应该所有 POST 请求都进行 CSRF 检查吗?

如果不是这种情况,还有哪些例外?

这个问题的起源来自一个关于使用 Firebase 管理会话 Cookie 的教程,他们使用 CSRF 检查初始登录步骤,但不检查 post 稍后的请求

https://firebase.google.com/docs/auth/admin/manage-cookies#node.js_2

TL;DR:

  1. 无论使用何种 HTTP 方法,都应在任何状态更改请求上实施 CSRF 保护(尽管 PUT 和 DELETE 请求本质上可以减轻 CSRF)
  2. 要防止 CSRF,请使用下面编号列表中描述的方法之一。

详情:

如您所述,在 CSRF 攻击中,攻击者希望执行状态更改操作,例如修改个人资料的电子邮件地址、转账等

任何触发服务器上任何操作的post-authentication请求都应该被验证。 在登录屏幕上实施 CSRF 保护是没有意义的,因为攻击者需要知道用户密码,如果他知道用户密码,CSRF 攻击就多余了。 (免责声明 - 在某些边缘情况下,例如使用自 XSS 链接,登录屏幕上的 CSRF 可能会协助攻击者)

只请求 return 数据但不执行任何操作,不需要 CSRF 保护,因为在 CSRF 攻击中,攻击者无法访问服务器的响应。

CSRF 攻击之所以成为可能,是因为浏览器会自动将 cookie 发送到相应的域,而无需任何程序触发或用户交互。这也意味着将 CSRF 令牌放入 cookie 中没有任何意义,也不会真正减轻 CSRF。

缓解措施:

也就是说,缓解 CSRF 攻击的方法不止一种:

  1. 使用反 CSRF 令牌 - 一个独特的随机值,通常存储为隐藏字段,作为发送请求的 HTML 表单的一部分。该值在每个页面或至少每个用户会话中应该是唯一的,并且在每次状态更改请求时由服务器验证。
  2. 使用存储在网络存储 (sessionStorage/localStorage) 中的会话令牌而不是 cookie。由于这些值需要以编程方式发送,通常是通过某些 SPA 框架并且不会自动发送,因此默认情况下这会破坏 CSRF。
  3. 在会话 cookie 上实施 "sameSite" flag