0

I have been trying to understand how CSRF tokens work and from my research, it looks like it is common for the server to provide both a CSRF cookie and a token to the end user. The user then returns it with the subsequent request and the server is able to validate the CSRF token against the CSRF cookie (by way of MAC).

My question is this - The CSRF validation is confirming if the session token is a legit token issued by the server. How do they ensure that the cookie/token combo being returned is the one that was issued for this specific user?

In other words, what is stopping the attacker from initiating a session with the web app, get a CSRF cookie/token, and attach it to the malicious request?

1

2 Answers 2

0

The CSRF token must be tied to the associated session identifier or else someone could generate a CSRF token for their own session then inject their token into the payload forging requests. This is the most common way to validate CSRF tokens, however, there are scenarios where CSRF tokens do not need to be tied to sessions. An example of this is the double-submit technique.

0

In a CSRF attack, the attacker causes the victim to send a request (the Cross-Site Request that is being Forged) to the server. The victim's browser sends its own cookies, not ones the attacker either knows about nor can control (at least, this is the assumption). As such, so long as each user gets a unique anti-CSRF token (it can be totally random, and if it's long enough there is still ~0 risk of collisions), an attacker can't use their own anti-CSRF token for a forged request, because it won't correspond to the victim's cookie (or match the anti-CSRF token expected for the victim using any other method either).

With that said, the "double-submit cookie" pattern that you're describing here is weak, and should be avoided. The problem is that the assumption "attacker can't set cookies for the victim" isn't a very good one. Cookie security is kind of a mess for historical reasons, and while there are ways to protect cookies that have been bolted on over time, they're not yet in widespread use. For example, an attacker can add their own cookie for the site using either a non-HTTPS request that they (as a man-in-the-middle) intercept and return a set-cookie header on (they can do this if the victim ever visits any non-HTTPS site, even if the target site doesn't even listen for plain HTTP!), or by gaining control of any subdomain that shares a root domain with the victim site and setting a cookie scoped to the root. In such cases, the attacker can in fact just get their own anti-CSRF token and anti-CSRF cookie, set the latter on the victim's browser, and then forge requests using the former.

A few much safer patterns than double-submit cookies exist.

  • Session anti-CSRF tokens, stored server-side, are a classic solution. However, they add significant server-side workload (either checking a DB or keeping a cache of valid values in sync across a cluster) on every state-changing request. As such, they are considered unsuited for highly-scalable apps.
  • Anti-CSRF tokens tied to the session/access token, typically via a hash (HMAC isn't needed; if the attacker knows the victim's auth token it's already game over). The server needs some way to identify each user (opaque session token, JWT, whatever), and the added workload to hash this auth token and check it against a submitted anti-CSRF token is trivial).
  • Use of API requests that are not valid "simple" requests for CORS, and as such require a pre-flight. Ways to do this include requiring a content type such as application/json (you do have to actually require that content type, though, not just that the request is parsable as JSON or that the content type header contains the text "application/json" somewhere), or requiring the presence of any custom header (it can be completely static, such as "X-CSRF: no"). Telling the victim's browser to send such a request from any third-party origin will cause a CORS pre-flight request, to which the server will not allow the actual request (unless you fully trust the relevant third-party origin, which you shouldn't in this scenario because it's an attacker-controlled one). CORS is not intended as an anti-CSRF measure, and people try to misuse it as one all the time (e.g. by checking the Origin header alone, which is not present on all cross-site requests!), but the security behavior of pre-flight request requirements is standardized.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.