Cross Site Request Forgery
Matthew Martin 10/17/2015 05:26:00 PM
Like a lot of web security issues, the story begins with the same-origin policy. All browsers enforce a policy whereby they will block http requests from a site with one domain name to a site with a different domain name, unless the response from that outside domain says to honor the request. An important caveat, though, is that the browser only blocks the origin site from reading the response from the second domain if the second site does not allow cross-domain requests. Since the browser cannot know ahead of time what the second domain's cross-domain policy will be, it can't block the first site from making the request.
Unfortunately, that same-origin policy comes too late in the process for other types of requests. Suppose that third-party website you clicked on instead sends a POST request containing a new facebook status update. Facebook.com would receive that request, see that it has a valid authentication cookie, think you made it from their website, and post the status under your name. That's very bad. It's easy how this can be an immensely profitable vulnerability when it comes to, for example, POSTing shopping orders on amazon.com or editing administrative records in a corporate web system.
How do we block this type of attack? The puzzle is we need a way to verify that the request was made from a web page under our control. Here's a way to do that: require that the request content contain a randomized key that matches a key in the request cookies. As mentioned earlier, browsers send cookies along with each request based on the domain the request is going to. So facebook.com can set such a key in the user's cookie collection for facebook.com, and then send this key back in the request body whenever it makes a POST request. The third-party website, however, is unable to read the key from the cookie collection for facebook.com, because browser blocks it from reading such cross-domain requests. But the browser does send this key back as part of the cookie collection for any requests to facebook.com. Thus by checking to see that the request has a key that matches the one sent in the cookie collection, we can confirm that--provided the browser properly implements the same-origin policy--the request came from the same domain. In asp.net, these keys are known as anti-forgery tokens. They are part of the asp.net MVC assembly. Click here for more on how to use anti-forgery tokens to prevent CSRF.
To sum up, you should be using anti-forgery tokens for every POST, PUT, and DELETE http request. Even for things like logins, since a CSRF could potentially log users into the wrong account--a variant of phishing that could lead a user to accidentally expose sensitive information to a different user. Every time, for everything other than GET. And you should make sure your GETs are true GETs--they should have zero effect at all on the state of your data on the server.