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?


3 Answers 3


Because a Session is client based, and a CSRF token is tab based

The Session ID identifies a connection between a Server and a Client Machine, but not what window or tab the client machine is using. As such, you can have 1 tab open and logged into a web service, open a new tab, and that tab is also logged into the service without having to log back in.

This is super convenient for a lot of use cases, but introduces the CSRF vulnerability if your Same Origen Policies are too permissive. In a CSRF attack, a hacker tries to get you to open thier website (or a compromised legitimate website) at the same time that you are logged into another website. Because the the Session Token only says what computer you are connected to, the malicious site can randomly run blind requests hoping that you have a valid session running in another tab or window for a service that they would like to hijack.

What a CSRF token does is it saves itself into a part of memory that is theoretically only accessible by scripts running in that tab. Because JavaScript specifically can not communicate with other tabs on the same machine, it means that an attacker can not call on the CSRF token of another open window or tab to be able to retransmit it.

There are also other protections that certain implementations of CSRF tokens can offer like protecting against retransmit or MitM attacks, but that is not thier primary function.


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.


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.
  • I don't get how the CORs Preflight thing is supposed to work. If a hacker is making a hostile website, then the hacker set the CORs for that website, and can enable cross-origin scripts. A simple AJAX script should then be able to inject all the header information you need in the request as long as the hacker knows what the target website's header is supposed to look like; so, you should still need some kind of CSRF token to generate a session unique header. Am I missing something?
    – Nosajimiki
    Commented Mar 26 at 15:42
  • CORS headers on the attacker site don't mean a thing. CORS does one thing: it pokes holes in the same-origin policy that normally protects a site against attacks from other sites. The attacker would need to control the CORS headers for the victim site, not for their own. As for why this can be used for CSRF protection, one of the features of same-origin policy is that sites can't add headers to cross-origin requests; trying generates a CORS preflight and unless the target server allows the origin site to set that server, the origin site browser will just not send the actual request.
    – CBHacking
    Commented Mar 27 at 10:36
  • I think it is the static header thing I'm struggling to understand more so than the CORS. Preflight options let you restrict what kind of response you accept, so you can require someone to send you something like a custom static header with any request, but anyone who examines thier own network traffic when using your web service will see that all requests include this custom header and know to include it in any AJAX header request that they make as well. As I understand it, the point of a CSRF token being randomized is to prevent this kind of rebroadcast vulnerability.
    – Nosajimiki
    Commented Mar 27 at 16:01
  • You've got two errors. 1) Preflight lets the SERVER restrict what kind of REQUEST you can SEND; it has nothing to do with accepting responses. 2) Unless the server's CORS configuration is very badly screwed up indeed, the server WILL NOT ALLOW a client browser to attach that header on a request from an unfamiliar origin, so it doesn't matter that the attacker knows what the header is, they can't make the victim's browser send it. They could attach it from their own browser (or via curl or similar) but who cares, the point of CSRF is that you do it using somebody else's browser.
    – CBHacking
    Commented Mar 28 at 3:47
  • OMG, I'm being retarded. I got so fixated on the header information itself that I was missing the oblivious SOP stuff at play. Thanks for bearing with me there.
    – Nosajimiki
    Commented Mar 28 at 13:58

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .