为啥 Express/Connect 会在每个请求上生成新的 CSRF 令牌?
Posted
技术标签:
【中文标题】为啥 Express/Connect 会在每个请求上生成新的 CSRF 令牌?【英文标题】:Why does Express/Connect generate new CSRF token on each request?为什么 Express/Connect 会在每个请求上生成新的 CSRF 令牌? 【发布时间】:2014-03-05 21:54:38 【问题描述】:据我了解,有两种方法可以防止 CSRF 攻击:1) 每个会话的令牌,以及 2) 每个请求的令牌
1) 在第一种情况下,CSRF 令牌仅在用户会话初始化时生成一次。因此,用户一次只有一个有效令牌。
2) 在第二种情况下,每个请求都会生成新的 CSRF 令牌,然后旧的令牌变得无效。 漏洞利用变得更加困难,因为即使攻击者窃取了令牌(通过 XSS)当用户转到下一页时它也会过期。 但另一方面,这种方法会降低 webapp 的可用性。这是来自security.stackexchange.com的一个很好的引用:
例如,如果他们点击“返回”按钮并使用新值提交表单,则提交将失败,并且可能会以一些恶意错误消息迎接他们。如果他们尝试在第二个选项卡中打开资源,他们会发现会话在一个或两个选项卡中随机中断
在分析 Node.js Express 框架(基于 Connect)时,我注意到每个请求都会生成一个新的 CSRF 令牌, 但旧的不会失效。
我的问题是:在每个请求上提供新的 CSRF 令牌而不是使旧的无效的原因是什么? 为什么不只为每个会话生成一个令牌?
谢谢你,对不起我的英语!
【问题讨论】:
【参考方案1】:CSRF 令牌是随机数。它们应该只使用一次(或在很长一段时间后安全使用)。它们用于识别和授权请求。让我们考虑两种预防 CSRF 的方法:
每个会话固定一个令牌:这样做的缺点是客户端可以将其令牌传递给其他人。这可能不是由于嗅探或中间人或某些安全漏洞。这是对用户的背叛。多个客户端可以使用相同的令牌。遗憾的是,对此无能为力。
动态令牌:每当服务器和客户端之间发生任何交互或发生超时时,都会更新令牌。它可以防止多个客户端同时使用旧令牌。
动态令牌的缺点是它限制了从那里返回和继续。在某些情况下,它可能是可取的,例如在实施购物车时,必须重新加载以检查是否有库存。 CSRF 将防止重新发送已发送的表单或重复购买/出售。
细粒度的控制会更好。对于您提到的场景,您可以在没有 CSRF 验证的情况下进行。然后不要对该特定页面使用 CSRF。换句话说,处理每个路由的 CSRF(或其异常)。
更新
我只能想到单个动态令牌优于多个的两个原因:
多个令牌确实更好,但至少有一个像上面那样的动态令牌。这意味着设计一个可能变得复杂的详细工作流程。例如看这里:
-
https://developers.google.com/accounts/docs/OAuth2
https://dev.twitter.com/docs/auth/implementing-sign-twitter
https://developers.facebook.com/docs/facebook-login/access-tokens/
这些是访问其 API(表单提交等)的令牌,而不仅仅是登录。每个人都以不同的方式实现它们。除非有好的用例,否则不值得做。您的网页将大量使用它。更何况现在提交表单已经不简单了。
动态单个令牌是最简单的,并且在库中很容易获得。所以可以在旅途中使用它。
多代币的优势:
-
可以实现事务。您可以在请求之间进行排序。
可以从超时和身份验证错误中回退(您现在必须处理它们)。
安全!比单个令牌更健壮。可以检测令牌滥用、黑名单用户。
顺便说一句,如果您想使用多个令牌,您现在拥有 OAuth2 库。
【讨论】:
感谢您的回答,非常感谢。但它没有描述多个有效令牌比单个有效令牌有什么优势。以上是关于为啥 Express/Connect 会在每个请求上生成新的 CSRF 令牌?的主要内容,如果未能解决你的问题,请参考以下文章
为啥即使未启用 CORS,HTTP 请求也会在 Action 中处理? [复制]