Introduction
Using query strings to send data from the browser to the server is a widespread approach. Giving the visitor of a web application the opportunity of modifying query strings by transmitting them in clear text, is certainly a potential security threat.
Thus, I encourage developers to encrypt query strings, even if they do not contain confidential data. However, I am aware that it is still possible to alternate an encrypted query string, but with an appropriate exception handling, this is harmless.
Background
To keep this article simple, I used a contradictable encryption (DES encoding), though any cutting-edge encryption can be easily applied to the samples given.
Using the code
So, let's get down to business. The main part of the presented solution consists of a HttpModule
which decrypts the query string and hence provides the page request with the ordinary unencrypted query strings:
using System;
using System.Web;
using System.Web.Configuration;
namespace HelveticSolutions.QueryStringEncryption
{
public class CryptoQueryStringUrlRemapper : IHttpModule
{
#region IHttpModule Members
public void Init(HttpApplication application)
{
application.AcquireRequestState += application_AcquireRequestState;
}
public void Dispose()
{}
#endregion
public void application_AcquireRequestState(object sender, EventArgs e)
{
HttpApplication application = (HttpApplication) sender;
HttpContext context = application.Context;
string encryptedQueryString = context.Request.QueryString["request"];
if (!string.IsNullOrEmpty(encryptedQueryString))
{
string cryptoKey = WebConfigurationManager.AppSettings["CryptoKey"];
string decryptedQueryString =
CryptoQueryStringHandler.DecryptQueryStrings(encryptedQueryString,
cryptoKey);
context.Server.Transfer(
context.Request.AppRelativeCurrentExecutionFilePath +
"?" + decryptedQueryString);
}
}
}
}
As you might have noticed, if there is an encrypted query string for the current request, the module automatically terminates the execution of the current page and internally starts execution of a new request on the server.
The next step is to register the HttpModule
in the web.config file:
<httpModules>
<add name="CryptoQueryStringUrlRemapper"
type="HelveticSolutions.QueryStringEncryption.CryptoQueryStringUrlRemapper"/>
</httpModules>
Last but not least, do not forget to encrypt query strings before sending them back to the server:
private void PrepareSendButton()
{
NameValueCollection queryStrings = new NameValueCollection();
queryStrings.Add("param1", "Test1");
queryStrings.Add("param2", "Test2");
queryStrings.Add("param3", "Test3");
string encryptedString = CryptoQueryStringHandler.EncryptQueryStrings(
queryStrings, WebConfigurationManager.AppSettings["CryptoKey"]);
btnSendParams.PostBackUrl = string.Concat("~/Default.aspx?", encryptedString);
}
As outlined earlier in this article, the encryption class can be easily replaced by any other encryption class. A full running sample can be downloaded above.
Important issue
The method DecryptQueryStrings
in the CryptoQueryStringHandler
contains the following line :
return Encryption64.Decrypt(encryptedStrings.Replace(" ", "+"), key);
For unknown reasons, the request replaces every '+' character in the query with an empty character.
History
- 30.04.2008 - First version (deleted -> was not possible to modify, why ever...).
- 01.05.2008 - Re-released updated article.
- 08.05.2008 -
BeginRequest
event in the HttpModule
changed to AcquireRequestState
in order to support Session data. - 11th November 2014 - Namespace corrected