据我了解,有两种方法可以防止CSRF攻击:1)每个会话令牌,2)每个请求令牌
1)在第一种情况下,初始化用户会话时仅生成一次CSRF令牌。因此,用户只能同时使用一个有效令牌。
2)在第二种情况下,在每个请求上生成新的CSRF令牌,之后旧的CSRF令牌变为无效。 利用vunerability更加困难,因为即使攻击者窃取了令牌(通过XSS),当用户转到下一页时,它也会过期。 但另一方面,这种方法使得webapp不太可用。以下是security.stackexchange.com的好引文:
例如,如果他们点击“后退”按钮并使用新值提交表单,则提交将失败,并且可能会遇到一些恶意错误消息。如果他们尝试在第二个标签中打开资源,他们会发现会话在一个或两个标签中随机中断
在分析Node.js Express框架(基于Connect)时,我注意到每个请求都会生成一个新的CSRF令牌, 但旧版本不会失效。
我的问题是:在每个请求上提供新CSRF令牌而不使旧版本无效的原因是什么? 为什么不在每个会话中生成一个令牌?
谢谢你,对不起我的英文!
答案 0 :(得分:4)
CSRF代币是nonce。它们应该只使用一次(或在很长一段时间后安全使用)。它们用于识别和授权请求。让我们考虑一下防止CSRF的两种方法:
每个会话固定一个令牌:这个缺点是客户端可以将其令牌传递给其他人。这可能不是由于嗅探或中间人或一些安全失误。这是对用户的背叛。多个客户端可以使用相同的令牌。遗憾的是,没有什么可以做的。
动态令牌:每次在服务器和客户端之间发生任何交互时或每当发生超时时,令牌都会更新。它可以防止使用旧版令牌并同时使用多个客户端。
动态令牌的缺点是它限制了返回并从那里继续。在某些情况下,可能需要,如果实施购物车,重新加载必须检查是否有库存。 CSRF将阻止重新发送已发送的表单或重复购买/出售。
细粒度控制会更好。对于您提到的方案,您可以不进行CSRF验证。然后不要将CSRF用于该特定页面。换句话说,每条路线处理CSRF(或其例外)。
<强>更新强>
我只能想到单个动态令牌优于多个的两个原因:
多个令牌确实更好,但至少有一个动态令牌,如上所述。这意味着设计一个可能变得复杂的详细工作流程。例如,请看这里:
这些令牌是访问他们的API(表单提交等)而不仅仅是登录。每个人都以不同方式实现它除非有良好的用例,否则不值得做。您的网页将大量使用它。更不用说表单提交现在并不简单。
动态单一令牌是最简单的,并且可以在库中随时使用。所以可以在旅途中使用它。
多个令牌的优点:
顺便说一下,如果你想使用多个令牌,你现在就拥有了OAuth2库。