我试图理解CSRF的整个问题和适当的方法来防止它。(我已经阅读、理解并同意的资源:OWASP CSRF预防小抄,关于CSRF的问题)
As I understand it, the vulnerability around CSRF is introduced by the assumption that (from the webserver's point of view) a valid session cookie in an incoming HTTP request reflects the wishes of an authenticated user. But all cookies for the origin domain are magically attached to the request by the browser, so really all the server can infer from the presence of a valid session cookie in a request is that the request comes from a browser which has an authenticated session; it cannot further assume anything about the code running in that browser, or whether it really reflects user wishes. The way to prevent this is to include additional authentication information (the "CSRF token") in the request, carried by some means other than the browser's automatic cookie handling. Loosely speaking, then, the session cookie authenticates the user/browser and the CSRF token authenticates the code running in the browser.
因此,简而言之,如果你正在使用会话cookie来验证你的web应用程序的用户,你还应该在每个响应中添加一个CSRF令牌,并在每个(变异)请求中要求一个匹配的CSRF令牌。然后CSRF令牌进行从服务器到浏览器再到服务器的往返,向服务器证明发出请求的页面是由该服务器批准的(甚至是由该服务器生成的)。
关于我的问题,这是关于往返中用于CSRF令牌的特定传输方法。
这看起来很常见(例如在AngularJS, Django, Rails中),将CSRF令牌作为一个cookie从服务器发送到客户端(即在Set-Cookie报头中),然后让客户端Javascript从cookie中抓取它,并将其作为一个单独的XSRF-TOKEN报头发送回服务器。
(另一种方法是Express推荐的方法,其中服务器生成的CSRF令牌通过服务器端模板展开包含在响应体中,直接附加到将其提供给服务器的代码/标记上,例如作为隐藏的表单输入。这个例子是一种更接近web 1.0的做事方式,但可以推广到一个更偏重于js的客户端。)
Why is it so common to use Set-Cookie as the downstream transport for the CSRF token / why is this a good idea? I imagine the authors of all these frameworks considered their options carefully and didn't get this wrong. But at first glance, using cookies to work around what's essentially a design limitation on cookies seems daft. In fact, if you used cookies as the roundtrip transport (Set-Cookie: header downstream for the server to tell the browser the CSRF token, and Cookie: header upstream for the browser to return it to the server) you would reintroduce the vulnerability you are trying to fix.
I realize that the frameworks above don't use cookies for the whole roundtrip for the CSRF token; they use Set-Cookie downstream, then something else (e.g. a X-CSRF-Token header) upstream, and this does close off the vulnerability. But even using Set-Cookie as the downstream transport is potentially misleading and dangerous; the browser will now attach the CSRF token to every request including genuine malicious XSRF requests; at best that makes the request bigger than it needs to be and at worst some well-meaning but misguided piece of server code might actually try to use it, which would be really bad. And further, since the actual intended recipient of the CSRF token is client-side Javascript, that means this cookie can't be protected with http-only. So sending the CSRF token downstream in a Set-Cookie header seems pretty suboptimal to me.