Joydip Kanjilal
Contributor

How to prevent CSRF attacks in ASP.NET Core

how-to
Sep 30, 20217 mins
Application SecurityC#Development Libraries and Frameworks

Take advantage of anti-forgery tokens in ASP.NET Core to protect users of your applications against cross site request forgery exploits.

cyber security shield lock protect
Credit: Who_I_am / Getty Images

Cross-site request forgery (CSRF) is an attack that tricks an end user into executing undesirable actions while logged into a web application. Taking advantage of the authenticated user’s permissions, a CSRF attack dupes the victim into performing specific actions that benefit the attacker. For example, a CSRF attack could be used to make a purchase from a website or transfer money from the victim’s bank account.

This article talks about CSRF attacks, how they work, and how such attacks can be prevented in ASP.NET Core 6. To execute the code examples provided in this article, you should have Visual Studio 2022 installed in your system. If you don’t already have a copy, you can download Visual Studio 2022 here.

Create an ASP.NET Core MVC project in Visual Studio 2022

First off, let’s create an ASP.NET Core 6 project in Visual Studio 2022. Follow these steps:

  1. Launch the Visual Studio 2022 IDE.
  2. Click on “Create new project.”
  3. In the “Create new project” window, select “ASP.NET Core Web App (Model-View-Controller)” from the list of templates displayed.
  4. Click Next.
  5. In the “Configure your new project” window, specify the name and location for the new project.
  6. Optionally check the “Place solution and project in the same directory” check box, depending on your preferences.
  7. Click Next.
  8. In the “Additional Information” window shown next, select .NET 6.0 (Preview) as the target framework from the drop-down list at the top. Leave the “Authentication Type” as “None” (default).
  9. Ensure that the check boxes “Enable Docker,” “Configure for HTTPS,” and “Enable Razor runtime compilation” are unchecked as we won’t be using any of those features here.
  10. Click Create.

This will create a new ASP.NET Core MVC 6 project in Visual Studio. We’ll use this project in the subsequent sections of this article.

How do CSRF attacks work?

Cross-site request forgery is a kind of attack in which an attacker sends a malicious message to a web app that exploits the authentication cookies of the victim. These attacks are most commonly performed by tricking users with phishing emails to lure them to malicious websites. Let’s understand how this attack works.

Suppose you’ve logged into a bank website using forms authentication. The server issues you an authentication cookie and this cookie is set in your web browser. If the banking website trusts any request as long as it contains an authentication cookie, then the conditions are ripe for a CSRF attack.

Now suppose an attacker sends you links in an email that appears to have come from your bank. If you click the links while you’re logged into your bank, the attacker’s malicious website could send POST requests back to the banking website. The malicious website might even attempt to insert or delete data in your bank since you’re already authenticated. The attacker could move funds from your account to the attacker’s account.

CSRF attacks are possible in web apps that use cookies to authenticate because:

  • Cookies are stored in web browsers.
  • Stored cookies comprise session cookies for all users who have been authenticated.
  • No matter how the request was generated, web browsers transmit all cookies associated with a domain to the web app.

Use anti-forgery tokens in ASP.NET Core

You can protect users of your ASP.NET Core applications from CSRF attacks by using anti-forgery tokens. When you include anti-forgery tokens in your application, two different values are sent to the server with each POST. One of the values is sent as a browser cookie, and one is submitted as form data.

Unless the server receives both values, it will refuse to allow the request to proceed. Thus the server ensures that all legitimate requests must come directly from the client, not from an external source. However, note that while web browsers send the cookie automatically, we must create the other token provided in the form. 

ASP.NET Core Razor Pages apps provide an anti-forgery token by default for the page forms; all you need to do is apply the appropriate validation. However, if you’re using an ASP.NET Core application (not MVC) from scratch, you’ll have to add the Microsoft.AspNetCore.Antiforgery package to your project manually and register the services.

The following code snippet demonstrates how to customize the token generation process using the AddAntiforgery function in the ConfigureServices method of the Startup class:

services.AddAntiforgery(options => 
{ 
      options.FormFieldName = "MyAntiForgeryField"; 
      options.HeaderName = "MyAntiForgeryHeader"; 
      options.Cookie.Name = "MyAntiForgeryCookie"; 
}); 

An anti-forgery token (also known as a CSRF token) is a unique, secret, and random parameter produced by a server-side application for a client’s subsequent HTTP request. The server compares the requested parameter to the anticipated value and denies requests if the parameter is incorrect or absent.

ASP.NET Razor Pages provide support for anti-forgery tokens by default. At runtime, the form tag helper will automatically render a hidden field that contains an anti-forgery token. Let’s understand this with an example. Consider the following tag helper:

