1

I have a little problem regarding to my CSRF token function (it changes the token every request). Here is the scenario of my problem:

When I opened 2 pages (with same CSRF Token), when I open the first page and submit the form there, the second page's form is not working(because the CSRF Token's value is changed). If you view it from the user's experience it will leave a bad taste, so I need to change it.

My question is, how can I make my CSRF Token function, works in multi-tab browsing, while not affecting the security along with better user experience? Because I want them to have a better user experience without affecting the security of their browsing.

Anders
  • 64,406
  • 24
  • 178
  • 215
googol8080
  • 21
  • 1
  • 4
  • 2
    Possible duplicate of [Why refresh CSRF token per form request?](http://security.stackexchange.com/questions/22903/why-refresh-csrf-token-per-form-request) – SilverlightFox Sep 16 '16 at 07:34
  • 2
    I would recommend just using one CSRF token per user instead. I have so far not heard any argument against that that I find compelling. – Anders Sep 16 '16 at 07:57
  • @SilverlightFox I read that, and the conclusion that I made after reading that is to remove all the tokens in my forms, except in login and signup forms? I can not comment to that thread that is why I made I post here. – googol8080 Sep 16 '16 at 11:53
  • If that is the case I would suggest you link to that question in your post and explain why that answer doesn't fit with your situation. Click [edit] to do this. The accepted answer was explaining to issue new tokens at the point of login, but not to remove them elsewhere. – SilverlightFox Sep 16 '16 at 12:46
  • 1
    Use session CSRF tokens – Neil McGuigan Sep 16 '16 at 17:08
  • @SilverlightFox okay, then my question is not answered then, because, my issue is not like that. – googol8080 Sep 18 '16 at 02:11

2 Answers2

1

Use a single CSRF token per session (rather than per request or per user). For example, the CSRF token can be the plain text session ID, or an encrypted or securely hashed (e.g. HMAC) version of the session key. Or you could store the CSRF token as a session variable that is associated with the session key. These are all common options.

If you're wondering if this makes your site any less secure, read this article for reassurance.

If you happen to be using the ASP.NET framework, the way to do this is simply set the Page.ViewStateUserKey to the session ID.

John Wu
  • 9,101
  • 1
  • 28
  • 39
  • What if an attacker get the csrf token? what will I do ? – googol8080 Sep 19 '16 at 12:20
  • A typical CSRF mitigation assumes that the attacked cannot obtain the CSRF token. If you are concerned about how to guard the token, please start another question. – John Wu Sep 19 '16 at 17:07
  • 2
    Don't use the session ID as the CSRF token, ever. It's a lot more likely that a CSRF token will leak than that a session ID (properly protected) will leak, and increasing the ways a session token could be leaked is a very bad idea. HMACing the session token with a server-side secret is pretty safe (using a completely random CSRF token is better but requires storing additional per-session state). – CBHacking Mar 22 '17 at 18:16
0

We need more details. Are you using a framework?

Furthermore, if you are creating a token for each request, how come two tabs have the same one? It kinda contradicts what you said.

Or maybe I misunderstood and you mean that you have only ONE csrf token "active" at a time. In that case the fix would be easy, allow for multiple CSRF tokens to be valid at the same time (by holding a list of sent ones server side). That way two different tabs have two different tokens, both of which are valid.

daniel f.
  • 281
  • 1
  • 6
  • Hello, thanks for your response, how can I make a list? What do I need? – googol8080 Sep 16 '16 at 07:26
  • Again, this would depend on the technology/framework you are using. Since you are faced with this issue I am guessing you are not using a webapp framework like Django or Rails, as they would take care of this issue. In PHP i would hold the pending tokens in a table together with an expiration date. Every time you get a POST request, you check in that table, if you find the token and it is not expired, you process the request. Otherwise you reject it. I would also make sure that expired tokens get purged once in a while. But I would suggest you use an existing framework! – daniel f. Sep 16 '16 at 07:35
  • 4
    This is mostly a request for more information and not an answer. Please put this in a comment. – Steffen Ullrich Sep 16 '16 at 07:40
  • I was torn, but as the "answer part" was longer than the request for more information I opted for an answer. – daniel f. Sep 16 '16 at 07:43
  • then split this up as comments and an answer – schroeder Sep 16 '16 at 08:08
  • maybe I can use the `password_hash()` function? Then I will set a secret value, for that even if the token is different when I use `password_verify()` it will remain true. Is it okay? – googol8080 Sep 20 '16 at 04:11
  • @googol8080 what would you hash? How often would you change the hashed value? To be honest I think the standard way is better here. Generate a random token, save it serverside, send it to the client. When a post request arrives, check that there is a token and that this token is present in your list of active ones – daniel f. Sep 20 '16 at 04:19
  • But to make a list, I need to make a table in my database and fetch it every time user/s make a `$_POST` requests and check it right? – googol8080 Sep 20 '16 at 04:48
  • @googol8080 yes – daniel f. Sep 20 '16 at 04:51
  • Then it will add more time before the `
    ` will perform right?
    – googol8080 Sep 20 '16 at 05:05
  • @googol8080 it should be negligible. It would really surprise me if you were to notice any measurable delays – daniel f. Sep 20 '16 at 05:08
  • so, every time a page with a form is visited or refreshed, I will insert a token value in the database (this is token-per-user method), then when the `
    ` is submitted, it will check the token and if it is verified, the token value will be deleted in right after that. What do you think?
    – googol8080 Sep 20 '16 at 05:20
  • @googol8080 I'd say it is a token-per-page, but yes, that sounds like the general workflow. I would give the tokens an expiration date tho, so that you can regularly clean that table by removing all expired tokens – daniel f. Sep 20 '16 at 05:22