Cross Site Request Forgery Attack

Today I am talking about ‘Cross Site Request Forgery’ attack. In short form it is called ‘CSRF’. It is a common way of security threat in web applications. If you are a web developer, you need to protect your web application from this kind of security threats.

By the way I am using ‘ASP.NET Core’ to discuss the implementation today. But you can find similar approach in another version of ASP.NET.

What is CSRF?

When a malicious website posts a ‘form’ to an another website with proper ‘form data’ and trigger the action of that website without user’s notice then it is called ‘Cross Site Request Forgery’ attack.

How it works?

Suppose you have a ‘http post’ action method in your controller which deduct money from user’s account. You have implement security in such a way that user needs to login before calling this action method.

[HttpPost]
[Authorize]
public IActionResult GetMoney(BankViewModel bank)
{
    BankViewModel bankAccount = (from account in _context.Banks
                                 where account.AccountNumber == bank.AccountNumber
                                 select account).SingleOrDefault();
    if (bankAccount != null && bankAccount.Amount != 0)
    {
        bankAccount.Amount -= bank.Amount;
        _context.SaveChanges();
    }            

    return View("Index");
}

Now after login user goes to a different website which is malicious. That malicious website creates a ‘form’ tag and there is a ‘submit’ method which post to the money deduct action method with user id.

<form action="http://localhost:64762/Bank/GetMoney/" method="post">
    <input type="text" name="AccountNumber" />
    <input type="text" name="Amount" />
    <input type="submit" value="Submit" />
</form>

When user click on the ‘submit’ method of the malicious website then it automatically deducts money from the user’s bank account. The user was logged in to the bank website before going to the malicious website, so the cookies are there in the browser cache. So the bank website has no clue that the request is coming from another website which is malicious.

How to be secure from CSRF?

There is an attribute in ASP.NET MVC called ‘AutoValidateAntiforgeryToken’. If you add this to the ‘http post’ action method which is deducting the money from user account, then ASP.NET creates a hidden field inside the ‘form’ tag in generating html and push back to the web browser.

[HttpPost]
[Authorize]
[AutoValidateAntiforgeryToken]
public IActionResult GetMoney(BankViewModel bank)
{
    BankViewModel bankAccount = (from account in _context.Banks
                                 where account.AccountNumber == bank.AccountNumber
                                 select account).SingleOrDefault();
    if (bankAccount != null && bankAccount.Amount != 0)
    {
        bankAccount.Amount -= bank.Amount;
        _context.SaveChanges();
    }            

    return View("Index");
}

If you open the view source in your web browser, you can see the hidden field with some auto generated random string inside that as value.

<form method="post" action="/Bank/GetMoney">
    <input type="number" data-val="true" 
           data-val-required="The AccountNumber field is required."      
           id="AccountNumber" name="AccountNumber" value="10">
    <input type="text" data-val="true" 
           data-val-number="The field Amount must be a number." 
           data-val-required="The Amount field is required." 
           id="Amount" name="Amount" value="">
    <input type="submit" value="Submit">
    <input name="__RequestVerificationToken" type="hidden" 
           value="CfDJ8KlQ1R0OJt5HhbmU6I--jSI5IXa1BKXKEbshhG9sBj6FCKAMU6Wp3ItRrWN3yLtd8Xjj8C7O7bhqO_AvpLs7Dy8L8ONXCEvrbpUYtKRlJif69ULxLAGumiplLy1bs2YsQhlq66sAlOddh7U1qsYYTo">
</form>

When the ‘form’ has been posted to server with ‘submit’ button click then the random string also has been posted with ‘form data’ and server actually validate that string to understand that the request actually comes from its own website and not from any external website. If the validation failed, then ASP.NET kills the request towards the action method. The external malicious website has no way to know the random string because it is in a hidden field and it is random (every request it has been generated with different string) and its cannot put that into its ‘form data’.

In this way no external website can post data to your money deducting action method.

–Arnab

Advertisements

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 )

Google+ photo

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

Connecting to %s