CSRF in MVC asp.net

Sometime 140 characters is not enough to explain your point. Recently on twitter Troy Hunt [someone you should be following] said the following in response to my claim that asp.net mvc did not offer out of the box protection from CSRF.


Before I go any further let me define IMO the characteristics a good CSRF prevention system should have:

  • Should prevent CSRF in ideal conditions (you and your users never ever get pwned)
  • Should not require tokens to remain secret forever
  • Should be on by default for all unsafe requests (see 9.1.1 of the http spec)

When attempting to prevent a CSRF attack on a website using asp.net MVC, and asp.net webforms. The developer is responsible for adding the following to their forms <%= Html.AntiForgeryToken() %> and actions which should be protected must be tagged with the [ValidateAntiForgeryToken] attribute.  This system is built on an opt in approach. By default all actions on all controls do NOT protect against CSRF. Further more because it is a direct reuse of the webforms code base it only works for form submissions. Which is great if that is all one does. However, in the last several years of development I have used less and less forms, and more and more json based services. For the sake of argument lets say you did follow the Microsoft line, and only ever use form submissions, and never forgot to tag your actions, then you are safe right? Nope, because the tokens are generated are essentially an hmac of the current user’s username they are not in anyway tied to the user’s current session. This means that even if the user logs out there CSRF tokens from the previous session are usable by an attacker.  It does not matter what you do as a user, you can change your password, log in log out clear your browser cache, none of this will invalidate any previously stolen CSRF token. This leads to the undesirable characteristic of once compromised always compromised.  Yes, you are safe. Troy hunt pointed out to me the implementations in webforms and mvc are different. MVC’s implementation of CSRF tokens (at least in the latest version) does not suffer from the same weakness as webforms which did not invalidate the tokens between sessions.

So of the three characteristics of a good CSRF prevention system asp.net’s system only has the first one has the first and second; It prevents CSRF in ideal conditions.  Sooner or later a CSRF token will be compromised because a user logs in from a public computer, gets a virus, is the victim of a main in the middle attack, or the site has an XSS vulnerability. This is not a question of if only a question of when.

The third characteristic (secure by default) is achievable in Microsoft’s ecosystem through the use of a custom filter that automatically requires CSRF protection on all unsafe methods similar to this: https://gist.github.com/jmaxxz/3190357

 

Previous Post
  • I think you’re on the right track now anyway, but here’s the succinct version for each of the three different technologies you’ve referred to:

    1) Classic ASP (usually done in VB script): You got nothing out of the box but you could hand-roll the whole thing yourself if you wanted.
    2) ASP.NET Web Forms: The default project template has an implementation built into the master page which is then inherited by any page using the master.
    3) ASP.NET MVC: You’ve got an HTML helper and as you say, a ValidateAntiForgeyToken attribute with which to decorate your methods.

    The latter two are keyed to the current user identity (if there is one) but not to the session (that’s just off the top of my head, I’d double-check that). If you’re building async requests then things get a little trickier, Phil Haack has a nice piece on it here: http://haacked.com/archive/2011/10/10/preventing-csrf-with-ajax.aspx/

    I also describe the semantic between the various implementations in my “ASP.NET Security Secrets Revealed” Pluralsight course here: http://pluralsight.com/training/Courses/TableOfContents/aspdotnet-security-secrets-revealed

    And talk through using anti forgery tokens when consuming APIs in the “Hack Yourself First” Pluralsight course here: http://pluralsight.com/training/Courses/TableOfContents/hack-yourself-first

    tl;dr – there are different implementations in different editions of Microsoft technologies but regardless of which one you use, you really want to understand how they work or it’s very easy to get wrong, particularly when you start hitting APIs.