Posted on 4/5/2020 3:29:01 PM by Admin

AntiForgeryToken in Asp.Net MVC

Before learning AntiForgeryToken ,let's unfold the term forgery in day-today life. If someone copies someone's signature on bank's cheque to withdraw money from his account, or anybody copies someone's work or art like copy the lyrics of music written by someone and show off it as his own work ,all of these act is called as forgery.

Nowadays almost everything has gone online, you can transfer money from your bank account to your friend or relative's bank account with some click only, the only condition is you must be logged in to your bank's website. Login in bank website ensures that you are a valid customer of that bank.

Now again come to the term forgery, if anybody steal something from somewhere in physical world then they are called as thief, similarly if someone steals something online then they are called as Hacker. Hacker can even steal your identity and pretend to be you and can access everything , whatever you can access online. This act is termed as digital forgery and we call it cyber crime.

Now let's take an example which will help us to understand AntiforgeryToken. Whenever we are Logged in to any website( account) then we can navigate anywhere within the site without logging in for each page(navigation),we can even request the same URL from another tab of our browser and the site do not ask us to log in. This is because at the time of logging in ,the site's server create a secret cookie(can be considered as our identity for that site) and send it to our browser ,if you request the same URL again within the same session meaning without closing the browser from any tab then the browser send that secret cookie also with our request, on the other side the bank's server read the cookie and assures himself that it's you.

Now suppose you are logged in to your bank's website from your browser and some other site is also opened in other tab at the same time. You have opened the other site thinking that it is a gaming site but actually it is created by a hacker and when you click any button from such site a request from your browser to transfer money goes to your bank website. As the URL is same your browser will send the cookie also and the bank's server thinks the request is coming from a trusted user (you) and processes the request. This is called as CSRF cross site request forgery.

AntiforgeryToken is used to prevent such CSRF attack. Let's first create a bank site with CSRF vulnerabilities and create another site to perform CSRF attack, in short let's be a Hacker for a few minute.

CSRF attack
CSRF attck

As you can see two tabs are open ,in first tab the hacker's site is opened and on the second tab your bank site is opened ,when you click button on hacker site a request to your bank site goes from your browser with all required values ,as the URL is same ,your browser sends the cookie too with the request to bank server and the bank server thinks it is a valid request and processes it like your normal request.

In order to understand CSRF attack completely ,Create two projects one Bank site with two modules and other Hacker site with one module.

Bank Site:-
  1. Login Module.
  Here as soon as the user will login a cookie will be created and send to the browser so for next request onwards he will not need to login anymore within the same session.
  2. Transaction Module.
  Here we will create two methods one to return Data Entry Screen and other to transfer money .

And other as a Hacker site with one module only.

Hacker Site:-
Here will create a UI with a button ,and will create a form similar to bank website with hidden fields so that when the user will click it actually a request with required values will go to the bank site.

Bank Website:-

I)Login Module:-

create two Login method one to provide login screen and other to validate user and creating cookie. I am using forms authentication for this purpose.


         [HttpGet]
        public ActionResult Login(string ReturnUrl)
        {
            ViewBag.ReturnUrl = ReturnUrl;
            return View();
        }
        [HttpPost]
        public ActionResult Login(string UserName, string Password, bool RememberMe, string ReturnUrl)
        {
            if (UserName == "sachin" & Password == "sachin@7777")
            {
                FormsAuthentication.SetAuthCookie(UserName, RememberMe);
                return Redirect(ReturnUrl);
            }
            return View("Login");
        }


        
  @{
    ViewBag.Title = "Login";
    }
   <h2>Login</h2>
    <form action="/Home/Login" method="post">
    User Name:@Html.TextBox("UserName")
    Password :@Html.Password("Password")
    Remember Me:@Html.CheckBox("RememberMe")
    @Html.Hidden("ReturnUrl", new { @value = ViewBag.ReturnUrl})
    <button type="submit">Login</button>
    </form>

To implement forms authentication add below lines to your webconfig.


        <system.web>
      <authentication mode="Forms">
        <forms loginurl="~/Home/Login">
        </forms>
     </authentication>
    <compilation debug="true" targetframework="4.5" />
    <httpruntime targetframework="4.5" />
    </system.web>

II)Transaction Module

