在许多教程和指南中,我看到应该根据请求刷新 CSRF 令牌。我的问题是为什么我必须这样做?每个会话单个 CSRF 令牌不是比每个请求生成一个并跟踪请求的令牌更容易吗?
在每个请求的基础上生成令牌似乎并没有提高每个会话令牌已经做的安全性。唯一的论点似乎是 XSS 保护,但这并不适用,因为当您有 XSS 漏洞时,脚本无论如何都可以读取新令牌。
每个请求生成新令牌有什么好处?
在许多教程和指南中,我看到应该根据请求刷新 CSRF 令牌。我的问题是为什么我必须这样做?每个会话单个 CSRF 令牌不是比每个请求生成一个并跟踪请求的令牌更容易吗?
在每个请求的基础上生成令牌似乎并没有提高每个会话令牌已经做的安全性。唯一的论点似乎是 XSS 保护,但这并不适用,因为当您有 XSS 漏洞时,脚本无论如何都可以读取新令牌。
每个请求生成新令牌有什么好处?
由于已经讨论过的原因,没有必要为每个请求生成一个新令牌。它带来了几乎为零的安全优势,并且在可用性方面付出了代价:一次只有一个有效令牌,用户将无法正常浏览 web 应用程序。例如,如果他们点击“返回”按钮并使用新值提交表单,则提交将失败,并且可能会以一些敌对的错误消息迎接他们。如果他们尝试在第二个选项卡中打开资源,他们会发现会话在一个或两个选项卡中随机中断。通常不值得破坏应用程序的可用性来满足这种毫无意义的要求。
不过,有一个地方值得发行新的 CSRF 令牌:在会话内的主体更改时。也就是说,主要是在登录时。这是为了防止会话固定攻击导致 CSRF 攻击的可能性。
例如:攻击者访问该站点并生成一个新会话。他们获取会话 ID 并将其注入受害者的浏览器(例如,通过从易受攻击的邻居域写入 cookie,或使用 jsessionid URL 等其他漏洞),并将 CSRF 令牌注入受害者浏览器中的表单。他们等待受害者使用该表单登录,然后使用另一个表单帖子让受害者使用仍然存在的 CSRF 令牌执行操作。
为防止这种情况,请使 CSRF 令牌无效并在您已经对会话 ID 执行相同操作的位置(如登录)发出一个新令牌,以防止会话固定攻击。
概述。标准建议是使用对每个请求都是唯一的唯一 CSRF 令牌。为什么?因为按请求令牌比按会话令牌更能抵御某些类型的实现错误。这使得按请求令牌可以说是新 Web 应用程序开发的最佳选择。此外,没有安全审计员会为使用每个请求的 CSRF 令牌而烦恼。
如果您是 Web 应用程序开发人员,这就是您需要了解的全部内容,您可以在此处停止阅读。但是,如果您是一名安全专家,想知道此建议背后的详细理由,或者想知道如果您确实使用按会话令牌的风险有多大,请继续阅读......
挖得更深一些。 事实是,如果您的网站没有任何其他漏洞,则每个会话一个 CSRF 令牌是可以的。没有理由必须为每个请求生成一个新的 CSRF 令牌。
这一点可以通过以下事实来证明:您还会找到著名的安全专家,他们说防御 CSRF 的另一种合理方法是使用 cookie 双重提交:换句话说,您使用一些客户端 Javascript 来计算session cookie 并将其添加到每个 POST 请求中,将哈希视为 CSRF 令牌。您可以看到,这实质上会即时生成一个 CSRF 令牌,该令牌对于整个会话都是相同的。
当然,我知道为什么有些人可能会建议为每个请求生成一个新的 CSRF 令牌的论点。他们在想,如果您的网站上也存在 XSS 漏洞,那么如果您在每个会话中使用单个 CSRF 令牌,那么使用 XSS 来恢复 CSRF 令牌将很容易,而如果您为每个请求生成一个新的 CSRF 令牌,它将需要更多的工作来恢复 CSRF 令牌。就个人而言,我不认为这是一个非常有说服力的论点。如果您的网站存在 XSS 漏洞,即使您为每个请求生成一个新的 CSRF 令牌,仍然可以恢复 CSRF 令牌,只需要多行几行恶意 Javascript。无论哪种方式,如果您的网站上存在 XSS 漏洞,并且您面临一个严重的、知识渊博的攻击者,那么无论您如何生成 CSRF 令牌,都很难保证安全性。
总的来说,为每个请求生成一个新的 CSRF 令牌并没有什么坏处。也许这样做更好,只是为了让安全审计员远离你。但是,如果您已经有一个遗留应用程序在整个会话中使用单个 CSRF 令牌,那么花钱将其转换为为每个请求生成一个新的 CSRF 令牌在我的优先级列表中可能不会超高:我打赌我可以为这笔钱和开发人员的精力找到一些其他用途,从而进一步提高安全性。
XSS 可以用来读取一个 CSRF 令牌,即使它是单个提交令牌,那也是小菜一碟。单个提交令牌的建议可能来自不了解 CSRF 的人。
使用“单一提交令牌”的唯一原因是您想防止用户意外单击提交两次。这样做的一个很好的用途是防止用户点击两次“结帐”并意外向客户收取两次费用。
验证码或询问用户当前密码可用作 XSS 无法绕过的反 csrf 措施。
我建议阅读CSRF 预防备忘单。
如果整个会话中的令牌相同,则攻击者可能会从一个页面泄漏令牌并将其用于不同的操作。
例如,您可以使用 iframe 加载页面,然后使用 XSS 漏洞提取令牌。从那里,您可以使用该令牌提交密码更改表单
使用每个请求令牌而不是会话范围令牌会使其变得更加困难,但它不会阻止 CSRF。攻击者可以简单地利用 XSS 从页面读取令牌,然后将其关闭。但是,如果令牌是全局的而不是仅限于单个页面,则攻击者可以针对任何页面来窃取令牌。为每个请求使用单独的令牌会使这变得更加困难。