I have an MVC app that is using the AntiForgeryToken capability of ASP.NET MVC. AFAICT this uses an encrypted synchronizer token variation where it validates the payload of the tokens.

A customer has questioned the fact that these tokens don't expire, and if captured will continue to be valid for a given user's session.

It is possible to customize add a timestamp to the token and validate it, thus expiring the issued token after a period.

What I'm wondering though, is this necessary? Should CSRF tokens provide replay protection? Wouldn't an attack require either MitM or an XSS vulnerability?

I sort of expect that a longish expiry is a reasonable part of a defense-in-depth strategy, but it is odd to me that replay would be raised as a security issue with an CSRF prevention scheme.

What am I missing?


If the CSRF token can be intercepted then the session cookie can usually be intercepted as well, so CSRF wouldn't be the immediate concern in that scenario.

Some CSRF token implementations have timed expirations, but this is an extra precaution and not strictly necessary. This answer from tylerl suggests that an expiration is a good precaution in case the token is leaked somehow, but expiring the CSRF token when the session ends is ok.

In a CSRF attack the attacker has the ability to submit whatever form data they want from your session, but they can't modify your cookies. For a CSRF token to be effective it should be impossible for the attacker to know its value. If the attacker exploits a vulnerability to obtain CSRF tokens, then you want to make sure that the CSRF tokens are no longer valid once the vulnerability is fixed. As long as the token cookie is expired when the session expires everything is fine (provided you force sessions to expire if you ever suspect tokens have been leaked).

From the documentation you linked it looks to me like it's actually using the Encrypted Token Pattern, which sort of combines a Double Submit Cookie with a Synchronizer Token.

  • Thanks @AndrolGenhald! The token is indeed encrypted, but it's also a synchronized token. The linked doc self explains the scheme as 'variant of the synchronizer token pattern'. In your opinion then replay is not a valid attack threat on the CSRF implementation?
    – JT.
    Sep 12 '17 at 13:59
  • In a replay attack the attacker is trying to cause your data to be sent to the server multiple times, in a CSRF attack they're trying to get you to submit something specific once. The issue isn't that requests can be replayed, it's that if the token has been compromised and hasn't been invalidated/expired then the application will be vulnerable to CSRF. Sep 12 '17 at 22:06
  • It would seem that if your cookie and in-page token can be sniffed, the application has bigger problems. IMO the true defense against this is transport security, though I can see the defense-in-depth argument. Where am I going wrong with this thinking?
    – JT.
    Sep 13 '17 at 3:37

We've had this discussion with many clients over the years. The most valid solution for CSRF protection is one where the server tracks what 'page' was sent to the client, then only accepts valid data from the page that was served, from only the client it was served to.

It's been a while since I've been on the programing side with MS, but the @AntiForgeryToken should change with every request and be validated on each page that receives data.

It sounds as if the application only generates the token once, then never again. Check out this blog for additional details. http://blog.stevensanderson.com/2008/09/01/prevent-cross-site-request-forgery-csrf-using-aspnet-mvcs-antiforgerytoken-helper/

  • Thanks for your reply! When considering per-page tokens with a synchronizer token pattern, wouldn't this mean that a cookie is either regenerated on each request or there would be a cookie per page? The first would create cross tab issues (as the shared cookie would get invalidated quickly), and the second would create a lot of cookies.
    – JT.
    Sep 12 '17 at 13:19
  • When considering the output of @AntiForgeryToken in the Razor side, note that while this may change often, the cookie stays relatively static. As soon as the cookie is reissued, page tokens that had previously been issued are invalidated. Complicating this is that the token is created as a session cookie, and while they're meant to be deleted on browser restart etc, modern browsers will often persist them indefinitely.
    – JT.
    Sep 12 '17 at 13:21
  • Lastly (to address the last of your points), the AntiForgeryToken attribute appears to generate a cookie once per login identifier, and doesn't readily regenerate it. This seems to be the nub of the customer's concerns. The key idea I'm trying to drill in on though is whether replay is an attack that an anti-CSRF implementation should consider?
    – JT.
    Sep 12 '17 at 13:57

A “replay-resistant” authentication stops a MITM from storing traffic and being able to perform requests on behalf of the victim.

A CSRF is an attack that allows an intruder to use a valid session, stored or not, to perform requests on behalf of the victim.

A CSRF token makes sure that access to the session alone does not grant access to perform requests on behalf of the victim. It also protects therefore against a "replay-resistance" authentication because the attacker has to have not only the classical HTTP cookie stored session but in addition a more difficult to obtain, if well implemented, CSRF token.

The answer to the question is therefore "No, it is not valid to defend a CSRF token against replay, because the CSRF token actually is the one that can protect against replay. If a CSRF token implementation needs to be "defended" against replay then that implementation is not good enough"

To dig further into a good implementation of a CSRF token, here is what to do (Note that CSRF token protection is not just about demanding a token when a request is received but also about when that token gets sent to the front end, and how the front end keeps it):

  1. Do not support old browsers. This ensures, for example, that SameSite=lax is set by default for cookies and provides an army of headers that can be sent from the server side to make the browser mitigate front end related attacks. Another example that shows why using latest browser versions is important would be the default "same origin policy" that new browsers use and their support for some controlled relaxing via Content-Security-Policy header. Bottom line, again, stop old browsers from using your app. Risking everybody because few do not upgrade their browsers is a totally incorrect approach.
  2. Do not allow any backend persistence without providing a CSRF token. So, for example, if your API implementation does not follow a purist REST approach, then consider checking CSRF for everything the server receives including yes, GET requests.
  3. Return the token as HTTP Header only once after successful login.
  4. Store the CSRF token in the local browser storage and never as a cookie. This is crucial because if you use a cookie then your browser will be sending the CSRF token regardless of what site does it on your behalf. The CSRF token must be reachable only if a user is running front end code from the app domain.
  5. Inactivate the session if an incorrect CSRF token is received for it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.