3

Do we need to compromise on back button navigation if we use one CSRF-token per request instead of one token per session?

(I was successful in using one token per session without any navigation problems but not able to do the same with one CSRF-token per request.)

Anders
  • 64,406
  • 24
  • 178
  • 215
Girish
  • 53
  • 4
  • I would argue there is no or little benefit in using one token per request. See this question: http://security.stackexchange.com/questions/22903/why-refresh-csrf-token-per-form-request – Anders Jun 14 '16 at 06:12
  • 2
    A possible solution might be the cache-control directives, and forcing the browser to make an actual new request when the user hits the back button. Might be a bit tricky to test on all browsers and can introduce performance issues, tho. – bayo Jun 14 '16 at 06:19

2 Answers2

1

The solution used in my Web-Applications (JSF) is to tell the browser to make a new GET-Request on browser-back (or reopen tab). This is done with the following HTTP Response Header:

Cache-Control: no-store, no-cache, must-revalidate
Expires: [in the past]

The first line is for HTTP 1.1, the second line is for Proxy-Servers.
This should work (at least) in all major browsers.

For details see this answer over at StackOverflow

DaniEll
  • 266
  • 2
  • 8
  • 1
    This does solve the problem, but as @bayo15 said in a comment, it comes with a performance hit. – Anders Jun 14 '16 at 08:35
  • @DanEll: The pragma directive does not do what you think it does. And if you must accomodate proxies which incorrectly downgrade the protocol, then use an expires date IN THE PAST to prevent caching. – symcbean Jun 14 '16 at 09:19
  • @symcbean yes you are right - i am not using the pragma-header, i copied it from the linked answer but removed it now... – DaniEll Jun 14 '16 at 09:24
0

I think you are wasting your time trying to implement per request tokens. D.W. explains it in this answer:

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.

That said, if you still want to do this perhaps the following approach would work:

  • When a form loads, do an AJAX call with JavaScript to getCsrfToken.php or something like that. Make sure you have strict CORS on this one.
  • On the server side, generate a random token if the session is valid, and send it back to the client.
  • You may want to unvalidate all older tokens for that session. However, this will cause issues if the user has your site open in multiple tabs. On the other side, if you don't, whats the point?

I just dreamed up this solution now, so see it more as a suggestion to be evaluated than as a definitive secure answer.

Anders
  • 64,406
  • 24
  • 178
  • 215
  • While DW makes an interesting point, the entire answer is predicated on there being a XSS vulnerability in the page; a CSRF vulnerability can exist in the absence of an XSS vulnerability. – symcbean Jun 14 '16 at 09:05
  • @symcbean Yes, it can. But how does the per request (as opposed to per session) token help you then? – Anders Jun 14 '16 at 09:08
  • this would need some serious thinking - and I suspect the answer would be very specific to the threat model. – symcbean Jun 14 '16 at 09:16