为什么在Cookie中放置CSRF预防令牌是很常见的? [英] Why is it common to put CSRF prevention tokens in cookies?

查看:3558
本文介绍了为什么在Cookie中放置CSRF预防令牌是很常见的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图理解CSRF的整个问题和适当的方法来防止它。 (资源我已阅读,理解并同意: OWASP CSRF预防热线表关于CSRF的问题)。



我理解它,CSRF周围的漏洞是由假设(从Web服务器的角度),入站HTTP请求中的有效会话cookie反映已认证用户的愿望引入的。但是原始域的所有cookie是神奇地附加到浏览器的请求,所以真正所有的服务器可以从一个请求的有效会话cookie的存在推断是请求来自具有验证会话的浏览器;它不能进一步假设在该浏览器中运行的代码,或者它是否真的反映用户的意愿。防止这种情况的方法是在请求中包含附加的身份验证信息(CSRF令牌),由浏览器的自动cookie处理以外的某些方式携带。简而言之,会话cookie验证用户/浏览器,CSRF令牌验证在浏览器中运行的代码。



简而言之,如果您使用一个会话cookie来验证您的Web应用程序的用户,您还应该向每个响应添加一个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:头部上游的浏览器返回到服务器)你将重新引入漏洞正在尝试修复。



我意识到上面的框架不使用cookie的整个往返的CSRF令牌;它们使用下游的Set-Cookie,然后使用上游的其他东西(例如X-CSRF-Token头),这样就可以关闭漏洞。但是即使使用Set-Cookie作为下游传输也是有可能误导和危险的;浏览器现在将附加CSRF令牌到每个请求,包括真正的恶意XSRF请求;最好是使请求比它需要的更大,在最坏的情况下,一些很好的,但误导的服务器代码片段可能实际上尝试使用它,这将是真的很糟糕。此外,由于CSRF令牌的实际预期接收者是客户端Javascript,这意味着该cookie不能用http保护。因此,在Set-Cookie头部发送CSRF令牌对我来说似乎不太理想。

解决方案