Create two Action method one for returning Transfer money screen and other for processing the request and perform transaction.


         public ActionResult TransferFund()
        {
            return View();
        }
        [Authorize]
        public ContentResult MoneyTransfer(string Amount, string Account)
        {
            return Content("Amount" + Amount + " " + "successfully transfered to" + " " + Account);
        }


        @{
    ViewBag.Title = "TransferFund";
     }
  <h2>TransferFund</h2>
   <form action="/Home/MoneyTransfer" method="post">
    <table>
        <tr>
            @Html.AntiForgeryToken()
            <td>@Html.Label("Amount")</td>
            <td>@Html.TextBox("Amount")</td>
        </tr>
        <tr>
            <td>@Html.Label("Account No")</td>
            <td>@Html.TextBox("Account")</td>
        </tr>
        <tr>
            <td colspan="2"><button type="submit">Transfer Money</button></td>
        </tr>
      </table>
   </form>

Now run the application you will get below results.

Transfer Fund Screen
Transfer Fund Screen
Login Screen
Login Screen

Do login with the password and User Name as specified in code and transfer money you will get below result.

Transfer Success
Transfer Success

Hacker Site:-

Create One method to return a simple screen with the hidden fields and URL as bank site URL like below.


   public ActionResult Index()
        {
            return View();
        }


  @{
    ViewBag.Title = "Index";
    }
  <h2>Index</h2>
  <form action="http://localhost:1075/Home/MoneyTransfer">
    <table>
        <tr>
            @Html.Hidden("Amount", new { @value = "30000" })
        </tr>
        <tr>
            @Html.Hidden("Account", new { @value = "3456782" })
        </tr>
        <tr>
            <td colspan="2"><button type="submit">win 20000$</button></td>
        </tr>
    </table>
   </form>

Now run both the application at a time ,and click win $2000 button of Hacker site.

Hacker Site
Hacker Site

You will be able to successfully transfer money and hence you becomes a hacker who knows how to perform CSRF attack.

Now, in order to avoid CSRF attack In Asp.Net MVC we use AntiforgeryToken.

AntiForgeryToken:-

This a secret token set on every UI from where any important post request comes. For example the bank website gives the user a screen to transfer money ,this screen must contain the AntiForgeryToken, when post request comes from such UI (Form) then along with every required value the token also goes as a query string ,on the other side the server validate this token and confirms that everything is alright.

So, let's add the AntiforgeryToken in TransferFund UI like below.


    @{
    ViewBag.Title = "Index";
   }
 <h2>Index</h2>
  <form action="/Home/MoneyTransfer">
    <table>
        <tr>
            @Html.AntiForgeryToken();
            @Html.Hidden("Amount")
        </tr>
        <tr>
            @Html.Hidden("Account")
        </tr>
        <tr>
            <td colspan="2"><button type="submit">win 20000$</button></td>
        </tr>
      </table>
    </form>

To Validate this Token Add ValidateAntiForgeryToken attribute to your Action Method like below.


         [Authorize]
       [ValidateAntiForgeryToken]
        public ContentResult MoneyTransfer(string Amount, string Account)
        {
            return Content("Amount" + Amount + " " + "successfully transfered to" + " " + Account);
        }

As you can see AntiForgeryToken is nothing but a Html helper method which generates a hidden field with some unique value.

There is a myth that even if ,It is good and reduces the chances of CSRF attack ,but hackers are usually of brilliant mind, they too can use AntiforgeryToken while creating Hidden form , so the another version of AntiForgeryToken which accepts salt that is a unique value should be used ,and that if you specify Salt in AntiForgeryToken then Salt+SecretCode merges to create a more unique Token. So we should always use the second version and specify Salt like below.


          @Html.AntiForgeryToken("mySecret123")

Here mySecret123 is Salt which makes the token more unique.(myth)

Now in the server side to validate the Token add ValidateAntiForgeryToken attribute to the Action method like below.


         [Authorize]
       [ValidateAntiForgeryToken(Salt="mySecret123")]
        public ContentResult MoneyTransfer(string Amount, string Account)
        {
            return Content("Amount" + Amount + " " + "successfully transfered to" + " " + Account);
        }

But in reality the term Salt was misleading and of no use actually AntiForgeryToken generates unique value for each user ,so using Salt is unnecessary. That is why, in latest version of .Net Salt has been deprecated.