在许多教程和指南中,我看到应该根据请求刷新CSRF令牌。我的问题是为什么我必须这样做?在每个会话中使用单个CSRF令牌是否比在每个请求中生成一个并跟踪所请求的令牌要容易得多?

在每个请求的基础上生成令牌似乎并不能提高安全性。每个会话令牌就已经可以了。唯一的论据似乎是XSS保护,但这并不适用,因为当您遇到XSS漏洞时,脚本仍然可以读出新令牌。

每个请求生成新令牌有什么好处?

#1 楼

出于已经讨论的原因,没有必要为每个请求生成新令牌。它带来了几乎为零的安全优势,并且在可用性方面使您付出了代价:一次只能使用一个令牌,用户将无法正常浏览Web应用程序。例如,如果他们单击“后退”按钮并使用新值提交表单,则提交将失败,并可能向他们发出一些敌对的错误消息。如果他们尝试在第二个选项卡中打开资源,他们会发现会话在一个或两个选项卡中随机中断。通常,不值得牺牲应用程序的可用性来满足这一毫无意义的要求。

在某个地方值得发布新的CSRF令牌:在会话中进行主体更改。也就是说,主要是在登录时。这是为了防止会话固定攻击导致CSRF攻击的可能性。

例如:攻击者访问站点并生成新会话。他们获取会话ID并将其注入受害者的浏览器中(例如,通过从易受攻击的邻居域编写cookie或使用其他漏洞(如jsessionid URL)),还将CSRF令牌注入受害者的浏览器中的一种形式。他们等待受害者使用该表单登录,然后使用另一个表单发布让受害者使用仍然有效的CSRF令牌执行操作。

为防止这种情况,请使CSRF令牌无效并在您已经在对会话ID进行相同操作的地方(例如登录名)发出一个新密码,以防止会话固定攻击。

评论


既然BREACH攻击已经成为现实,那么这个建议仍然有效吗?

– millerdev
17年3月15日在1:08

BREACH攻击应该在另一层解决(通过禁用应用程序数据压缩和TLS压缩),因此答案是:您不必担心BREACH攻击,除非您设置TLS或HTTP服务器

– David天宇黄
18年1月29日,0:44



#2 楼

概述。标准建议是使用对于每个请求都是唯一的唯一CSRF令牌。为什么?因为与每个会话令牌相比,每个请求令牌在某些类型的实现错误上更具弹性。这使得按请求令牌可以说是新Web应用程序开发的最佳选择。另外,没有安全审核员会麻烦您使用按请求的CSRF令牌。

如果您是Web应用程序开发人员,这就是您所需要知道的,您可以在这里停止阅读。 。但是,如果您是安全专家,想知道此建议背后的详细原理,或者想知道如果您确实使用按会话的令牌会带来多大的风险,请继续阅读....


进行更深入的研究。
事实是,如果您的网站中没有其他漏洞,则每个会话一个CSRF令牌即可。没有理由不必一定要为每个请求生成一个新的CSRF令牌。

事实证明,您还会找到著名的安全专家,他们说,另一种抵御CSRF的合理方法是使用cookie两次提交:换句话说,您使用一些客户端Javascript来计算会话cookie的哈希并将其添加到每个POST请求中,并将哈希视为CSRF令牌。您可以看到,这实质上是即时生成的CSRF令牌与整个会话相同。

当然,我知道为什么有人建议为每个请求生成一个新的CSRF令牌这一论点。他们在想,如果您的网站上也存在XSS漏洞,那么如果您在每个会话中使用单个CSRF令牌,则使用XSS来恢复CSRF令牌将很容易,而如果您在每个请求中生成新的CSRF令牌,则会很容易将需要更多的工作来恢复CSRF令牌。就我个人而言,我认为这不是一个令人信服的论点。如果您的站点上存在XSS漏洞,即使您为每个请求生成一个新的CSRF令牌,也仍然可以恢复CSRF令牌,它只需要额外的几行恶意Javascript。无论哪种方式,如果您的站点上存在XSS漏洞,并且您面对的是严重的,知识渊博的攻击者,那么无论您如何生成CSRF令牌,都很难保证安全性。

