Why a CSRF token shouldn’t be passed in a cookie??

KG
4 min readNov 29, 2022

A one-liner for CSRF is “An attacker will be able to induce users to execute unwanted actions that they do not intend to perform” — A well-known definition. For more details, please refer to https://owasp.org/www-community/attacks/csrf.

We know that the remediation of CSRF is to use anti-CSRF tokens, Custom request headers, and a few other defenses in-depth mechanisms as mentioned in OWASP cheatsheet:https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html.

Let’s jump to the main scenario “Why should the token not be passed as a cookie”?

Cookie- Yes or no??

What exactly is a cookie??

A cookie is a small amount of data that the server sends to the user’s browser, and it will use in later requests by the browser for efficient communication and will send those with every request.

Concerning CSRF, What is the impact if CSRF token cookie is passed in every request??

Yes, As the cookie will be sent automatically with all requests by the browser. So only using a token in a cookie defeats the whole purpose of CSRF defense.

Let’s break down this and get an answer by implementing multiple test cases.

I explained a few scenarios for developers on what happens if a CSRF token exists in a cookie.

  1. CSRF token implemented in the session cookie itself:
Session cookie: ABC 
CSRF cookie: ABC;

Here, the cookie maintaining the session is the same as a CSRF cookie. However, it doesn’t serve the purpose of CSRF as, if a user logs into the application, they will have a session cookie by default, and it’s not something unique to prevent CSRF from happening.
So, Not an exemplary implementation.

2. CSRF token implemented as a different cookie from that of session cookie:

Session cookie: ABC
CSRF cookie: DEF;

In this scenario, the CSRF cookie differs from the session cookie. So, yes, that’s correct; one for maintaining the session and another for handling CSRF issues. The problem is when an attacker has a valid CSRF cookie.

If the application is vulnerable to CRLF injection, the attacker can set his valid CSRF cookie value in the victim’s account, generate a CSRF POC through his account, send it to the victim, and boom!!! The CSRF attack had happened.

So, how can an attacker set a cookie here?? It can happen if the application is vulnerable to XSS or, as told through CRLF injection, even though HTTPOnly and Secure attributes are set on the cookie, It can’t prevent CSRF.

So, This implementation is a NO.

3. CSRF token is tied to a non-session cookie+ unique value in the POST body:

Session cookie: ABC;
CSRF cookie: DEF;

POST body: csrftoken: 123;
This is an example of the post-body+cookie scenario

The above-mentioned is an example of the post-body+cookie scenario
In the above use case, an update email functionality is a state-changing function. There are two cookies, one for session maintenance and another for preventing CSRF with a combination of a unique token in the body. Developers have tied the CSRF cookie to the CSRF token in the body, which looks like a good way of implementation.

But the catch is, like the above scenario(2), the attack is possible if the website contains any functionality that allows an attacker to set a cookie. When an attacker has a valid CSRF cookie and the post body value, the attacker can set his CSRF cookie value in the victim’s account. It happens if the application is vulnerable to CRLF injection and an attacker can set a cookie, generate a CSRF POC through his account and send it to the victim, and a CSRF attack happens.

An excellent implementation for this scenario in Portswigger labs to try out gives practical experience.

Even though all cookie attributes such as HTTPonly, Secure and SameSite attributes are set, a CSRF attack is made through cookies by a simple cookie setting functionality.

A point to highlight, The cookie setting mechanism can not only be present in the same application but can also be set even throughout the subdomains of the application.

E.g., CSRF setting behavior on subdomain2.abc.test.com can be leveraged to place a cookie submitted to subdomain1.test.com.

What Should Developers Do?

Don’t use cookie-based implementation. Instead, use a double-submit cookie if required to maintain state-less; otherwise, by default, token-based remediation or through headers. Refer to OWASP for more kinds of implementation.

Conclusion:

Have you got clarity on why cookie-based implementation for CSRF is not correct?

In case of any queries/corrections/enhancements, please dm me.

--

--