防止 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 攻击。
我的上述推理有什么问题?我不明白什么?