总体而言,它无法会为每个请求生成一个新的CSRF令牌。也许最好这样做,只是让安全审核员摆脱困境。但是,如果您已经有一个在整个会话中使用单个CSRF令牌的旧版应用程序,那么花钱将其转换为每个请求生成一个新的CSRF令牌可能不会在我的优先级列表中过高:我敢打赌可以找到这笔钱和开发人员精力的其他用途,从而进一步提高安全性。

评论


如果他们推荐双重Cookie提交,我不会称他们为“著名的安全专家”……XSS并不是唯一的问题。 OWASP在这方面有一个很好的总结...

–AVID♦
2012年10月21日,11:15

@Gili双重提交cookie的问题在于,这通常是指正常的,已经存在的会话cookie-JavaScript不应访问该cookie(例如,使用HttpOnly标志)。使用此技术可能会阻止CSRF攻击,但会使会话cookie打开其他问题,例如使其更容易受到可能的XSS漏洞的攻击。有些技术可以很好地工作,而不会引起其他单独的漏洞。

–AVID♦
14年6月27日在8:14

正如security.stackexchange.com/q/61110/5002中所述,@ AviD正是出于这个原因,OWASP指示开发人员为CSRF令牌使用单独的cookie。您可以在会话cookie上保留HttpOnly标志。

–吉利
14-6-27在8:24



@Gili,重新阅读AviD的评论。不要错过他对“通常”一词的使用。通常,将双cookie提交理解为意味着重新使用会话cookie。如果有人建议提交双cookie,而没有明显相反的免责声明,则意味着他们建议重新使用会话cookie。我认为AviD在上面的评论中涵盖了这一点。

– D.W.
14年6月27日在17:15

“为每个请求生成一个新的CSRF令牌都不会受到损害”,这会损害可用性(?)

–pinkpanther
16年5月24日在20:44

#3 楼

XSS可以用来读取CSRF令牌,即使它是一个提交令牌也是如此,这就是孩子的游戏。推荐的单个提交令牌可能来自不了解CSRF的人。

使用“单个提交令牌”的唯一原因是要防止用户意外点击。提交两次。这样做的一个好方法是防止用户两次单击“结帐”并意外向客户收费两次。

CAPTCHA或询问用户当前密码可以用作一种反csrf措施,不能被XSS绕过。

我建议阅读CSRF预防备忘单。

评论


面对XSS,我看不出验证码或输入密码的安全性。它只是迫使攻击者跳了几圈。

– CodesInChaos
2012年10月20日19:00

攻击者必须知道@CodesInChaos,然后才能知道其密码。

–rook
2012年10月20日19:53

如果用户在xss之后的某个时间输入密码,则攻击者可能会窃取它。因此,重新输入密码会有所帮助,但作用不大。

– CodesInChaos
2012年10月20日20:12



@CodesInChaos在纸上可以正常工作,但是这种提议的攻击在现实情况下成功的可能性很小。

–rook
2012年10月20日在20:28

@CodesInChaos您是正确的,CAPTCHA与此无关。另一方面,重新认证(选择性地针对敏感操作)是CSRF的最佳解决方案之一,应使用更多。另请参阅Schneier关于“事务验证”的讨论,尽管没有完全相同,但它们是相似的。

–AVID♦
2012年10月21日,11:12

#4 楼

如果令牌在整个会话中都是相同的,则攻击者可能会从一个页面泄漏令牌并将其用于其他操作。

例如,您可以使用iframe来加载页面,然后使用XSS漏洞提取令牌。从那里,您可以使用该令牌提交密码更改表单

使用每个请求令牌而不是整个会话范围的令牌会更加困难,但这不会阻止CSRF。攻击者可以简单地利用XSS从页面读取令牌,然后将其触发。但是,如果令牌是全局的,而不是局限于该单个页面,则攻击者可以将任何页面作为目标来窃取令牌。为每个请求使用单独的令牌会增加难度。

