流程

首先不管这个词是什么意思,先了解下发生的流程:

  1. 有用户已经登录了 bank.com 且登录凭证保存在 Cookie 中
  2. 用户打开了 attcker.com
  3. attcker.com 向 bank.com 发送请求。例如 img 加载或表单 post
  4. 这个请求会带有来自 bank.com 的 Cookie,会被认为是合法请求
  5. 既然是合法请求,就可以搞事,例如发送向 attacker 转账的请求

再来看名字:

  • 跨站:bank.com 和 attacker.com
  • 请求:img 加载或表单 post 等请求发出方法

重点

CSRF 利用了浏览器在同域发送请求会携带 Cookie 的特性。

如何在 attcker.com 发出来自 bank.com 的请求

  1. img 发出的 GET 请求。
  2. 表单发出的 POST 请求。
  3. 也许还有更多

如何避免

使用 referer

可以在头部添加 referer。表明请求来源,如果来源不是 bank.com 则认为请求非法。

The HTTP referer (a misspelling of referrer[1]) is an optional HTTP header field that identifies the address of the webpage (i.e., the URI or IRI), which is linked to the resource being requested. By checking the referrer, the new webpage can see where the request originated.

https://en.wikipedia.org/wiki/HTTP_referer

然而根据 wiki 对 referer 的解释。这只是一个被设计用来显示来源网站可选选项。所以看起来不应该被用于源站身份验证。

使用 token

attacker 虽然可以发送合法请求,但是并不知道 bank.com 的 Cookie 中存储了什么内容,也不能获取 bank.com 页面中的任何信息。可以利用这个信息差来保证安全:

  1. 后端端下发一个 token 给前端。使用 header 或者 response 中或者其它任何方法均可,因为都能保证不被 attacker.com 获取到
  2. 要求每个请求(请求体或者请求头均可)都带上一个 token 以供 bank.com 验证。
  3. token 验证通过说明请求合法
  4. 由于 attacker.com 无法获取 bank.com 的内容,所以其无法获取 token,进而无法攻击。

Cookies are not sent on normal cross-site subrequests (for example to load images or frames into a third party site), but are sent when a user is navigating to the origin site (i.e., when following a link).

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite#lax

开启 SameSite Cookie Lax 模式,在一些正常请求中不携带 Cookie。例如加载图片、在 iframe 中导航、提交表单等。

参考