4

In a lot of different products the CSRF token is stored in a session.

Which means that if the session has expired then the next form submit will fail.

Example scenario: you open a login form, the session is implicitly created if you didn't have one yet and a CSRF token is persisted in a session and is put as a hidden field of a form.

Then you wait until the session is expired (and garbage collected), then you fill your credentials and submit it.

Now even if the credentials are correct you will see the ugly "CSRF token is invalid" (or something similar) form validation error message.

So the question is: is there a secure way to improve this flow?

PS: ... apart of using AJAX to periodically poll some endpoint to keep the session alive.

zerkms
  • 173
  • 10
  • Just force a relogin by reloading the page to create a new session and CSRF token – Neil Smithline May 10 '15 at 23:42
  • I would still display some sort of message. The mental model of nothing being wrong with authentications failing for no apparent reason contributes to the efficiency of some auth spoofing attacks. – Steve Dodier-Lazaro May 11 '15 at 00:00

2 Answers2

5

(this question might be better suited for the User Experience site)

Change the error message to "We need you to log in again because you were inactive for more than XX minutes." Problem solved.

Let the user know how long they have exactly, because if they have to submit a complex form they need to be aware that they will need to collect whatever information they need and prepare whatever text they must input within a set time. Even better, monitor on which forms sessions tend to reset and use that information to figure out if you must support longer-lasting sessions.

Sometimes users might make a token expire before they even logged in as you pointed out. In that case, a formulation that is generic enough to cover both use cases will remove the need for you to try and test how the session looked like before it expired. You still need to address the confusion that such a message can cause for users who were not logged in before (their mental model might not accommodate the idea that individual forms expire rather than actual sessions).

You can do so by adding a "learn more" or "more details" link on your error message. Clicking that link can then display an additional paragraph that explains (succintly, and in very simple prose!) that Web login forms expire after XX minutes for security reasons, and the user was inactive for too long. You'll still need to ensure that additional text is visible to users without JS.

At this point you might as well implement your idea of serving a fresh CSRF token via AJAX when the user has been inactive for long enough...


Edit: some services directly display a timer indicating for how long the current page will be valid. You could go as far as implement such a timer on a standalone login page. This will at least prepare users to the idea that the page has expired / will expire, and can be especially useful if the page must be entirely refreshed when the timer expires. This being said, thee proper approach remains to never invalidate the existing login page.

XScreensaver login UI with a timer

Steve Dodier-Lazaro
  • 6,798
  • 29
  • 45
  • "Your session has expired because you were inactive for more than XX minutes" --- the thing is that the user hasn't been logged in yet. It's odd to say that to an anonymous user. – zerkms May 10 '15 at 23:55
  • 1
    Are you able to detect that specific case in Web frameworks? This is really a marginal case, so you could use a more generic formulation "We need you to log in again because you were inactive for too long", and possibly a "learn more" link on your error message where you can explain (in very simple prose!) that sessions expire for security measures and the user was inactive for XX minutes before logging in / since they last logged out. – Steve Dodier-Lazaro May 10 '15 at 23:58
  • 1
    "We need you to log in again because you were inactive for too long" --- you're on the login page already. You cannot "log in again" since you was not yet :-) – zerkms May 11 '15 at 01:03
  • 1
    Well that depends whether you have a login form on each page or a dedicated login page! :-) If you want *exact* advice for your site, then we need to have a 15 minute chat about your user base, your use contexts, and your site's UI... But I hope you get the general idea of what to do from the above :-) – Steve Dodier-Lazaro May 11 '15 at 01:05
2

There's always been a trade between UI and security. To my knowledge, CSRF Tokens at login page is to protect against brute-force attack, which might also be achieved by other means like Captcha verification. It may also be abused, if possible, to make victims login to attacker's account and do some nasty stuff, but that's rare, I guess.

The best, I think, is to refresh the token with new one automatically as soon as it gets expired. Implementing plain CSRF Token that remains static throughout a period of time is of no use at all.

1lastBr3ath
  • 909
  • 6
  • 13
  • Please, enough with the "security-usability" trade-off myth. The people who say that are the people who don't understand the concept of a design space. Besides CSRF have to do with XSS attacks and *not* brute-force. Finally the harm caused by marginal and uncommon CSRF token expirations will *never* be anywhere near the harm caused by having legitimate users fill CAPTCHAs. In general, if you feel the need to say things such as "I think", or "I believe" in your answer, it's best to take some time and learn more before you provide answers. Usability engineering is not a matter of opinion. – Steve Dodier-Lazaro May 11 '15 at 00:01
  • OK! Thanks for the clarification, but I don't understand CSRF tokens being used to protect XSS. It would be nice if could provide me with references I can learn these from. – 1lastBr3ath May 11 '15 at 00:26
  • Blargh, I'm mixing myself up too! My bad. CSRF tokens have to do with CSRF, and indeed do not help with XSS (they in fact can be defeated by XSS). I don't get what you meant by brute-force either though. – Steve Dodier-Lazaro May 11 '15 at 00:28
  • Using random tokens at login page requires attackers to obtain the token accordingly, making it hard to automate the brute-force attack. Otherwise, I don't see the use of CSRF tokens in un-authenticated areas, and being able to logged into a victim's machine merely does any harm. – 1lastBr3ath May 11 '15 at 00:34
  • That just doubles the amount of requests, but the time-complexity of a brute-force attack would remain unchanged. CSRF is a type of attack where I can cause users to submit a form on a third-party website (e.g. by creating a link to yourbank.com/sendmoney?to=me&amount=alot). The existence of a CSRF token forces me to first render that form to obtain the token. I won't be able to do so as your existing user session would not be available to me -- I'd need to have stolen your credentials already. See https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet – Steve Dodier-Lazaro May 11 '15 at 00:39
  • Yeah, I know what CSRF attack is, how it's exploited, and in what scenarios. That's what the point here is, you cannot make automated requests without obtaining the token, and if the token is changing or if you're being redirected twice, it's almost impossible to perform a brute-force attack, all due to the token. I'd be glad if you could just let me know the use of CSRF tokens in un-authenticated areas, like in this case. Edited: That's in case of authenticated areas :) – 1lastBr3ath May 11 '15 at 00:46
  • See [this question on our very site about CSRF and brute-forcing](http://security.stackexchange.com/questions/67835/can-anti-csrf-token-prevent-bruteforce-attack). I hope it clarifies. – Steve Dodier-Lazaro May 11 '15 at 00:54