与多个选项卡的 CSRF 令牌冲突

2022-08-30 21:11:11

我在我的应用程序中构建了CSRF保护,只需在每次页面加载时生成一个随机令牌,将其放入会话中,然后将令牌绑定到tag属性,如下所示:<body>

<body data-csrf-token="csrf_GeJf53caJD6Q5WzwAzfy">

然后,在每个表单操作或ajax请求上,我只需从body标签中获取令牌并将其发送即可。

这很好,除了一个巨大的问题。用户正在打开应用程序的多个选项卡,并且我看到令牌冲突。例如,用户加载第一个页面并生成一个令牌,然后他们切换选项卡,加载另一个页面,从而生成一个新令牌。最后,他们切换回第一页并提交格式操作。这会导致 CSRF 令牌错误无效。

重新构建它的最佳方法是什么,以防止与多个选项卡发生冲突,同时尽可能保持其安全性。

是否只是在登录时生成单个令牌是正确的解决方案,而不是在每次页面加载时生成新令牌?


答案 1

假设你的应用使用 SSL 进行保护,那么在每次页面加载时生成新令牌实际上不会产生任何价值。这并不能阻止利用XSS漏洞的攻击者 - 无论如何,他们都可以访问新生成的令牌。

请记住CSRF令牌的防御措施:恶意的第三方页面盲目地试图将数据发布到您的应用程序,希望用户已登录。在这种攻击中,攻击者永远无法访问CSRF令牌,因此经常更改它没有任何好处。

不要浪费时间和资源来跟踪每个会话的多个令牌。只需在开始时生成一个并完成。


答案 2

您可以在登录时使用单个令牌。正如@Josh3736指出的那样,这很好。

如果确实希望每页有一个令牌,则可以将有效令牌数组存储在 $_SESSION 中。然后,您将在使用单个令牌时使它们过期。您也可以选择在一段时间后使它们过期,但只有当超时短于会话超时,这才有意义。但是,再说一遍,你真正做到了什么?单个令牌对于CSRF目的来说完全没问题。


推荐