Introduction

Threat and security measures go hand in hand in the history of internet era. We have improved a lot in security measures to make hacker's life really hard. Here I am expalining a method which prevents the submission of any malformed URL request (forged URL) to a web application. The idea is simple that any URL request to the secured application spacecan be verified for its identity. So that our application knows this request is trustable.

Generally we have checksum and hash for protecting files and data transmission in a secured transaction. But it is not a general practice to use this method on a URL request. This article explains the threat of URl forgery and how an URL hash is a useful solution with an example

Background

Before jump in to the sample application let us brush up the security methods available with ASP.Net MVC.

  1. Authorize attribute: This is useful to authorize a user or role to access any resource in the application after authenticated. So we can have seamless flexibility to control user/roles based restrictions without any additional codes.
  2. Http Referrer Check: This is a general method not confined to .NET. This is to prevent an URL request which is not from the site, but from an external link or the link directly pasted at the navigation bar.
  3. Anti Forgery Token: This is a powerfull option to prevent any hidden field manipulation while form posting and prevents Cross-Site Request Forgery
  4. Html Encoding: It is advised to encode all user inputs to prevent Cross Site Scripting attack/ XSS attack etc.,
  5. Encryption of Query string parameters. This is good way to prevent manipulation of query string parameters. But this is not a complete protection, still vulnerable for a brute force attack.

But there is no inbuilt support to check the URL or part of the URL is manipulated before submission. 

Using the Code 

Though it is general concept  this example developed with Visual Studio Express 2010, C#, ASP.Net MVC 2 (These plateforms are freely available for download).

This is a small proof of concept question bank application where it has students. Each student is assigned to subjects and they should allow to view questions belong to the subjects assigned to them. Below is the database relationship diagram.

sample_DB.jpg

Fig 1: Showing the Database relationship in the sample application

This database is very simple and nothing much to explain. The work flow like user logged in, select a subject and it display the exams conducted in that subject. The exams contains questions. Note the below user interface shows a questions link, which is the key place we are going to talk further.

sample_question_link.jpg

Figure 2: List of exams with link to questions showing secure and unsecure links

The above picture shows the  secured link and a unsecured link which are as follows.

http://localhost:49510/Questions/QuestionsView/2/RayZZsXb1M8fjToWiVgEkQGr%2bI0%3d 
http://localhost:49510/Questions/UnsecuredQuestionsView/2
*(change the localhost:port number to your URL)

The only difference between these two URLs is the second parameter which is a hash. Before looking into how the hash is formed let us have a word about the threat here.

What if the authorized user change the id (exam id here) parameter to another value, for example like http://localhost:49510/Questions/UnsecuredQuestionsView/7 which is an exam id belongs to a subject not assigned to the logged in user (albin, password: test123).

Let us see the ways to prevent it. If this URL pasted to the navigation bar or access this link from a different website , it won't work because it checks for http referrer.But still it doesn't prevent the threat.  But still (when you are on the exams page) you can use the following javascript pasted in the navaigation bar and hit enter, which will give you an link.

javascript:document.getElementById('testplace').innerHTML=
    '<a href="http://localhost:49510/Questions/UnsecuredQuestionsView/7">Test Me</a>';

We can have the id parameter encrypted then it is secured, but once the database is bigger then the chance of getting hit by brute forcing by random manipulation of the hash is higher.

We can verify the parameter by checking  through parent-child table relationship. But this tedious and need specific logics for each method.

So is it a better method available where the URL can't be forged?!. Yes it is. We can compute a hash out of the URL and pass that hash as a parameter and then verify it in the called method. It is a simple technique. Let us have a look how we can implement it in asp.net MVC.

       //This method accepts the partial path, starts from the controller and 
       //end with the parameters. Also It accepts a password
        public static string generateUrlToken(string controllerName, string actionName,
            ArrayList argumentParams, string password)
        {
            string token = "";
            //The salt can be defined global
            string salt = "#testsalt";
            //generating the partial url
            string stringToToken = controllerName + "/" + actionName + "/";
            foreach (string param in argumentParams)
            {
                stringToToken += "/" + param;
            }
            //Converting the salt in to a byte array
            byte[] saltValueBytes = System.Text.Encoding.ASCII.GetBytes(salt);
            //Encrypt the salt bytes with the password
            Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, saltValueBytes);
            //get the key bytes from the above process
            byte[] secretKey = key.GetBytes(16);
            //generate the hash
            HMACSHA1 tokenHash = new HMACSHA1(secretKey);
            tokenHash.ComputeHash(System.Text.Encoding.ASCII.GetBytes(stringToToken));
            //convert the hash to a base64string
            token = Convert.ToBase64String(tokenHash.Hash);
            return token;
        }

The above method accepts part of the URL the controller name, action name and the parameter array. It returns a hash that can be added to the URL as below.

&lt;%
     ArrayList args = new ArrayList();
     args.Add(Convert.ToString(item.ExamId));
     string token = SecureUrl.Models.SecureUrlToken.generateUrlToken("Questions", 
         "QuestionsView", args, "QuestionList");
%&gt;

 &lt;%: Html.ActionLink("Questions- Secured Link", "QuestionsView", "Questions", 
    new {id = item.ExamId,urltoken=token }, null)%&gt;

The same way it can be veryfied in the controller as follows.

 public ActionResult QuestionsView(string id, string urltoken)
    {
        //The url token is generated by the same way it is generated for the link
        ArrayList args = new ArrayList();
        args.Add(Convert.ToString(id));
        //This method employs a common business logic for all urls, but only the
        //parameters are different
        //It helps the url password protected
         string token = SecureUrlToken.generateUrlToken("Questions", "QuestionsView",
             args, "QuestionList");

        //The url token is cross checked here to ensure that url parameters are not forged
          if (token == urltoken)

This method can be resued anywhere in the application. Be secure!!.

Points of Interest

I have written this small article to make use of this method in the common web applications, because I came across many sites which pass parameters in the URL unsecured. So thought make this method more common I choose popular code project to publish it.

As a final word if errors there forgive me. In my next article I will write about how this can be implement in ajax requests.