As part of the book currently under way I cover Cross Site Request Forgery, a rather fun exploit that numerous web sites have been vulnerable to. In September of this year researchers from Princeton announced the discovery of four major web sites where were susceptible which included ING Direct, a vulnerability which would allow an attacker to transfer money between accounts.
CSRF works via persistent authentication. When you logon to a web site an authentication cookie is left on your machine (or if you're using HTTP Authentication your browser remembers and sends the username and password with each request). An attacker can then create a malicious web page that submits a form, or a query string based GET request to a site you are authenticated to. The browser sends the request to the target web site, along with the authentication details it already has stored and bang, there's your exploit.
With ASP.NET you can protect against CSRF with a ViewStateUserKey which locks ViewState to a particular value you associate with a user or session (their login ID or session ID for example) - however this requires ViewState to be enabled (and often it is disabled for performance reasons) and it is by no means a panacea. A fellow Developer Security MVP (and the technical editor for my book) Alex Smolen points the problems with solely relying upon it.
The classic solution to CSRF is to add a secondary authentication token to a form as a hidden form field and to drop an authentication cookie during the first GET request to your site then every time a form is submitted the cookie and the form token are compared and if they do not match the request is rejected - this is the approach the ASP.NET MVC folks have taken with Html.AntiForgeryToken(). One draw back to this method is the need to manually add the token and do the checks, this sort of thing should be automatic.
At BlueHat this year Alex and I batted back some approaches to this, I wanted something simple for the book.The good folks at OWASP have the .NET CSRF Guard project but this uses sessions, something I wanted to avoid.
After some batting back and forth, and some silly mistakes on my part we developed AntiCSRF, an HTTP Module which you can slot into your web application to take the worries away. The module automatically takes care of token generation and checking for every Page on your web site, assuming it inherits from System.Web.Page and contains an ASP.NET form.
What it does not do is protect you from GET requests which cause destructive actions. The HTTP specifications state that GET requests should be idempotent (i.e. they do not cause state changes within your application). If you have URLs which trigger actions like deletes then you need to start thinking about changing those types of requests to become POSTs. We also haven't protected non ASP.NET webforms as, frankly, trying to process HTML code is a bit of a nightmare.
The protection is opt-out (unlike the MVC approach and ViewStateUserKey which are opt-in and need code for implementation). This is a deliberate choice as it is, in my opinion, safer.
We are not saying this is the final word in CSRF protection, you should always treat these things as just another layer of your defence in depth; but please download, have a play, see how it goes and don't forget to log any issues or bugs on CodePlex. The code is licensed under the Microsoft Permissive License.
Download AntiCSRF 0.9 Beta
Technorati Tags: ASP.NET