AntiForgeryToken in ASP.NET Core MVC

SPONSOR AD

Cross-Site Request Forgery and AntiForgeryToken in ASP.NET Core MVC

In this article, I will discuss Cross-Site Request Forgery and AntiForgeryToken in ASP.NET Core MVC Applications with Examples. Please read our previous article discussing the Difference Between TypeFilter and ServiceFilter in ASP.NET Core MVC.

What is Cross-Site Request Forgery?

Cross-Site Request Forgery (CSRF or XSRF) is a type of security attack that forces an end user to execute unwanted actions on a web application they’re currently authenticated. In ASP.NET Core MVC, protecting against CSRF attacks is crucial to ensure the application’s and its users’ security.

Let us first understand the Cross-Site Request Forgery (CSRF or XSRF) attack, and then we will see how we can prevent this in ASP.NET Core MVC Application.

Example to Understand Cross-Site Request Forgery (CSRF or XSRF)

Let us create a new ASP.NET Core Application using the Model-View-Controller Project template and give the project name BankingApplication. Once you create the project, modify the Home Controller as follows. So, our requirement is to create a view for updating the PIN of an Account Number of a user.

SPONSOR AD
using Microsoft.AspNetCore.Mvc;
namespace BankingApplication.Controllers
{
    public class HomeController : Controller
    {
        [HttpGet]
        public IActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public string Index(string AccountNumber, string Pin)
        {
            // Process the data
            // ...

            return $"AccountNumber: {AccountNumber} Pin Changed to: {Pin}";
        }
    }
}

When the user provides the account number and pin and submits the button, it will post the form data to the Post Index action method of the Home Controller. Next, modify the Index.cshtml View of Home Controller as follows:

@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1>Pin Change</h1>
    @using (Html.BeginForm("Index", "Home", FormMethod.Post))
    {
        <input type="text" name="AccountNumber" id="AccountNumber" />
        <input type="text" name="Pin" id="Pin" />
        <input type="submit" value="Change Pin" />
    }
</div>

Now, run the application, go to the Index view, and submit the Account Number and Pin as shown in the below image:

Example to Understand Cross-Site Request Forgery (CSRF or XSRF)

Once you click on the Change Pin button, the Pin has been changed for the account number, and you should see the following message:

Example to Understand Cross-Site Request Forgery (CSRF or XSRF) in ASP.NET Core MVC

Now, as you can see, the application is working as expected. Here, please observe the URL, i.e., https://localhost:44378/Home/Index, and let’s see how a hacker can make a Cross-Site Request Forgery (CSRF or XSRF) attack to your site by using the above URL.

Hackers Application:

Let us create a new ASP.NET Core Application using the Model View Controller Project template and give the project name as HackerApplication. Once you create the HackerApplication, then modify the Home Controller as follows:

SPONSOR AD
using Microsoft.AspNetCore.Mvc;
namespace HackerApplication.Controllers
{
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    }
}

Next, modify the Index.cshtml view of the Home Controller of HackerApplication as follows. Here, you can see we are posting the form data to the Banking Application. Here, we have a text field to store the Account Number and PIN in the hidden field, and once the user clicks on the Claim My Gift Card button, it will submit the request to the BankingApplication, where it will update the Account Number and Pin.

@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h3>Enter your Account Number to Claim Your Gift</h3>
    <form action="https://localhost:44378/Home/Index" method="post">
        <input type="text" name="AccountNumber" id="AccountNumber" />
        <input type="hidden" name="Pin" id="Pin" value="1111" />
        <input type="submit" value="Claim Your Gift" />
    </form>
</div>

Now, run the application, enter your account number, and click the Claim Your Gift button, as shown in the image below.

AntiForgeryToken in ASP.NET Core MVC

Once you click on the Claim Your Gift button, your account number pin is updated in the Banking Application as shown in the below image:

AntiForgeryToken in ASP.NET Core MVC

This is nothing but a Cross-Site Request Forgery (CSRF or XSRF) attack on a website.

How can we prevent Cross-Site Request Forgery (CSRF or XSRF) Attack in ASP.NET Core MVC?

To prevent Cross-Site Request Forgery (CSRF or XSRF) in ASP.NET Core MVC Web Applications, we need to use AntiForgery Tokens.

AntiForgery Tokens: ASP.NET Core uses anti-forgery tokens, also known as request verification tokens, to prevent CSRF attacks. These tokens are unique to each user session and are used to confirm that the user submitting a request is the one who originally requested the page.

SPONSOR AD
How Does It Work?
  • When a form is rendered, ASP.NET Core injects a hidden form field with the anti-forgery token.
  • The user’s browser submits this token along with the form data.
  • Upon receiving the request, the server validates the token to ensure that the request is legitimate.
