Creating tamper proof Url in asp.net – a way to prevent spoofing and forged HTTP requests

Consider the following URL-

http://www.mysite.com/orders.aspx?id=10 

Now the problem is that anybody having this link can view more data than authorised and required by simply changing the value of id to say 16,17,18,19…
Another problem could be that script tags could be added to the URL by malicious sources.

Here is how I prevented the same situation in one of my project as secuirity fixes. The basic idea was to append an additional secret MD5 encrypted query string (Digest) in the URL while redirecting to a page and on the page load of the target page (redirected page) check wheather the Digest is correct or not. If Digest matches, URL is valid, else throw the user out of the system. In my example below, I have used “prady##blog” as the seceret code. This seceret code can be modified as required.
Lets come to the code part to implement this. Add a C# class file in your project and copy-paste following code-

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
public class CL_URLTempering
{
    public static string CreateTamperProofQryStringURL(string Page)
    {
        string strpage = Page.Remove(0, 2); //assuming that the URL like
                     ~/PageName.aspx; the code removes ~/ from the URL
        try
        {
            return string.Concat(Page + "&Digest=", GetDigest(strpage));
            //Adding an additional querystring - Digest
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
    public static bool EnsureURLNotTampereding(string Url, string tamperProofParams)
    {
        try
        {
            string expectedDigest = GetDigest(Url); //Expected Digest
                                    as per received querystring
            string receivedDigest = tamperProofParams; //Actual Digest
                                    as sent from previous page
            if (receivedDigest == null)
            {
                return false;
            }
            else
            {
                receivedDigest = receivedDigest.Replace(" ", "+");
                if (string.Compare(expectedDigest, receivedDigest) != 0)
                //return false in case expectedDigest and receivedDigest do not match
                {
                    return false;
                }
                else
                    return true;
            }
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }   

    public static string GetDigest(string tamperProofParams)
    {
        try
        {
            string SecretSalt = "prady##blog"; //change the seceret code as desired
            string Digest = string.Empty;
            string input = string.Concat(SecretSalt, tamperProofParams, SecretSalt);
            byte[] hashedDataBytes;
            System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding();
            System.Security.Cryptography.MD5CryptoServiceProvider md5Hasher =
                new System.Security.Cryptography.MD5CryptoServiceProvider();
            hashedDataBytes = md5Hasher.ComputeHash(encoder.GetBytes(input));
            Digest = Convert.ToBase64String(hashedDataBytes).TrimEnd("=".ToCharArray());
            return Digest;
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
}

Now modify Response.Redirect() code lines as-

Response.Redirect(CL_URLTempering.CreateTamperProofQryStringURL
("~/PageName_new.aspx?id="1&catgID=2&Type=3"));

This actually will redirect to a URL like-

PageName_new.aspx?id="1&catgID=2&Type=3&Digest=vsmEhO2T8g6wIlNU4FK6aQ

Now on page load of PageName_new.aspx, add following code-

if (Request.Url.Query != "")
if (!CL_URLTempering.EnsureURLNotTampereding(
Request.Url.Segments[Request.Url.Segments.Length - 1] +
Request.Url.Query.Substring(0, Request.Url.Query.LastIndexOf("&Digest=")),
Request.QueryString["Digest"]))
{
    Response.Redirect("~/Error.aspx");
}

Now if you try modifying URL; the system will Redirect you to Error.aspx because the Digest query string contains encrypted querystring + Seceret code. You can change readable part of querystring value but you can not guess/ calculate and change correct MD5 Digest.
Any problem using the code, please let me know and I will be glad to help you.

This entry was posted in ASP.NET, C#, Knowledge Sharing, Troubleshooting. Bookmark the permalink.

Leave a Reply