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

you*_*786 8 ruby-on-rails csrf-protection

在阅读了CSRF保护在Rails中的工作原理后,我尝试通过执行以下操作来触发CSRF保护:

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

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

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

但是,这确实有效:

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

在这种情况下,我得到一个InvalidAuthenticityToken异常。为什么?

Sar*_*kom 8

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

为什么第二个选项卡中的请求不会失败

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

CSRF代币的构造图

Rails将CSRF机密存储在会话cookie中,而无需进行XORing。浏览器应使用Javascript从meta标记中读取被屏蔽的令牌,并将其传递到X-CSRF-TOKEN标头中。

当Rails验证请求时,它:

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

这就是为什么您会看到标记中的令牌发生更改的原因meta-一次性填充垫有所不同。如果您验证了令牌,则会在两个令牌中找到相同的秘密。

注意:这项一次性垫业务似乎不必要。任何人只要拥有被屏蔽的令牌,都可以检索真实机密。令人惊讶的是,XORing的目的是在每个请求上更改CSRF令牌,以使攻击者无法使用定时攻击来识别机密。有关BREACH SSL攻击,请参阅本文

为什么请求在注销时失败

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