Secure .Net Core applications from CSRF attack: .Net Core security Part II

csrf4

You can find all of my  .Net core posts here.

This is the second post on .Net Core security. First part is here.

In this post, we will see how to secure your .Net Core applications from CSRF attack.

What is CSRF?

CSRF stands for Cross-Site Request Forgery.

CSRF in simple words:

Cross-Site Request Forgery (CSRF) is an attack where a malicious site sends a request to a vulnerable site where the user is currently logged in.

For example:

  • You logged in to the site X.com with form authentication
  • The site will return an authentication cookie
  • This cookie will travel along with the users every request
  • If the user visits a malicious site Y.com, the site may contain an HTML form with submit(or any other button) button
  • If you click on the button, the form will be submitted to the X.com instead of Y.com along with the authentication cookie
  • The hacker can do whatever you want to do using your authentication and they can post the form by running some scripts
  • This can be so dangerous when the person is logged into some banking or any other important websites.

Below image can give some better information for CSRF:

csrf2

To prevent this, you need a token which will be included in the form and will be validated server side when the user submits the form.

Let us see how .Net Core handles this CSRF attack

If we compare .Net Core with .Net as far as the resolution of CSRF attacks is concerned, The ValidateAntiForgeryToken attribute and The AntiForgeryToken HTML helper(@Html.AntiForgeryToken()) are still there in .Net Core. On top of these, there are some more powerfull options we have in .Net Core.

Let us see by creating .Net Core application

prerequisite:

  • Visual studio 2017 community edition, download here
  • .Net Core 2.0 SDK from here (I have written a post to install SDK here)
  • We will use the code which I created during Code first sample which is here. Details of the code are here in this post.

Token Generation

If you open Create.cshtml page, then you will notice below form tag:


<form asp-action="Creates">

Here asp* is a tag helper and the best part is asp* tags will automatically add the token into your form when you submit the form.

For example, in below form, the __RequestVerificationToken is generated along with the form:

csrf1

Note – From .Net Core 2.0 onwards, the token would be added even if you do not have asp* tags in your form.

Also, note that simple form tag with action does not generate the token automatically. so if you have below code in razor file then the token will not be generated automatically:


<form action="Creates" >

In such case you can generate the token by adding @Html.AntiForgeryToken() under the form as shown below:


<form action="Creates" >
@Html.AntiForgeryToken()

</form>

This will generate the token.

Restricting auto-generation of the tokens

As .Net Core generates the token automatically along with the form tag, you can even restrict this autogeneration if you do not wish to generate this tokens.

For this you need to add asp-antiforgery=”false” in form tag as below:


<form asp-action="Creates" asp-antiforgery="false">

This will not generate the token for your form.

One more way to restrict this is using ! before the form tag as below:


<!form asp-action="Creates" >

! is called Opt-out symbol.

Token with jQuery and Ajax

If you are using Ajax call instead of using Form submit button, then you can use below code to generate and send the token:


var csrfToken = $.cookie("CSRF-TOKEN");

$.ajax({
url: "/Employees/Creates",
contentType: "application/json",
data: JSON.stringify({  }), //// Data here
type: "POST",
headers: {
"X-CSRF-TOKEN": csrfToken
}
});

Validating the anti-forgery token

Generally, a controller may contain GET as well as POST action methods. POST action methods require validating the anti-forgery token and not the GET action methods. So, if the ValidateAntiforgeryToken is declared on the controller, the HTTP GET requests become invalid and would throw the error as below:

csrf3

I remember writing different code to resolve this issue. But not this .Net core anymore. AutoValidateAntiforgeryToken would be your friend in such cases.

AutoValidateAntiforgeryToken

This is a new attribute added with .Net Core.

Sometimes it is not required to validate all the tokens, for example, the requests like:

  • GET
  • HEAD
  • OPTIONS
  • TRACE

AutoValidateAntiforgeryToken is almost similar to ValidateAntiforgeryToken except the fact that it doesn’t validate tokens on GET, HEAD, OPTIONS and TRACE requests.

This filter can be applied either at controller level or globally.

You can add AutoValidateAntiforgeryToken filter above the action or above the controller as below:


[HttpPost]
[AutoValidateAntiforgeryToken]
public async Task<IActionResult> Creates([Bind("EmployeeId,EmployeeName,EmployeeAge,DepartmentId")] Employee employee)
{

...

}

Or globally under ConfigureService method of Startup.cs class as below:


services.AddMvc(options =>
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute()));

When you add this attribute globally, then you are not required to put the attribute above different actions as well as controllers.

ValidateAntiForgeryToken

This filter is same as we have in .Net MVC.

This filter validates the request token on each and every method it is placed on regardless of the HTTP verb. So it validates even on GET, HEAD etc requests.

We can put this filter on the action method(or above controller):


[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Creates([Bind("EmployeeId,EmployeeName,EmployeeAge,DepartmentId")] Employee employee)
{

...

}

Or Globally:


services.AddMvc(options =>
options.Filters.Add(new ValidateAntiForgeryTokenAttribute()));

Note – It is advisable to use AutoValidateAntiforgeryTokenAttribute than using ValidateAntiForgeryTokenAttribute globally because if we apply ValidateAntiForgeryTokenAttribute globally then We will not receive the anti-forgery tokens for certain types of requests like GET, HEAD, TRACE etc which will cause the validation errors from those requests as I explained above.

IgnoreAntiforgeryToken

Sometimes there might be some requirements for ignoring the anti-forgery tokens or you need to ignore the tokens for specific actions of the controllers. In such case, you can use an IgnoreAntiforgeryToken filter.

For example you want to ignore the tokens for any specific action of a controller then you can apply to controller and to that action:


[AutoValidateAntiforgeryToken]
public class EmployeesController : Controller
{
[HttpPost]
[IgnoreAntiforgeryToken]
public async Task<IActionResult> Creates([Bind("EmployeeId,EmployeeName,EmployeeAge,DepartmentId")] Employee employee)
{

...

}

}

Hope it helps.

 

 

 

 

Advertisement

2 thoughts on “Secure .Net Core applications from CSRF attack: .Net Core security Part II

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s