【问题标题】:Why does the CSRF token in Rails not prevent multiple tabs from working properly?为什么 Rails 中的 CSRF 令牌不能阻止多个选项卡正常工作?
【发布时间】:2018-05-23 05:34:01
【问题描述】:

在阅读了关于 CSRF 保护在 Rails 中的工作原理之后,我尝试通过这样做来触发 CSRF 保护:

注意:我们正在使用基于 cookie 的会话。

  1. 访问登录页面。检查 meta => abc123 中的 CSRF 令牌
  2. 打开第二个浏览器选项卡,然后访问相同的登录页面。元中的 CSRF 令牌不同 => def456
  3. 返回到第一个标签。
  4. 提交登录凭据。

我预计这会失败,因为第二个选项卡生成了一个新的、不同的 CSRF 令牌。当登录表单提交时,提交给服务器的令牌不应该是旧的,陈旧的吗?

但是,这确实有效:

  1. 访问登录页面。检查 meta => abc123 中的 CSRF 令牌
  2. 打开第二个浏览器选项卡,然后访问相同的登录页面。元中的 CSRF 令牌不同 => def456
  3. 返回到第一个选项卡。
  4. 提交登录凭据。
  5. 注销(清除会话)
  6. 转到第二个选项卡,然后提交登录信息。

在这种情况下,我得到了预期的 InvalidAuthenticityToken 异常。为什么?

【问题讨论】:

标签: ruby-on-rails csrf-protection


【解决方案1】:

来源:https://medium.com/rubyinside/a-deep-dive-into-csrf-protection-in-rails-19fa0a42c0ef

为什么第二个选项卡中的请求没有失败

meta 标签中的 CSRF 令牌实际上是两个字符串的串联:每个请求生成的“一次性填充”,以及与一次性填充异或的“真实”CSRF 秘密。请参见下图,一次性填充是如何添加到掩码令牌中的 XORed 字符串之前的,该字符串存储在 meta 标记中:

Rails 将 CSRF 机密存储在会话 cookie 中,无需异或。应在浏览器中使用 Javascript 从 meta 标记中读取掩码令牌并将其传递到 X-CSRF-TOKEN 标头中。

当 Rails 验证请求时,它:

  1. 拆分X-CSRF-TOKEN 标头中传递的值以检索一次性填充和异或字符串。
  2. 对它们进行异或运算以检索真正的秘密。
  3. 将此与 cookie 中的秘密进行比较。

这就是您在meta 标签中看到更改标记的原因——一次性便笺簿是不同的。如果您验证了令牌,您会在两个令牌中发现相同的秘密。

注意:这种一次性便笺本业务似乎没有必要。任何人只要拥有蒙面令牌,就可以检索真正的秘密。令人惊讶的是,XORing 的目的是在每个请求上更改 CSRF 令牌,这样攻击者就无法使用定时攻击来辨别秘密。见this paper on the BREACH SSL attack

为什么请求在注销时失败

@max's comment 中所述,注销会删除会话 cookie。下一个请求会生成一个新的 CSRF 机密,该机密不再与旧的掩码令牌匹配。

【讨论】:

  • 也许这个问题的答案是一样的? stackoverflow.com/questions/50159847/…, @Sarkom?
  • 因为第一步是检查form_token 是否与session_token 匹配——如果我的第二个标签更新了我的session_token(cookie),那么现在旧标签上不会有任何请求失败是因为session_token != form_token?
  • @Meekohi 是的,但更新 session_token 的唯一方法是注销。 cookie 编码的不仅仅是会话令牌,因此 cookie 可以在每个请求中更改,但会话令牌不会。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-11
  • 1970-01-01
相关资源
最近更新 更多