在阅读了 Rails 中 CSRF 保护的工作原理后,我尝试通过执行以下操作来触发 CSRF 保护:
注意:我们使用基于 cookie 的会话。
- 访问登录页面。检查元中的 CSRF 令牌 => abc123
- 打开第二个浏览器选项卡,然后访问相同的登录页面。元中的 CSRF 令牌不同 => def456
- 返回第一个选项卡。
- 提交登录凭据。
我预计这会失败,因为第二个选项卡生成了一个新的、不同的 CSRF 令牌。当登录表单提交时,提交到服务器的令牌不应该是旧的、过时的令牌吗?
然而,这does work:
- 访问登录页面。检查元中的 CSRF 令牌 => abc123
- 打开第二个浏览器选项卡,然后访问相同的登录页面。元中的 CSRF 令牌不同 => def456
- 返回第一个选项卡。
- 提交登录凭据。
- 注销(清除会话)
- 转到第二个选项卡,然后提交登录。
在这种情况下,我按预期收到 InvalidAuthenticityToken 异常。为什么?
Source: https://medium.com/rubyinside/a-deep-dive-into-csrf-protection-in-rails-19fa0a42c0ef https://medium.com/rubyinside/a-deep-dive-into-csrf-protection-in-rails-19fa0a42c0ef
为什么第二个选项卡中的请求没有失败
CSRF 令牌位于meta
标签实际上是两个字符串的串联:每个请求生成的“一次性密码本”,以及与一次性密码本进行异或运算的“真实”CSRF 秘密。请参见下图,一次性填充如何添加到屏蔽令牌中的异或字符串之前,该字符串存储在meta
tag:
Rails 将 CSRF 秘密存储在会话 cookie 中,而不进行异或运算。应该在浏览器中使用 JavaScript 从meta
标记并将其传递到X-CSRF-TOKEN
header.
当 Rails 验证请求时,它:
- 分割传入的值
X-CSRF-TOKEN
用于检索一次性填充和异或字符串的标头。
- 将它们异或在一起以检索真正的秘密。
- 将其与 cookie 中的秘密进行比较。
这就是为什么您会看到令牌不断变化的原因meta
标签——一次性便签本是不同的。如果您验证了令牌,您会在两个令牌中发现相同的秘密。
Note:这种一次性便笺业务似乎没有必要。如果任何人拥有被掩盖的令牌,他们都可以检索真正的秘密。令人惊讶的是,XORing 的目的是在每个请求上更改 CSRF 令牌,以便攻击者无法使用定时攻击来辨别秘密。看本文介绍 BREACH SSL 攻击 http://breachattack.com/resources/BREACH%20-%20SSL,%20gone%20in%2030%20seconds.pdf.
为什么请求在注销时失败
如中所述@max的评论 https://stackoverflow.com/questions/47723379/why-does-the-csrf-token-in-rails-not-prevent-multiple-tabs-from-working-properly#comment82408038_47723379,注销会删除会话 cookie。下一个请求会生成一个新的 CSRF 密钥,该密钥不再与旧的屏蔽令牌相匹配。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)