CSRF or XSRF stands for Cross Site Request Forgery. It is an attack on web applications where a malicious user uses an authenticated user’s cookie to perform a transaction on the web application mimicking as the original user.
Background of the Attack
For example, assume you have a form to reset password in your website(www.yoursite.com) similar to below.
<form action="/Account/PasswordReset" method="post">
<input id="txtNewPassword" name="txtNewPassword" type="text" value="" />
<input id="txtConfirmNewPassword" name="txtConfirmNewPassword" type="text" value="" />
<input type="submit" value="Create" class="btn btn-default" />
Before logging off session, if you happen to visit a malicious site it may execute the below form submission to change your password. Please note the browser will automatically attach the user cookie to a request based on the URI the request is targetting. Since the below form's POST refers www.yoursite.com, the cookie information will be automatically attached by the browser.
<form action="http://www.yoursite.com/Account/PasswordReset" method="post">
<input id="txtNewPassword" name="txtNewPassword" type="hidden" value="" />
<input id="txtConfirmNewPassword" name="txtConfirmNewPassword" type="hidden" value="" />
Note – This is just for demonstration to understand how XSRF attack is done. A real password reset page may have additional input validations like asking user to input existing password, etc.
Forcing user to logoff session or advising user not to use any other site may look like a preventive measure but it may not be a practical solution. Even if the user is so protective, a web application that is vulnerable can still be targeted easily by an attacker by various means. We can also check the HTTP Referer header to check whether the request is referencing our website domain or the last page the user was on from where he/she has given the current request. But we cannot guarantee this as an effective method to prevent CSRF because there are cases where the user would have disabled browser’s capability to add Referer header with http request.
Preventing XSRF or CSRF Attack
Since CSRF is one of well-known and a common web security vulnerability, all the web stack frameworks currently provides a mechanism to prevent XSRF attack. Asp.Net framework uses a specific implementation called synchronizer token pattern to prevent XSRF attacks. This pattern generates 2 anti-XSRF tokens for each request and sends it back to browser. The 2 anti-XSRF tokens are,
The session token is sent as a cookie which consist of 128 bit identifier called security token that cannot be guessed or predicted.
The field token is sent as hidden form field. This field value is generated using 128 bit security token created for session token and using the logged-in user identity. In user is not authenticated, the token is generated considering username as empty string. The field token can also include additional data by extending the field token generation process using IAntiForgeryAdditionalDataProvider interface.
The browser should then send back these 2 tokens for doing any transaction on the page in the subsequent request. The server will validate these tokens and it will allow the transaction only if the token matches with what it originally sent. For authenticated request, the username is extracted from the field token and it should match the logged in username. For instance, any page that updates data or make a transaction will be accessed by an initial GET request on which the browser receives the 2 tokens. Once the user submits the form, the data is posted to server using POST method with the 2 security token for validation.
Let’s see how to make the Asp.Net MVC framework to include these tokens and validation during request processing.
Including AntiForgery Tokens in Asp.Net MVC View/Controller
To include the anti-XSRf tokens, we can use the html helper method @Html.AntiForgeryToken() or @AntiForgery.GetHtml() from the razor view.
@*Removed for brevity *@
The above HTML helper method will include a field token as input hidden field like below.
<input name="__RequestVerificationToken" type="hidden" value="8pgRNnRsV11Gjq_oaOoWz6FSiWbUo0YHERAq5ryCTjMFTN6Yl63Szc-gkOF2BVXek6dKjkxV-EvfhXAO7Et3FytHJAYnlkWkM3yc7wpptTPMqG2aRmnx-jpXPK5sD4JmDbZ__3kYc3-OvdEXUA1Urg2" />
And the session token cookie will be added to outbound cookie collection. This can be inspected by using browser developer tools like FireBug or IE developer toolbar. The below image shows the FireBug Net console’s output for a GET request with Anti Forgery token included in the response.
To include the validation on the Controller action method, we can decorate the action with the attribute ValidateAntiForgeryToken.
public ActionResult Create(Employee emp)
This will now validate the POST request’s anti-XSRF tokens and it will allow the post method only if successfully validated.
In Asp.Net Core MVC, the antiforgery tokens are automatically added to the response when you use the form tag helpers. This means you need not explicitly call the @Html.AntiForgeryToken() in razor view page.
You will get the following error if validation fails or when the token in missing in the request.
The anti-forgery token could not be decrypted. If this application is hosted by a Web Farm or cluster, ensure that all machines are running the same version of ASP.NET Web Pages and that the <machineKey> configuration specifies explicit encryption and validation keys. AutoGenerate cannot be used in a cluster.
The required anti-forgery form field "__RequestVerificationToken" is not present.