评论


有人无法从iframe中提取任何内容,这将破坏相同的原始政策

– Philipp Gayret
2012年10月20日14:46



即使每次请求都刷新,也应该可以使用XSS提取令牌。我对吗?

– Emilio
2012年10月20日在16:05



是的,您可以通过XSS将iframe加载到密码更改表单中,然后可以提取该令牌,如果存在XSS漏洞,则生成新令牌不会使任何安全。

– Philipp Gayret
2012年10月20日17:41



@Rook Huh?我从来没有说过使用单个令牌是好的...

–多项式
2012年10月21日,11:56

如果您有XSS漏洞,则可以使用XHR读取任何页面并提交任何请求。在每个页面上使用不同的令牌无济于事。

–rook
2012年10月21日17:37

#5 楼

除其他答案外,如果服务器容易受到BREACH攻击,也可能刷新令牌。

这需要满足以下三个条件:



由使用HTTP级压缩的服务器提供服务
在HTTP响应主体中反映用户输入
在HTTP响应主体中反映秘密(例如CSRF令牌)



要减轻破坏,您将需要刷新GET请求中的CSRF令牌,该请求会加载一个使所有先前令牌无效的表单。这样,创建附加请求以发现页面中令牌的MITM(中间人)每次都会获得一个不同的令牌。这确实意味着真实用户在MITM情况下将无法提交表单。

当然,您还需要满足其他两个条件。为每个会话维护CSRF令牌并为提供表单的任何页面禁用HTTP级压缩可能会更容易。

#6 楼

这不是一个众所周知的事实,但是正常的字符串比较容易受到定时攻击(例如这一点)。长话短说,正常的字符串比较操作(=====)将从左到右逐个字符地比较两个字符串并返回一旦他们在两个字符串的给定位置遇到了不相等的任何字符,则返回false,这在时间上的微小差异被证明是可检测的。

通过使用定时攻击来尝试所有可能的方法

当然,这可以防止实际攻击的发生。通过每次提交带有令牌的请求时创建一个新令牌,就可以防止这种攻击。仅在提交了无效令牌的情况下还重新创建令牌的情况下才起作用,这可能是不希望的,因此,最好使用对时间不敏感的字符串比较函数(例如此函数)来解决此问题。

评论


好的,但是我必须在示例和论文中指出,您列出了理论上的攻击者可以非常精确地测量CPU时钟时间。这台机器没有其他负担,许多语言在执行逐字符检查之前使用预先计算的哈希码进行字符串比较。

– Philipp Gayret
15年7月22日在10:10

恒定时间比较可以并且应该用来减轻这种情况(循环所有字符和异或标志)。

–eckes
16年1月14日在21:46

#7 楼

希望每个请求更改CSRF令牌的原因之一是减轻令牌的压缩泄漏。我的意思是,如果攻击者Eve可以在包含令牌的页面上注入数据,并发送该页面,则Eve可以猜测字符串的第一个字符,并为该页面接收较小的数据集,因为她知道自己猜对了,然后就去了。转到下一个字符。

这类似于定时攻击。

目前(我知道)没有理由仅在HTTP标头中发送令牌时更改令牌。

另一种方法是在发现失败的请求后立即更改令牌,但这可能会导致用户无法提交任何表单。

#8 楼

如果整个会话使用相同的令牌,则攻击者很有可能会使用XSS劫持令牌,并使用受害者的会话进行某些恶意活动,例如更改密码。

他们可以破坏密码通过将iframe放入您正在使用的网站中。

因此,每个请求最好使用一个令牌,以避免攻击者获得对该令牌的访问权。

评论


使用XSS的攻击者可以访问新令牌,这就是整个问题所在。另请参阅对security.stackexchange.com/a/22904/15195的评论

– Philipp Gayret
15年7月28日在9:35