在阅读了有关CSRF保护如何在Rails中工作之后,我试图通过这样做来触发CSRF保护:
注意:我们正在使用基于cookie的会话。
我预计这会失败,因为第二个标签生成了一个新的,不同的CSRF令牌。当登录表单提交时,提交给服务器的令牌是不是旧的,陈旧的?
但是, 工作:
在这种情况下,我按预期获得InvalidAuthenticityToken异常。为什么呢?
答案 0 :(得分:4)
来源:https://medium.com/rubyinside/a-deep-dive-into-csrf-protection-in-rails-19fa0a42c0ef
meta
标记中的CSRF令牌实际上是两个字符串的串联:每个请求生成一个“一次性填充”,以及与一次性填充异或的“真实”CSRF秘密。请参阅下图,了解一次性打击垫如何添加到蒙版令牌中的XORed字符串中,该字符串存储在meta
标记中:
Rails将CSRF秘密存储在会话cookie中,无需XORing。应在浏览器中使用Javascript从meta
标记中读取屏蔽标记,并将其传递到X-CSRF-TOKEN
标题中。
当Rails验证请求时,它:
X-CSRF-TOKEN
标头中传递的值,以检索一次性打击垫和XORed字符串。这就是您在meta
标签中看到更改令牌的原因 - 一次性打击垫不同。如果您验证了令牌,则会在两个令牌中找到相同的秘密。
注意:这种一次性平垫业务似乎没必要。任何人都可以检索真正的秘密,如果他们有掩码令牌。令人惊讶的是,XORing的目的是在每个请求上更改CSRF令牌,这样攻击者就无法使用定时攻击来识别秘密。请参阅this paper on the BREACH SSL attack。
如@max's comment所述,注销会删除会话cookie。下一个请求会生成一个新的CSRF密钥,该秘密不再与旧的掩码令牌匹配。