HTTP Request Query String Protection






4.44/5 (27 votes)
Add one layer of security to your Web application
Table of Contents
- Introduction
- The Motivation
- TagSinj Intervention
- Overview of Functionality
- The Actual Code Behind It
- Using the Code
- Comments
Introduction
This article will present a solid method of securing your query string from SQL injections. The overall idea was inspired from the way payment gateways secure their parameters.
TagSinj (Stands for Tag Secure Injection) class includes two main functions which can integrate easily with all Web applications.
The Motivation...
When building applications, it is very necessary to secure the way you grab parameters sent by the HTTP query string. It is very common and simplistic for users just to alter those parameters and mess up your application. For example, let's say you are using two parameters in your query string, one to identify the page you wish to load, and another to load a specific product using its ID (Database ID, i.e.: Primary Key), your query string might look as follows:
http://www.yourdomain.com/default.aspx?page=products&id=234
Let's say you are grabbing those parameters and generating a database query. Your database query might look like this:
SELECT * FROM product WHERE ProductID = '234'
A simple manipulation of the query string is as follows (removing the value of the parameter "id
"):
http://www.yourdomain.com/default.aspx?page=products&id=
Your dynamically generated database query will turn out to be:
SELECT * FROM product WHERE ProductID = ''
That usually won't do much harm, except that it wouldn't load properly by the user, but what if your environment is not secured enough? For example:
http://www.yourdomain.com/default.aspx?page=products&id=';DROP DATABASE databasename;--
Your dynamically generated database query will turn out to be:
SELECT * FROM product WHERE ProductID = '';DROP DATABASE databasename;--'
This can be quite harmful...
TagSinj Intervention
TagSinj intervenes just one layer prior to generating your database query string. Once your page loads, TagSinj will check the sent parameters. If they are authentic, then you can continue executing your code, otherwise, they have been manipulated. You can break execution of the code and handle the exception accordingly.
Overview of Functionality
The main concept behind this idea is mainly to confirm that the parameters that were sent from one page are exactly the same as the parameters received by the recipient page (Works fine, even if both pages are the same page).
To do so, this class will append an additional parameter to the querystring (called "mac
") which is an MD5 string (The mac parameter is the MD5 result of all parameters concatenated together with a Secure Access code).
Thus, in order to lock your query string from injections, you would need to generate secure links (generateSecureLink(string link)
) and upon loading the page, you need a method to authenticate the parameters (validateLink(HttpRequest Request)
).
The Actual Code Behind It...
First, I will discuss the method that generates the secure links. What this method would do is take the original link that you use, for example: default.aspx?par1=hello&par2=world
and return default.aspx?par1=hello&par2=world&mac=MD5STRING
where MD5STRING
is your par1
value concatenated with your par2
value concatenated with your secure access key, i.e. in this case we would have (and if our access code is "howareyou
"): helloworldhowareyou
.
/// <summary>
/// This method takes a link and appends to it the secure hash used to
/// validate the query string
/// </summary>
/// <param name="""""link""""" />link</param>
/// <returns>input link with mac paramater appended</returns>
public static string generateSecureLink(string link)
{
string toHash = "";
string[] querystring = null;
string[] vars = null;
string[] vals = null;
//if the link has some parameters
if (link.Contains("?"))
{
querystring = link.Split('?'); vars = querystring[1].Split('&');
foreach (string st in vars)
{
vals = st.Split('=');
//toHash has all parameters value appended next to each other
toHash += vals[1].ToString();
}
}
//otherwise
else
{
querystring = link.Split('?');
vars = querystring[1].Split('=');
toHash += vals[1].ToString();
}
//append the access code to the end of the string and MD5 the result
string hashed = TagSinj.Hash(toHash + TagSinj.AccessCode);
//returns the mac parameter appended to the link
return link + "&mac=" + hashed;
}
Secondly, you would need a method that validates the generated secure link (it is to be used whenever you want to validate that your query string is received exactly the same way that it was sent.
This method takes the HttpRequest
(uses the querystring from it). It basically retakes all parameters passed by the querystring except for the "mac", re-concatenates them in the same order they were passed and appends the access key.
Then it matches the resulting MD5 string with the grabbed MD5 string. If both match, then the query string is safe, otherwise it has been manipulated and there is a possible threat.
/// <summary>
/// This method takes an HttpRequest as a parameter and checks
/// whether the query string parameters have been
/// manipulated by the user
/// </summary>
/// <param name="""""Request""""" />
/// HttpRequest, used to take the querystring item</param>
/// <returns>true if query string is authentic, false otherwise</returns>
public static bool validateLink(HttpRequest Request)
{
try
{
//loop through all the parameters and recreate the hash
if (Request.QueryString.Count > 0)
{
String[] queryKeys = Request.QueryString.AllKeys;
int queryCount = Request.QueryString.Count;
string toHash = "";
for (int m = 0; m < queryCount; m++)
{
if (queryKeys[m] != "mac")
{
toHash += Request.QueryString[queryKeys[m]];
}
}
string hashed = TagSinj.Hash(toHash + TagSinj.AccessCode);
if (hashed != Request.QueryString["mac"])
{
return false;
}
else
{
return true;
}
}
else
{
return false;
}
}
catch
{
return false;
}
}
Using the Code
Below, I will illustrate the way to use this class:
Step 1: Include
- Download TagSinj.zip
- Add the *.dll file as a reference in your project
- Include the file in your *.cs files:
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using TagSinj;
Once the above step has been taken care of, you can now use the two methods offered by this class.
Step 2: Setting up the Access Code
To have a unique "mac" you have to set a value to your access code. This can be set once in your global.asax page or in the page where you are using this class. The access code can be any string
of your choice.
//The below selected access code is for illustration purposes only //Simpler or more complex codes can be randomly generated TagSinj.TagSinj.AccessCode = "AV$%990LK_12";
Step 3: Generating Secure Links
In order for the query string to be accepted by your application, you have to generate secure links using:
//the generateSecureLink function will append to the parameter added a
//"mac" parameter which will be a unique way of identifying your
//sequence of parameters
secureLink = TagSinj.TagSinj.generateSecureLink
("anyPage.aspx?var=test1&var1=test2&var2=test3");
Your resulting value should look like:
anyPage.aspx?var=test1&var1=test2&var2=test3&mac=bc2d6cb550c88bed381521bea654ea11
Step 4: Grabbing Your Variables
Now that you have your links secured, it is time to make sure that no one is manipulating your query string. To do so, under the Page_Load
event, add this piece of code:
if (TagSinj.TagSinj.validateLink(this.Request))
{
//parameters are exactly the same way you have sent them
//Do action
Response.Write("The parameters are correct");
}
else
{
//somebody is playing around with the parameters
//Do action
Response.Write("The parameters are incorrect");
}
Conclusion
This way, you have made sure that the parameters that you have sent from one page are exactly the same as the parameters you have received. This functionality will greatly reduce to the point of eliminating the threat of SQL injections to your website.
Comments
This is my first article here at The Code Project. Any comments would be appreciated. Drop me an email if you are planning to use this DLL.
Thank you for reading.