为什么Express / Connect会在每个请求中生成新的CSRF令牌?

时间:2014-02-08 11:35:31

标签: node.js security express csrf

据我了解,有两种方法可以防止CSRF攻击:1)每个会话令牌,2)每个请求令牌

1)在第一种情况下,初始化用户会话时仅生成一次CSRF令牌。因此,用户只能同时使用一个有效令牌。

2)在第二种情况下,在每个请求上生成新的CSRF令牌,之后旧的CSRF令牌变为无效。 利用vunerability更加困难,因为即使攻击者窃取了令牌(通过XSS),当用户转到下一页时,它也会过期。 但另一方面,这种方法使得webapp不太可用。以下是security.stackexchange.com的好引文:

  

例如,如果他们点击“后退”按钮并使用新值提交表单,则提交将失败,并且可能会遇到一些恶意错误消息。如果他们尝试在第二个标签中打开资源,他们会发现会话在一个或两个标签中随机中断

在分析Node.js Express框架(基于Connect)时,我注意到每个请求都会生成一个新的CSRF令牌, 但旧版本不会失效

我的问题是:在每个请求上提供新CSRF令牌而不使旧版本无效的原因是什么? 为什么不在每个会话中生成一个令牌?

谢谢你,对不起我的英文!

1 个答案:

答案 0 :(得分:4)

CSRF代币是nonce。它们应该只使用一次(或在很长一段时间后安全使用)。它们用于识别和授权请求。让我们考虑一下防止CSRF的两种方法:

  1. 每个会话固定一个令牌:这个缺点是客户端可以将其令牌传递给其他人。这可能不是由于嗅探或中间人或一些安全失误。这是对用户的背叛。多个客户端可以使用相同的令牌。遗憾的是,没有什么可以做的。

  2. 动态令牌:每次在服务器和客户端之间发生任何交互时或每当发生超时时,令牌都会更新。它可以防止使用旧版令牌并同时使用多个客户端。

  3. 动态令牌的缺点是它限制了返回并从那里继续。在某些情况下,可能需要,如果实施购物车,重新加载必须检查是否有库存。 CSRF将阻止重新发送已发送的表单或重复购买/出售。

    细粒度控制会更好。对于您提到的方案,您可以不进行CSRF验证。然后不要将CSRF用于该特定页面。换句话说,每条路线处理CSRF(或其例外)。

    <强>更新

    我只能想到单个动态令牌优于多个的两个原因:

    1. 多个令牌确实更好,但至少有一个动态令牌,如上所述。这意味着设计一个可能变得复杂的详细工作流程。例如,请看这里:

      1. https://developers.google.com/accounts/docs/OAuth2
      2. https://dev.twitter.com/docs/auth/implementing-sign-twitter
      3. https://developers.facebook.com/docs/facebook-login/access-tokens/
      4. 这些令牌是访问他们的API(表单提交等)而不仅仅是登录。每个人都以不同方式实现它除非有良好的用例,否则不值得做。您的网页将大量使用它。更不用说表单提交现在并不简单。

      5. 动态单一令牌是最简单的,并且可以在库中随时使用。所以可以在旅途中使用它。

      6. 多个令牌的优点:

        1. 可以实施交易。您可以在请求之间订购。
        2. 可以从超时和身份验证错误中退回(您现在必须处理它们)。
        3. 安全!比单个令牌更强大。可以检测令牌滥用,黑名单用户。
        4. 顺便说一下,如果你想使用多个令牌,你现在就拥有了OAuth2库。