Friday, September 13, 2013

ASP.Net MVC: Cross Site Request Forgery - CSRF

How does it happen? 

  1. User logs in
  2. Our site sends back an authentication cookie
  3. On every subsequent request, the user’s browser will send the cookie back to our server and the server knows the user's agent (browser) is authenticated

Browser ---> Authenticate me ---> Server

Server --> OK, take this authentication cookie and supply to me on subsequent requests --> Browser

So far so good 

  • User goes to another site or tricked into picking HTML from another malicious site. Links in suspicious emails are a common way by which users are tricked.
  • The malicious link puts up a page/form in the user's web browser that points to our site and posts a form with bad information. The form has all the inputs in the form to apply changes (recall that the user browser already has the authentication cookie previously obtained upon authentication).
  • At the bottom of the malicious form, there is a script to automatically submit this form when the form POPs up.
    • < form action=>..
    • <div>
    • < input...>
    • </div>
    • <script type=”text/javascript”>
    •   document.getElementById(“theForm”.submit());
    • </script>
  • The malicious request or form works against our Server because the browser has been previously authenticated 
  • Result: The user has just inadvertently submitted data on behalf of the malicious site

It is not enough to be authenticated

  • In MVC, we use the Authorize attribute on HttpGets and HttpPosts to authenticate the user before the controller action proceeds any further
  • GETs should not be used to update information on the Server; only POSTs should update information
  • Our server should not only make sure the POST request is from an authenticated browser but it must also make sure the form being posted originated from our server.
  • Therefore, we must check that the information being submitted is from a FORM our Server provided to the browser

Use the Html Anti-forgery token in MVC Forms

  • An Html helper adds hidden input to the form with a value unique to user’s browsing session
  • A matching value (anti-forgery token) is sent as a cookie to user’s browser
  • Malicious user is not able to manipulate cookies for your server domain
  • The Anti-forgery token will comes back during authenticated postback
// Razor code
@using (Html.BeginForm())
{
HtmlHelper.AntiforgeryToken();
@Html.ValidationSummary(true);
...
}
  • To enforce the anti-forgery token, an ValidateAntiForgeryToken attribute must be applied to POST controller action

[HttpPost]
[Authorize]
[ValidateAntiForgeryToken] // make sure form value and cookie values match
// Valid only for POST verb
public ActionResult Edit(Review review)
{
 ...
}
  • Now the malicious popup will get an error from ASP.Net: A required anti-forgery token was not supplied or was invalid.