In many tutorials and guides I see that a CSRF token should be refreshed per request. My question is why do I have to do this? Isn't a single CSRF token per session much easier than generating one per request and keeping track of the ones requested? Generating the token on a per-request basis doesn't seem to improve security beyond what a per-session token would already do. The only argument seems to be XSS protection, but this doesn't apply as when you have a XSS vulnerability the script could read out new tokens anyway. What are the benefits of generating new tokens per request?
103 3 3 bronze badges asked Oct 20, 2012 at 11:15 Philipp Gayret Philipp Gayret 1,433 2 2 gold badges 11 11 silver badges 14 14 bronze badgesFor the reasons already discussed, it is not necessary to generate a new token per request. It brings almost zero security advantage, and it costs you in terms of usability: with only one token valid at once, the user will not be able to navigate the webapp normally. For example if they hit the 'back' button and submit the form with new values, the submission will fail, and likely greet them with some hostile error message. If they try to open a resource in a second tab, they'll find the session randomly breaks in one or both tabs. It is usually not worth maiming your application's usability to satisfy this pointless requirement.
There is one place where it is worth issuing a new CSRF token, though: on principal-change inside a session. That is, primarily, at login. This is to prevent a session fixation attack leading to a CSRF attack possibility.
For example: attacker accesses the site and generates a new session. They take the session ID and inject it into a victim's browser (eg via writing cookie from a vulnerable neighbour domain, or using another vulnerability like jsessionid URLs), and also inject the CSRF token into a form in the victim's browser. They wait for the victim to log in with that form, and then use another form post to get the victim to perform an action with the still-live CSRF token.
To prevent this, invalidate the CSRF token and issue a new one in the places (like login) that you're already doing the same to the session ID to prevent session fixation attacks.
answered Oct 21, 2012 at 20:31 12.7k 1 1 gold badge 28 28 silver badges 42 42 bronze badges Is this advice still valid now that BREACH attacks are a thing? Commented Mar 15, 2017 at 1:08BREACH attacks are supposed to be solved at a different layer (by disabling application data compression AND TLS compression), so the answer is: you shouldn't worry about the BREACH attack unless you're setting up TLS or the HTTP server
Commented Jan 29, 2018 at 0:44@millerdev BREACH attack can be mitigated by applying a random mask to the csrf token on each request while keeping the actual token value unchanged. This prevents BREACH attack as the random mask makes it impossible to guess and also maintains usability because the token's secret value is still the same.
Commented May 6, 2021 at 5:47Overview. The standard advice is to use a unique CSRF token that is unique for each request. Why? Because a per-request token is a bit more resilient to certain kinds of implementation errors than a per-session token. This makes per-request tokens arguably the best choice for new web application development. Also, no security auditor is going to hassle you about using a per-request CSRF token.
If you're a web application developer, this is all you need to know, and you can stop reading here. But if you're a security expert wondering about the detailed rationale behind this advice, or wondering about just how great the risk is if you do use a per-session token, read on.
Digging in a bit deeper. The truth is that, if you don't have any other vulnerabilities in your web site, a single CSRF token per session is OK. There's no reason why you necessarily have to generate a fresh CSRF token per request.
This is demonstrated by the fact that you'll also find reputable security experts who say that another reasonable way to defend against CSRF is to use cookie double-submission: in other words, you use some client-side Javascript which computes a hash of the session cookie and adds that to each POST request, treating the hash as the CSRF token. You can see that this essentially generates on-the-fly a CSRF token that is the same for the entire session.
Of course, I know the argument why some people might recommend generating a new CSRF token for every request. They are thinking, if you also have a XSS vulnerability on your website, then if you use a single CSRF token per session it will be easy to use XSS to recover the CSRF token, whereas if you generate a new CSRF token per request, it will take more work to recover the CSRF token. Personally, I don't find this a terribly compelling argument. If you have a XSS vulnerability on your site, it's still possible to recover CSRF tokens even if you generate a new CSRF token for every request, it just takes a few extra lines of malicious Javascript. Either way, if you have a XSS vulnerability on your site and you face a serious, knowledgeable attacker, it's hard to guarantee security, no matter how you generate your CSRF tokens.
Overall, it can't hurt to generate a new CSRF token for every request. And maybe it's better to do it that way, just to get security auditors off your back. But if you already have a legacy application that uses a single CSRF token for the entire session, spending the money to convert it to generate a new CSRF token for each request probably wouldn't be super-high on my priority list: I bet I could find some other uses for that money and developer energy that would improve security even more.