<form method="post">
    @Html.AntiForgeryToken() 
</form>

At run time, this tag helper will generate the following HTML:

<form method="post">     
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8MZ1yRS5ySZJqjGnctAjlJcuQEPXqJHkCYWpvhGPis3j1s7cUUZByFfabzIP0xlz2kWwbaXZQ86hzrHmeU5DlD-u8DHmg_a5PhLwDcpJSdpnO4bHtE_X2OksjQW2uRp7ZWdnf1d0hcJZ1eAWtUNabHw" />
</form>

This would prevent XSRF/CSRF attacks in our Razor web pages.

Validate anti-forgery tokens in ASP.NET Core

You can programmatically validate CSRF tokens in ASP.NET Core. Consider the following action method:

 [HttpPost]
 public async Task<ActionResult<int>> UpdateStock(int noOfItemsSold)
 {
      if (! await IsAntiForgeryTokenValid())
          return BadRequest();
      //Write your code here...
       return Ok();
  }

And here is the IsAntiForgeryTokenValid method referenced above:

private async Task<bool> IsAntiForgeryTokenValid()
{
     try
     {
          await antiForgery.ValidateRequestAsync(this.HttpContext);
          return true;
     }
     catch (AntiforgeryValidationException)
     {
          return false;
     }
}

Alternatively, you can take advantage of the AutoValidateAntiForgeryToken attribute instead of the ValidateAntiForgeryToken attribute. The former works similar to the latter, but it doesn’t require tokens for requests made using HTTP methods that leverage the GET, HEAD, OPTIONS, and TRACE verbs.

The following code snippet illustrates how you can specify the AutoValidateAntiForgeryToken attribute in your controller.

[AutoValidateAntiforgeryToken]
public class HomeController : Controller
{
    //The action methods go here
}

You can also specify this attribute globally. The following code snippet illustrates how you can use this attribute globally, in the ConfigureServices method of the Startup class.

public void ConfigureServices(IServiceCollection services)
{
   services.AddControllersWithViews(options =>
   options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()));
}

Override anti-forgery attributes in ASP.NET Core

Finally, it is also possible to override the anti-forgery attributes. For example, you may want to change the cookie name or specify the form field or the header header name. You may want the ASP.NET Core runtime to look for the token in the header rather than a cookie. (Storing data in the request header is always safer than storing it in the cookie.) Moreover, your cookie can have a different name than what the ASP.NET Core runtime expects.

To override the anti-forgery attributes, you can take advantage of the IgnoreAntiforgeryToken filter as shown in the code snippet given below.

[AutoValidateAntiforgeryToken]
public class HomeController : Controller
{
    [HttpPost]
    [IgnoreAntiforgeryToken]
    public async Task<IActionResult> MySafeMethod(MyViewModel model)
    {
        //Antiforgery token is not required
    }
}

Best practices to prevent CSRF attacks

You can adhere to the following best practices to prevent CSRF attacks:

  • Ensure that your anti-virus software is up-to-date.
  • Refrain from saving log-in credentials in your web browser.
  • Clear your web browser cookies periodically.
  • Disable scripting in your web browser.
  • Implement two-factor authentication.
  • Log out from your applications when they are not in use.
  • Check your devices periodically for malware.

Cookies are not the only targets of CSRF attacks. Basic and digest authentication, for example, are both at risk. After a user signs in using basic or digest authentication, the browser transmits credentials to the user until the session expires. CSRF attacks can exploit this window of vulnerability.

You can protect users of your ASP.NET Core applications by using anti-forgery tokens. ASP.NET Core MVC applications include anti-forgery tokens automatically, but they must be added manually in other ASP.NET Core projects. Finally, note that ASP.NET Core will not generate anti-forgery tokens for HTTP methods (GET, HEAD, OPTIONS, and TRACE) that are safe.

Joydip Kanjilal
Contributor

Joydip Kanjilal is a Microsoft Most Valuable Professional (MVP) in ASP.NET, as well as a speaker and the author of several books and articles. He received the prestigious MVP award for 2007, 2008, 2009, 2010, 2011, and 2012.

He has more than 20 years of experience in IT, with more than 16 years in Microsoft .Net and related technologies. He has been selected as MSDN Featured Developer of the Fortnight (MSDN) and as Community Credit Winner several times.

He is the author of eight books and more than 500 articles. Many of his articles have been featured at Microsoft’s Official Site on ASP.Net.

He was a speaker at the Spark IT 2010 event and at the Dr. Dobb’s Conference 2014 in Bangalore. He has also worked as a judge for the Jolt Awards at Dr. Dobb's Journal. He is a regular speaker at the SSWUG Virtual Conference, which is held twice each year.

More from this author