为什么Rails中的CSRF令牌不会阻止多个选项卡正常工作? [英] Why does the CSRF token in Rails not prevent multiple tabs from working properly?

查看:74
本文介绍了为什么Rails中的CSRF令牌不会阻止多个选项卡正常工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

p>


  1. 访问登录页面。在meta => abc123

  2. 中检查CSRF令牌。打开第二个浏览器选项卡,并访问相同的登录页面。 meta中的CSRF令牌不同=> def456

  3. 返回第一个标签。

  4. 提交登录凭据。

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



但是,此确实有效


  1. 访问登录页面。在meta => abc123

  2. 中检查CSRF令牌。打开第二个浏览器选项卡,并访问相同的登录页面。 meta中的CSRF令牌不同=> def456

  3. 返回第一个标签。

  4. 提交登录凭据。

  5. 注销(清除会话)

  6. 转到第二个选项卡,然后提交登录

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

解决方案

来源:



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



Rails验证请求时,它会:


  1. 拆分在 X-CSRF-TOKEN 标头中传递的值以检索一次性填充和XORed字符串。

  2. 将它们一起异或检索真正的秘密。

  3. 将其与Cookie中的秘密进行比较。

这是为什么您在 meta 标记中看到更改令牌的原因–一次性垫不同。如果您验证了令牌,则会在两个令牌中找到相同的机密。



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



为什么请求注销失败



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


After reading about how the CSRF protection works in Rails, I tried to trigger CSRF protection by doing this:

Note: We are using cookie based sessions.

  1. Visit login page. Check CSRF token in meta => abc123
  2. Open a 2nd browser tab, and visit the same login page. CSRF token in meta is different => def456
  3. Go back to 1st tab.
  4. Submit login credentials.

I expected this to fail, because the 2nd tab generated a new, different CSRF token. When the login form submits, shouldn't the token that gets submitted to the server be an old, stale one?

However, this does work:

  1. Visit login page. Check CSRF token in meta => abc123
  2. Open a 2nd browser tab, and visit the same login page. CSRF token in meta is different => def456
  3. Go back to 1st tab.
  4. Submit login credentials.
  5. Logout (clearing session)
  6. Go to 2nd tab, and submit login.

In this case, I get an InvalidAuthenticityToken exception as expected. Why?

解决方案

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

Why the request in the second tab doesn't fail

The CSRF token in the meta tag is actually a concatenation of two strings: a "one-time pad" generated per request, and the "real" CSRF secret XORed with the one-time pad. See in the diagram below how the one-time pad is prepended to the XORed string in the masked token, which gets stored in the meta tag:

Rails stores the CSRF secret in a session cookie without XORing. Javascript should be used in the browser to read the masked token from the meta tag and pass it in the X-CSRF-TOKEN header.

When Rails validates a request, it:

  1. Splits the value passed in the X-CSRF-TOKEN header to retrieve the one-time pad and XORed string.
  2. XORs them together to retrieve the real secret.
  3. Compares this with the secret in the cookie.

This is why you are seeing changing tokens in the meta tag -- the one-time pads are different. If you validated the tokens, you would find the same secret in both tokens.

Note: This one-time pad business might seem unnecessary. Anyone can retrieve the real secret if they have the masked token. Surprisingly, the purpose of the XORing is to change the CSRF token on every request so an attacker can't use timing attacks to discern the secret. See this paper on the BREACH SSL attack.

Why the request fails on logout

As noted in @max's comment, logging out deletes the session cookie. The next request generates a new CSRF secret which no longer matches the older masked tokens.

这篇关于为什么Rails中的CSRF令牌不会阻止多个选项卡正常工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