【发布时间】:2013-12-28 13:58:42
【问题描述】:
我正在尝试了解 CSRF 的整个问题以及预防它的适当方法。 (我已阅读、理解并同意的资源:@987654321@、Questions about CSRF。)
据我了解,围绕 CSRF 的漏洞是由以下假设引入的:(从网络服务器的角度来看)传入 HTTP 请求中的有效会话 cookie 反映了经过身份验证的用户的意愿。但是源域的所有 cookie 都被浏览器神奇地附加到请求上,所以实际上所有服务器可以从请求中是否存在有效会话 cookie 推断出请求来自具有经过身份验证的会话的浏览器;它不能进一步假设在该浏览器中运行的代码,或者它是否真的反映了用户的意愿。防止这种情况的方法是在请求中包含额外的身份验证信息(“CSRF 令牌”),由浏览器自动 cookie 处理以外的其他方式携带。简单地说,会话 cookie 对用户/浏览器进行身份验证,而 CSRF 令牌对在浏览器中运行的代码进行身份验证。
因此,简而言之,如果您使用会话 cookie 来验证 Web 应用程序的用户,您还应该为每个响应添加一个 CSRF 令牌,并在每个(变异)请求中要求一个匹配的 CSRF 令牌。然后 CSRF 令牌从服务器到浏览器再到服务器进行往返,向服务器证明发出请求的页面已由该服务器批准(甚至由该服务器生成)。
关于我的问题,关于该往返中用于该 CSRF 令牌的特定传输方法。
似乎很常见(例如在AngularJS、Django、Rails)将 CSRF 令牌作为 cookie(即在 Set-Cookie 标头中)从服务器发送到客户端,然后在客户端中有 Javascript从 cookie 中刮出它并将其附加为单独的 XSRF-TOKEN 标头以发送回服务器。
(另一种方法是 Express 推荐的方法,其中服务器生成的 CSRF 令牌通过服务器端模板扩展包含在响应正文中,直接附加到将提供它的代码/标记到服务器,例如作为隐藏的表单输入。这个例子是一种更 web 1.0-ish 的做事方式,但可以很好地推广到更重 JS 的客户端。)
为什么使用 Set-Cookie 作为 CSRF 令牌的下游传输如此普遍/为什么这是个好主意?我想所有这些框架的作者都仔细考虑了他们的选择,并没有弄错。但乍一看,使用 cookie 来解决本质上对 cookie 的设计限制似乎很愚蠢。实际上,如果您使用 cookie 作为往返传输(Set-Cookie:下游标头用于服务器告诉浏览器 CSRF 令牌,Cookie:上游标头用于浏览器将其返回给服务器)您将重新引入您的漏洞正在尝试修复。
我意识到上述框架在 CSRF 令牌的整个往返过程中不使用 cookie;他们在下游使用 Set-Cookie,然后在上游使用其他东西(例如 X-CSRF-Token 标头),这确实关闭了漏洞。但即使使用 Set-Cookie 作为下游传输也可能具有误导性和危险性;浏览器现在会将 CSRF 令牌附加到每个请求,包括真正的恶意 XSRF 请求;充其量这会使请求比它需要的更大,最坏的情况是一些善意但被误导的服务器代码实际上可能会尝试使用它,这将是非常糟糕的。此外,由于 CSRF 令牌的实际预期接收者是客户端 Javascript,这意味着该 cookie 不能仅使用 http 来保护。因此,在 Set-Cookie 标头中向下游发送 CSRF 令牌对我来说似乎不太理想。
【问题讨论】:
-
这是一个很好的问题。
-
更奇怪的是,OWASP 声明“不应使用 cookie 传输 CSRF 令牌”。 cheatsheetseries.owasp.org/cheatsheets/…
-
嗯,如果 cookie 上有 SameSite,为什么 CSRF 会成为问题?
-
metamat,那么,答案是什么? (你是否重新引入了你试图修复的漏洞?为什么)。
标签: http security cookies csrf owasp