How to Implement AntiForgery Tokens in ASP.NET Core MVC?
  • In the View: To generate the token, use the @Html.AntiForgeryToken() helper method in your Razor views within the <form> tag.
  • In the Controller: Decorate actions that change state (like POST actions) with the [ValidateAntiForgeryToken] attribute. This ensures that the action method processes the request only if it comes with a valid anti-forgery token.
  • Automatic Token Generation in ASP.NET Core 2.0 and Later: From ASP.NET Core 2.0 onwards, the framework automatically generates anti-forgery tokens for all forms by default. However, manually adding the @Html.AntiForgeryToken() is still a good practice for clarity and backward compatibility.
  • Ajax Requests: For Ajax requests, you need to manually retrieve the token from the cookie or form and add it to the request header.
  • Token Validation: The framework validates the token automatically when the action method is decorated with the [ValidateAntiForgeryToken] attribute. If the token is missing or invalid, it rejects the request.

So, let us proceed and implement this in our Banking Application:

Modify the Index.cshtml view of the Home Controller of our banking application. As you can see, we are adding the @Html.AntiForgeryToken() helper method within the form body. The @Html.AntiForgeryToken() method generates a hidden input field containing the anti-forgery token.

@{
    ViewData["Title"] = "Home Page";
}

<div class="text-center">
    <h1>Pin Change</h1>
    @using (Html.BeginForm("Index", "Home", FormMethod.Post))
    {
        @Html.AntiForgeryToken()

        <input type="text" name="AccountNumber" id="AccountNumber" />
        <input type="text" name="Pin" id="Pin" />
        <input type="submit" value="Change Pin" />
    }
</div>

Next, modify the Home Controller of our Banking Application as follows. As you can see, we are decorating the Post Index action method with the ValidateAntiForgeryToken attribute. The [ValidateAntiForgeryToken] attribute ensures the request includes a valid anti-forgery or request verification token.

using Microsoft.AspNetCore.Mvc;
namespace BankingApplication.Controllers
{
    public class HomeController : Controller
    {
        [HttpGet]
        public IActionResult Index()
        {
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public string Index(string AccountNumber, string Pin)
        {
            // Process the data
            // ...

            return $"AccountNumber: {AccountNumber} Pin Changed to: {Pin}";
        }
    }
}

With the above changes, run the Banking Application; you will see that the account number pin updation functionality is working as expected. Now, run the Hacker Application and click on the Claim My Gift Card button by entering the Account, and you should see the following error page:

Cross-Site Request Forgery and AntiForgeryToken in ASP.NET Core MVC Applications with Examples

The anti-forgery token filed name is __RequestVerificationToken, and if you want, you can also capture this field value in your application code. For example, modify the Home Controller of Banking Application as follows:

using Microsoft.AspNetCore.Mvc;
namespace BankingApplication.Controllers
{
    public class HomeController : Controller
    {
        [HttpGet]
        public IActionResult Index()
        {
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public string Index(string AccountNumber, string Pin, string __RequestVerificationToken)
        {
            // Process the data
            // ...

            return $"Request Verification Token: {__RequestVerificationToken}";
        }
    }
}

How AntiForgeryToken Generated and Validated in ASP.NET Core MVC?

In ASP.NET Core MVC, the AntiForgeryToken is a key mechanism for preventing Cross-Site Request Forgery (CSRF) attacks. Here’s how it is generated and validated:

Generation of AntiForgeryToken
  • Creation: ASP.NET Core generates a unique token called the AntiForgeryToken when a form is rendered. This token is created using the @Html.AntiForgeryToken() helper method in Razor views.
  • Storage: The generated token consists of two parts: a hidden field in the form and a cookie. The hidden field ensures the token is sent along with the form data during a POST request while the cookie is stored in the user’s browser.
  • Encryption: The token is encrypted and securely signed to ensure that it cannot be tampered with or forged by an attacker.
Validation of AntiForgeryToken
  • Automatic Validation: In ASP.NET Core MVC, when a form is submitted, the framework automatically validates the AntiForgeryToken if the [ValidateAntiForgeryToken] attribute is applied to an action method. This attribute can be applied to individual action methods or the controller level.
  • Token Comparison: During validation, the framework compares the token from the hidden field (sent in the POST request) with the token in the cookie.
  • Integrity Check: The validation process includes checking the integrity and validity of the token to ensure it hasn’t been tampered with.
  • Exception Handling: If the tokens do not match or are missing, ASP.NET Core will throw an exception, preventing the action method from executing, thereby stopping the potential CSRF attack.
Best Practices
  • Always use [ValidateAntiForgeryToken] on POST actions.
  • Do not expose sensitive actions through GET requests.
  • Ensure that anti-forgery tokens are used in all forms, especially those that perform create, update, or delete operations.

In the next article, I will discuss Action Name Attributes in ASP.NET Core MVC. In this article, I explain Cross-Site Request Forgery and AntiForgeryToken in ASP.NET Core MVC Applications with Examples. I hope you enjoy this Cross-Site Request Forgery and AntiForgeryToken in the ASP.NET Core MVC article.

SPONSOR AD

Leave a Reply

Your email address will not be published. Required fields are marked *