为什么Rails中的CSRF令牌不会阻止多个选项卡正常工作?

时间:2017-12-08 23:01:15

标签: ruby-on-rails csrf-protection

在阅读了有关CSRF保护如何在Rails中工作之后,我试图通过这样做来触发CSRF保护:

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

  1. 访问登录页面。检查meta =>中的CSRF令牌ABC123
  2. 打开第二个浏览器标签,然后访问同一个登录页面。元中的CSRF令牌不同=> def456
  3. 返回第1个标签页。
  4. 提交登录凭据。
  5. 我预计这会失败,因为第二个标签生成了一个新的,不同的CSRF令牌。当登录表单提交时,提交给服务器的令牌是不是旧的,陈旧的?

    但是, 工作:

    1. 访问登录页面。检查meta =>中的CSRF令牌ABC123
    2. 打开第二个浏览器标签,然后访问同一个登录页面。元中的CSRF令牌不同=> def456
    3. 返回第1个标签。
    4. 提交登录凭据。
    5. 退出(清算会话)
    6. 转到第二个标签,然后提交登录信息。
    7. 在这种情况下,我按预期获得InvalidAuthenticityToken异常。为什么呢?

1 个答案:

答案 0 :(得分:4)

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

为什么第二个标签中的请求不会失败

meta标记中的CSRF令牌实际上是两个字符串的串联:每个请求生成一个“一次性填充”,以及与一次性填充异或的“真实”CSRF秘密。请参阅下图,了解一次性打击垫如何添加到蒙版令牌中的XORed字符串中,该字符串存储在meta标记中:

Diagram of construction of CSRF token

Rails将CSRF秘密存储在会话cookie中,无需XORing。应在浏览器中使用Javascript从meta标记中读取屏蔽标记,并将其传递到X-CSRF-TOKEN标题中。

当Rails验证请求时,它:

  1. 拆分X-CSRF-TOKEN标头中传递的值,以检索一次性打击垫和XORed字符串。
  2. 将他们放在一起以找回真正的秘密。
  3. 将其与cookie中的秘密进行比较。
  4. 这就是您在meta标签中看到更改令牌的原因 - 一次性打击垫不同。如果您验证了令牌,则会在两个令牌中找到相同的秘密。

    注意:这种一次性平垫业务似乎没必要。任何人都可以检索真正的秘密,如果他们有掩码令牌。令人惊讶的是,XORing的目的是在每个请求上更改CSRF令牌,这样攻击者就无法使用定时攻击来识别秘密。请参阅this paper on the BREACH SSL attack

    为什么请求在注销时失败

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