royco
royco

Reputation: 5529

How can I make a query string tamper-proof?

I need to use query strings in a URL, but need to ensure that they haven't been tampered with. I found a solution which almost works, but the encoded strings get mangled by a service my app needs to use. Can anyone think of a different solution?

EDIT: The solution I mention doesn't work for me because the Base64 encoded query string it produces contains "+". The service I pass this query string to doesn't properly handle "+", and I can't even URL encode it to "%2B". I can substitute "_" for it, I suppose. However, I was wondering if there was a different solution entirely.

EDIT 2: To be more clear, the solution I reference works, but I was wondering about alternative solutions.

Upvotes: 3

Views: 4335

Answers (3)

Zo Has
Zo Has

Reputation: 13038

You can compute and pass a hash of your parameters along with your querystring. On your landing page, compute the hash again and compare it with the query string hash, if both are not same it means the URL is tampered.

You can make functions inside a utility class like

const string secretKey = "%%YoUrSeCrEtKeY##";

     public static string CreateTamperProofUrl(string pageUrl)
    {
        try
        {
            return HttpUtility.UrlEncode(CreateDigest(pageUrl.Trim()));
        }
        catch (Exception)
        {
            throw;
        }
    }

    private static string CreateDigest(string pageUrl)
    {
        string urlToEncode = secretKey + pageUrl + secretKey;
        var hasher = new MD5CryptoServiceProvider();
        var encoder = new UTF8Encoding();

        byte[] hashedDataBytes = hasher.ComputeHash(encoder.GetBytes(urlToEncode));
        string signatureData = Convert.ToBase64String(hashedDataBytes);

        return signatureData;
    }

    public static bool IsValidDigest(string pageUrl, string receivedDigest)
    {
        if (receivedDigest == null)
        {
            return false;
        }

        string expectedDigest = CreateDigest(pageUrl);
        if (string.Compare(receivedDigest, expectedDigest) != 0)
        {
            return false;
        }
        else
            return true;
    }

On your landing page just check like this

    if (!Page.IsPostBack)
        {
            if (Request.QueryString["Digest"] != null)
            {
                // compare the digest
                string id = Request.QueryString["fid"];
                string digest = Request.QueryString["Digest"];

                if (Utility.IsValidDigest(id, digest))
                {
                    lblStatus.ForeColor = System.Drawing.Color.DarkGreen;
                    lblStatus.Text = "Valid digest received";
                }
                else
                {
                    lblStatus.ForeColor = System.Drawing.Color.Red;
                    lblStatus.Text = "Url is tampered!";
                }

            }
   }

Upvotes: 2

Muhammad Akhtar
Muhammad Akhtar

Reputation: 52241

you can encrypt your querystring value and then pass it and where you want to use, simply decrypt it. Also check these articles... how-to-encrypt-query-string-parameters-in-asp-net

http://www.codeproject.com/KB/web-security/QueryStringEncryptionNET.aspx

Upvotes: 4

Michael Gattuso
Michael Gattuso

Reputation: 13210

Basically a duplicate of: Security with QueryString values in Asp.net MVC

Bottom line - never trust input from the user especially over the web, always assume a user can and will tamper with the inputs.

Upvotes: 2

Related Questions