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.