Table of Contents
- Introduction
- The Motivation
- TagSinj Intervention
- Overview of Functionality
- The Actual Code Behind It
- Using the Code
- Comments
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.
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 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.
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)
).
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
.
public static string generateSecureLink(string link)
{
string toHash = "";
string[] querystring = null;
string[] vars = null;
string[] vals = null;
if (link.Contains("?"))
{
querystring = link.Split('?'); vars = querystring[1].Split('&');
foreach (string st in vars)
{
vals = st.Split('=');
toHash += vals[1].ToString();
}
}
else
{
querystring = link.Split('?');
vars = querystring[1].Split('=');
toHash += vals[1].ToString();
}
string hashed = TagSinj.Hash(toHash + TagSinj.AccessCode);
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.
public static bool validateLink(HttpRequest Request)
{
try
{
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;
}
}
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.
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:
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))
{
Response.Write("The parameters are correct");
}
else
{
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.
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.