8/23/12

Protect Your Form Postback with Anti-Forgery


To secure a web page postback from malicious exploits, we can add a security token as a hidden field to the form or a cookie. When a postback is received, this token is validated to make sure that the request is not a cross-site request forgery.

When working with Razor Web Pages and WebMatrix, we can find a handy helper which provides this implementation right out of the box. The AntiForgery helper gives us the capability to create and validate the secured encrypted token by just using a couple of lines of code. This helper is found in the System.Web.Helpers.dll assembly, and it should be added automatically as a reference to your project in the bin folder. Note that for Visual Studio you need to install a Nuget Package using this command:

 Install-Package RazorGenerator.Templating

To show you how to use this helper, open a web page on WebMatrix and add the following mark-up:

@{
    // Validation token test during postback;
    if(IsPost){
        try
        {
            AntiForgery.Validate();
        }
        catch(Exception ex)
        {
            ModelState.AddFormError(ex.Message);
        }
     
        if(ModelState.IsValid)
        {
            Page.SuccessMessage = "Token validated!";           
        }        
    }    
}
<!DOCTYPE html>
<html lang="en">
    <head>  
    </head>
<body>
<div class="message-error">@Html.ValidationSummary()</div>
<div class="message-success">@Page.SuccessMessage</div>
<form method="post" action="">
    Full Name:<input type="text" name="username" id="username"/><br/>
    EMail:<input type="password" name="username" id="username"/><br/>
   @AntiForgery.GetHtml()
    <input type="submit" name="submit" value="Send"/>   
</form>
</body>
</html>
 
This is a simple contact page with two fields. This page is available to the public on the internet, and we would like to prevent any type of exploits. In order to do that, we have added this line of code in between the form tags:

@AntiForgery.GetHtml()

If you look at the page source after it has rendered on the browser, you can see that a hidden field has been added:



The _RequestVerificationToken field contains an encoded encrypted token. In addition, a cookie with the same information has been created. This allows the helper to cross check the token in both the form and cookie.

To validate the token during the post back, we use this code:

        try
        {
            AntiForgery.Validate();
        }
        catch(Exception ex)
        {
            ModelState.AddFormError(ex.Message);
        }

The call to Validate() raises an exception if the token is not valid. At this point, the code can stop doing any additional logic and just present an error using the ValidationSummary method from the Html helper.  If the token is successfully validated, we check the ModelState.IsValid method and continue the intended logic which for this example is just adding the contact information to the system.

I hope you can find this helper very useful for your own implementation.