12

I currently have forms on my page, which are there regardless of if a user is logged in or not. Once a user logs in, they are presented with one of these forms (which use CSRF).

The issue is that if this box is presented after the authentication, the CSRF tokens are invalidated. I have confirmed this by allowing myself to submit the form without authentication checks and $form->isValid() returns true whereas after login, it gives me false with the error of:

The CSRF token is invalid. Please try to resubmit the form.

I guess there are three solutions - stop Symfony from regenerating/invalidating the CSRF tokens on authentication, remove the CSRF tokens from these forms or generate my form after authentication (I'd rather avoid this, however). My current solution is to pass a new CSRF token back with the authentication and set forms token input value.

Additional: Does anyone know how to view all CSRF tokens that are currently assigned? The session doesn't seem to hold them.

Prisoner
  • 27,391
  • 11
  • 73
  • 102
  • The page doesn't reload after the login? – lsouza Aug 09 '13 at 13:53
  • @Hisamu No, the login is done using ajax, so the user logs in and then I open up a form on successful login. This is the point where the tokens become invalidated (seemingly). If I knew where to view all tokens I'd be able to debug this further though. – Prisoner Aug 09 '13 at 13:56
  • Perhaps you could regenerate the other tokens? See: http://stackoverflow.com/a/11632713/209585 – lsouza Aug 09 '13 at 14:05
  • @Hisamu, I had considered this but with the amount of forms I'll end up using I'd rather have symfony not invalidate the csrf tokens! But if I can't, I guess I'll have to go down another route. – Prisoner Aug 09 '13 at 14:11
  • The form is being submitted correctly with ajax? [link](http://stackoverflow.com/a/13155322/712120) Any code snippets? – Dickriven Chellemboyee Aug 12 '13 at 15:59
  • @Chellem not really. I'd have to post a shed load of code for someone to reproduce this. I'm hoping someone has come across this issue before – Prisoner Aug 13 '13 at 13:59
  • While I see your need I think the complication of token invalidation it's probably by design. The CSRF token is intended to give a unique signature to requests in order to deter malicious users who want to automate attacks or hijack other users' sessions. Instead of trying to stop regeneration it seems better to embrace it and find a solution that plays nice with it. – Mark Fox Aug 27 '13 at 22:45
  • @MarkFox I did figure that, and I can see the reasoning for invalidating any request tokens on unauthentication, but I can't really see a good enough reason for invalidating them on authentication. I have found a solution which I have stated in the original question - I was just wondering if anyone else had come across this same issue and found a more elegant solution. – Prisoner Aug 27 '13 at 23:26
  • @Prisoner In my mind it just makes sense that CSRF tokens would be tied to users identities, seems more straightforward. Say a user starts out on http submits a form, then authenticates through https - since the token did not change an an attacker could Man In The Middle or XSS the unecrypted POST, access the token and potentially start messing with an authenticated users session. Obviously this hinges on some specifc assumptions, but a good framework wants to assume the reasonable worst. – Mark Fox Aug 28 '13 at 06:32
  • 1
    If you do not regenerate the CSRF on login, you might become vulnerable to fixation attacks: the attacker creates a session, saves the CSRF key, forces the user into that session with cookie tossing, waits for the user to log in, and can then send forged requests with valid CSRF tokens. – Tgr Sep 03 '13 at 21:03
  • I came back with a link but @Tgr already beat me to the punch; either way here's a link about session fixation: http://cwe.mitre.org/data/definitions/384.html – Mark Fox Oct 25 '13 at 03:44

2 Answers2

0

The usual approach is that when someone logs in successfully, the whole page is refreshed, as potentially different data is going to be displayed, customised to the user.

However if you really don't want to do that, You said:

My current solution is to pass a new CSRF token back with the authentication and set forms token input value.

Just do that. There is nothing wrong with that.

Ben
  • 34,935
  • 6
  • 74
  • 113
0

Thanks to @MarkFox for pointing me to this CWE - although I knew it was through design, I'd hoped there would be a way for me to avoid going down the route I ended up.

For anyone interested, the CWE states:

Authenticating a user, or otherwise establishing a new user session, without invalidating any existing session identifier gives an attacker the opportunity to steal authenticated sessions.

For this reason, I recommend that you go down the path I ended up, sending the new request tokens via AJAX and place them into the relevant forms.

Community
  • 1
  • 1
Prisoner
  • 27,391
  • 11
  • 73
  • 102