为什么通过发行 CSRF 代币可以防止 CSRF 攻击?

信息安全 csrf
2021-08-13 13:54:42

防止 CSRF 请求的常用方法:每次用户加载包含要发布的表单的页面时,都会向用户发出一个 CSRF 令牌,该令牌应该对潜在的恶意第三方站点是未知的。令牌以 cookie 和隐藏<form>字段的形式发布。客户端应该通过在请求正文中放置一个有效的 CSRF 令牌并提供一个有效的 cookie 来验证每个 POST 请求。

假设用户登录example.com并在另一个选项卡上浏览到evil.com; 并且evil.com想要攻击example.com/form.html我知道evil.com可以向 a 发出 POST 请求,example.com/form.html并且该站点会将这个恶意 POST 请求解释为来自用户的有效请求。CSRF 令牌阻止了这种情况,因为它们应该是未知的evil.com它无法通过其恶意 POST 请求发送正确的令牌,因此example.com服务器将拒绝该请求。

这是我无法理解的部分。CSRF 令牌以 cookie 和隐藏表单字段的形式发布。对于 cookie 部分,这是微不足道的:IIUC 每个请求都example.com自动包含来自的所有 cookie example.com因此,假设用户在另一个选项卡上登录example.com,恶意 POST 请求将包含有效的 CSRF cookie。这个对吗?

对于隐藏的表单字段部分,这会稍微复杂一些,但并不多。Evil.com可以发出 GET XMLHttpRequest 到example.com/form.html并且该请求将成功,因为用户在另一个选项卡上登录到此站点并且因为 GET 请求不受 CSRF 保护。作为响应,evil.com获取example.com/form.html包含相关<form>问题的HTML 源代码,该源代码又包含<input>带有 CSRF 令牌的隐藏字段。Evil.com现在可以解析接收到的文档,提取令牌并将其与随后的恶意 POST 请求捆绑在一起example.com/form.html,从而成功完成 CSRF 攻击。

我的上述推理有什么问题?我不明白什么?

1个回答

您是正确的,浏览器将从请求中发送 CSRF-cookie example.com但是,由于Cross Origin Resource Sharing上的脚本evil.com无法读取嵌入在网页中的 CSRF-token example.com/form.html

所以脚本evil.com不能访问cookie,因为它属于另一个域。并且它不能读取表单中的令牌,因为浏览器不允许它读取页面的内容。

如果允许其-header中的域,则脚本evil.com可以读取表单中的令牌。这意味着已明确列入白名单以便能够读取响应内容。example.comAccess-Control-Allow-Originexample.comevil.com