Backend

Introduction

I recently needed to restrict page access to authorised visitors with valid query parameters. The solution involved employing SHA-256 hashing to safeguard query strings from tampering.

Concept

Query string protection works by appending a hash value to URLs:

https://www.mywebsite.com/mypage?x=value1&y=value2&hash=532eaabd9574880dbf76b9b8cc00832c20a6ec113d682299550d7a6e0f345e25

If an attacker tries to modify any part of the query string parameter values (x, y or hash) the system will know and reject the URL, as the query string values don’t match the provided hash value.

Hash Calculation

The process concatenates query parameters with a salt value, then applies SHA256 hashing:

x + y + Salt → SHA256 = hash value appended to URL

Hash Salt Explanation

Direct hashing of parameters creates vulnerability — attackers could independently calculate hash values. A random salt value (ideally a GUID) known only to the system prevents this exploitation.

Code Implementation

Generate URL with hash protection:

public string GenerateUrl(string queryStringOne, string queryStringTwo)
{
    string hashedVariables = GenerateHashToken(queryStringOne, queryStringTwo);

    string url = String.Format("?x={0}&y={1}&token={2}", queryStringOne, queryStringTwo, hashedVariables);

    return url;
}

Generate hash token:

private string GenerateHashToken(string queryStringOne, string queryStringTwo)
{
    // Use a random GUID for the salt e.g. 313fdac5-af26-44bd-9dbc-70a15d4093c6
    string salt = System.Configuration.ConfigurationManager.AppSettings["QueryStringHash.Salt"];

    string concatVariables = queryStringOne + queryStringTwo + salt;
    string hashedVariables = GetSha256Hash(concatVariables);

    return hashedVariables;
}

SHA256 hashing method:

private string GetSha256Hash(string text)
{
    byte[] bytes = Encoding.UTF8.GetBytes(text);
    SHA256Managed hashstring = new SHA256Managed();
    byte[] hash = hashstring.ComputeHash(bytes);
    string hashString = string.Empty;

    foreach (byte x in hash)
    {
        hashString += String.Format("{0:x2}", x);
    }

    return hashString;
}

Validate URL integrity:

public bool IsValidUrl(string queryStringOne, string queryStringTwo, string token)
{
    if (string.IsNullOrWhiteSpace(token))
    {
        return false;
    }

    string hashedToken = GenerateHashToken(queryStringOne, queryStringTwo);

    return hashedToken == token;
}

Implementation Notes

I organised this logic into a HashQueryStringService.cs service file. Enhancement opportunities include creating more generic implementations using Request.QueryString looping functionality.