接触的一种方式是,一旦收到CSRF cookie,它就可以在客户端脚本中的整个应用程序中使用,用于常规表单和AJAX POST。这在JavaScript重型应用程序(例如AngularJS使用的应用程序)中是有意义的(使用AngularJS不要求应用程序是单页应用程序,因此在状态需要在不同的页面请求之间流动时是有用的,其中CSRF值



请在典型应用程序中考虑以下场景和过程,以描述每种方法的某些优点和缺点。这些基于同步器令牌模式



请求正文方法




  1. 用户已成功登录。


  2. 如果尚未为此会话生成,服务器将生成CSRF令牌,存储

  3. 服务器检查隐藏字段是否匹配会话存储的令牌。
  4. li>



优点





缺点




  • 所有表单必须在HTML中输出隐藏字段。

  • 任何AJAX POST都必须包含该值。 li>
  • 页面必须提前知道它需要CSRF令牌,因此它可以将其包含在页面内容中,因此所有页面必须在某处包含令牌值,这可能会使实施一个大网站。



自定义HTTP标头(下游)




  1. 用户成功登录。

  2. 服务器发出验证Cookie。

  3. 用户点击导航到表单。

  4. 在浏览器中加载页面,然后发出AJAX请求以检索CSRF令牌。

  5. 服务器生成CSRF令牌(如果尚未为会话生成),将其存储在用户会话中,并将其输出到
    头。

  6. 用户提交表单(令牌通过隐藏字段发送)。

  7. 服务器检查隐藏字段是否匹配会话存储的令牌。



优点





缺点




  • 如果没有AJAX请求就无法获取标题值。

  • 所有表单都必须动态添加到HTML。

  • 任何AJAX POST都必须包含该值。

  • 页面必须首先发出AJAX请求才能获取CSRF令牌,










$ b b

自定义HTTP标头(上游)




  1. 用户已成功登录。

  2. 服务器问题auth cookie。

  3. 用户点击导航到表单。

  4. 如果尚未为此会话生成CSRF,服务器会生成CSRF令牌,将其存储在用户会话中,并在页面内容中输出。

  5. 用户通过AJAX提交表单(令牌通过头发送)。




  6. 优点





    缺点




    • 不适用于表单。

    • 所有AJAX POST必须包含标题。



    自定义HTTP标头(上游和下游)




    1. 用户已成功登录。

    2. 服务器发出验证Cookie。

    3. 用户点击导航到表单。

    4. 在浏览器中加载页面,然后发出AJAX请求以检索CSRF令牌。

    5. 服务器生成CSRF令牌(如果尚未为会话生成),将其存储在用户会话中,并将其输出到
      头。

    6. 用户通过AJAX提交表单(令牌通过标头发送)。




    7. 优点





      缺点




      • 不能使用表单。

      • 所有AJAX POST都必须包含该值。




      Set-Cookie h1>


      1. 用户已成功登录。

      2. 服务器发出验证cookie。

      3. <
      4. 服务器生成CSRF令牌,将其存储在用户会话中,并将其输出到cookie。

      5. 用户通过AJAX或通过HTML表单提交表单。

      6. 服务器检查自定义标头(或隐藏的表单字段)是否匹配会话存储的令牌。

      7. 在浏览器中用于附加的AJAX和表单请求,而不需要对服务器检索CSRF令牌的额外请求。



      优点




      • 易于实施。

      • 适用于AJAX。


      • 不一定需要一个AJAX请求来获取cookie值。任何HTTP请求都可以检索它,并且可以通过JavaScript将其附加到所有表单/ AJAX请求。

      • 一旦CSRF令牌已被检索,因为它存储在cookie中,



      缺点




      • 所有表单都必须动态添加到HTML中。

      • 任何AJAX POST都必须包含该值。

      • 每个请求(即图像,CSS,JS等的所有GET,不涉及CSRF过程)增加请求大小。
      • Cookie不能< a href =https://www.owasp.org/index.php/HttpOnly>仅限HTTP。



      因此,cookie方法是相当动态的,提供一种简单的方法来检索cookie值(任何HTTP请求)并使用它(JS可以自动将值添加到任何形式,它可以在AJAX请求中作为标头或形式值)。一旦为会话接收到CSRF令牌,就不需要重新生成它,因为使用CSRF漏洞的攻击者没有检索此令牌的方法。如果恶意用户尝试在上述任何方法中读取用户的CSRF令牌,则这将由相同来源政策。如果恶意用户尝试检索CSRF令牌服务器端(例如通过 curl ),则此令牌将不会关联到同一用户帐户,因为受害者的auth会话cookie将会从请求中丢失(它将是攻击者的 - 因此它不会与服务器端与受害者的会话相关联)。



      以及同步程式令牌样式还有双重提交Cookie CSRF预防方法,它当然使用cookie来存储一种类型的CSRF令牌。这更容易实现,因为它不需要CSRF令牌的任何服务器端状态。实际上,当使用此方法时,CSRF令牌可以是标准的认证cookie,并且该值通过cookie像请求一样通过cookie提交,但是值也在隐藏字段或头中重复,其中攻击者不能复制为他们不能读取值在第一位。然而,建议选择另一个cookie,而不是认证cookie,以便认证cookie可以通过标记为HttpOnly来保护。因此,这是您使用基于Cookie的方法来查找CSRF预防的另一个常见原因。


      I'm trying to understand the whole issue with CSRF and appropriate ways to prevent it. (Resources I've read, understand, and agree with: OWASP CSRF Prevention CHeat Sheet, Questions about 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.

      So in a nutshell, if you're using a session cookie to authenticate users of your web application, you should also add a CSRF token to each response, and require a matching CSRF token in each (mutating) request. The CSRF token then makes a roundtrip from server to browser back to server, proving to the server that the page making the request is approved by (generated by, even) that server.

      On to my question, which is about the specific transport method used for that CSRF token on that roundtrip.

      It seems common (e.g. in AngularJS, Django, Rails) to send the CSRF token from server to client as a cookie (i.e. in a Set-Cookie header), and then have Javascript in the client scrape it out of the cookie and attach it as a separate XSRF-TOKEN header to send back to the server.

      (An alternate method is the one recommended by e.g. Express, where the CSRF token generated by the server is included in the response body via server-side template expansion, attached directly to the code/markup that will supply it back to the server, e.g. as a hidden form input. That example is a more web 1.0-ish way of doing things, but would generalize fine to a more JS-heavy client.)

      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.

      解决方案

      A good reason, which you have sort of touched on, is that once the CSRF cookie has been received, it is then available for use throughout the application in client script for use in both regular forms and AJAX POSTs. This will make sense in a JavaScript heavy application such as one employed by AngularJS (using AngularJS doesn't require that the application will be a single page app, so it would be useful where state needs to flow between different page requests where the CSRF value cannot normally persist in the browser).

      Consider the following scenarios and processes in a typical application for some pros and cons of each approach you describe. These are based on the Synchronizer Token Pattern.

      Request Body Approach

      1. User successfully logs in.
      2. Server issues auth cookie.
      3. User clicks to navigate to a form.
      4. If not yet generated for this session, server generates CSRF token, stores it against the user session and outputs it to a hidden field.
      5. User submits form.
      6. Server checks hidden field matches session stored token.

      Advantages

      • Simple to implement.
      • Works with AJAX.
      • Works with forms.
      • Cookie can actually be HTTP Only.

      Disadvantages

      • All forms must output the hidden field in HTML.
      • Any AJAX POSTs must also include the value.
      • The page must know in advance that it requires the CSRF token so it can include it in the page content so all pages must contain the token value somewhere, which could make it time consuming to implement for a large site.

      Custom HTTP Header (downstream)

      1. User successfully logs in.
      2. Server issues auth cookie.
      3. User clicks to navigate to a form.
      4. Page loads in browser, then an AJAX request is made to retrieve the CSRF token.
      5. Server generates CSRF token (if not already generated for session), stores it against the user session and outputs it to a header.
      6. User submits form (token is sent via hidden field).
      7. Server checks hidden field matches session stored token.

      Advantages

      Disadvantages

      • Doesn't work without an AJAX request to get the header value.
      • All forms must have the value added to its HTML dynamically.
      • Any AJAX POSTs must also include the value.
      • The page must make an AJAX request first to get the CSRF token, so it will mean an extra round trip each time.
      • Might as well have simply output the token to the page which would save the extra request.

      Custom HTTP Header (upstream)

      1. User successfully logs in.
      2. Server issues auth cookie.
      3. User clicks to navigate to a form.
      4. If not yet generated for this session, server generates CSRF token, stores it against the user session and outputs it in the page content somewhere.
      5. User submits form via AJAX (token is sent via header).
      6. Server checks custom header matches session stored token.

      Advantages

      Disadvantages

      • Doesn't work with forms.
      • All AJAX POSTs must include the header.

      Custom HTTP Header (upstream & downstream)

      1. User successfully logs in.
      2. Server issues auth cookie.
      3. User clicks to navigate to a form.
      4. Page loads in browser, then an AJAX request is made to retrieve the CSRF token.
      5. Server generates CSRF token (if not already generated for session), stores it against the user session and outputs it to a header.
      6. User submits form via AJAX (token is sent via header) .
      7. Server checks custom header matches session stored token.

      Advantages

      Disadvantages

      • Doesn't work with forms.
      • All AJAX POSTs must also include the value.
      • The page must make an AJAX request first to get the CRSF token, so it will mean an extra round trip each time.

      Set-Cookie

      1. User successfully logs in.
      2. Server issues auth cookie.
      3. User clicks to navigate to a form.
      4. Server generates CSRF token, stores it against the user session and outputs it to a cookie.
      5. User submits form via AJAX or via HTML form.
      6. Server checks custom header (or hidden form field) matches session stored token.
      7. Cookie is available in browser for use in additional AJAX and form requests without additional requests to server to retrieve the CSRF token.

      Advantages

      • Simple to implement.
      • Works with AJAX.
      • Works with forms.
      • Doesn't necessarily require an AJAX request to get the cookie value. Any HTTP request can retrieve it and it can be appended to all forms/AJAX requests via JavaScript.
      • Once the CSRF token has been retrieved, as it is stored in a cookie the value can be reused without additional requests.

      Disadvantages

      • All forms must have the value added to its HTML dynamically.
      • Any AJAX POSTs must also include the value.
      • The cookie will be submitted for every request (i.e. all GETs for images, CSS, JS, etc, that are not involved in the CSRF process) increasing request size.
      • Cookie cannot be HTTP Only.

      So the cookie approach is fairly dynamic offering an easy way to retrieve the cookie value (any HTTP request) and to use it (JS can add the value to any form automatically and it can be employed in AJAX requests either as a header or as a form value). Once the CSRF token has been received for the session, there is no need to regenerate it as an attacker employing a CSRF exploit has no method of retrieving this token. If a malicious user tries to read the user's CSRF token in any of the above methods then this will be prevented by the Same Origin Policy. If a malicious user tries to retrieve the CSRF token server side (e.g. via curl) then this token will not be associated to the same user account as the victim's auth session cookie will be missing from the request (it would be the attacker's - therefore it won't be associated server side with the victim's session).

      As well as the Synchronizer Token Pattern there is also the Double Submit Cookie CSRF prevention method, which of course uses cookies to store a type of CSRF token. This is easier to implement as it does not require any server side state for the CSRF token. The CSRF token in fact could be the standard authentication cookie when using this method, and this value is submitted via cookies as usual with the request, but the value is also repeated in either a hidden field or header, of which an attacker cannot replicate as they cannot read the value in the first place. It would be recommended to choose another cookie however, other than the authentication cookie so that the authentication cookie can be secured by being marked HttpOnly. So this is another common reason why you'd find CSRF prevention using a cookie based method.

      这篇关于为什么在Cookie中放置CSRF预防令牌是很常见的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