Click here to Skip to main content
Click here to Skip to main content

Global Query String Encryption

, 26 Apr 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
Query String Encryption without changing source

Introduction 

Most old web applications use query strings to send data between pages. This problem makes applications vulnerable to query string injection attacks. The main problem in these projects is that they cannot afford a lot of costs to change the way of using query strings.

Background 

In this project we are using HTTP Modules to encrypt and decrypt query strings.

Using the code  

The QueryStringModule class implements the IHttpModule interface. This interface uses the BeginRequest delegate to control requests to the website. As you can see in the picture above this module controls all of the requests and responses to the application.

In this project we use 64 bit encryption from the RijndaelManaged class. 

#region Using
 
using System;
using System.IO;
using System.Web;
using System.Text;
using System.Security.Cryptography;
 
#endregion
 
/// <summary>
/// Summary description for QueryStringModule
/// </summary>
public class QueryStringModule : IHttpModule
{
 
    #region IHttpModule Members
 
    public void Dispose()
    {
        // Nothing to dispose
    }
 
    public void Init(HttpApplication context)
    {
        context.BeginRequest += new EventHandler(context_BeginRequest);
    }
 
    #endregion
 
    private const string PARAMETER_NAME = "enc=";
    private const string ENCRYPTION_KEY = "key";
 
    void context_BeginRequest(object sender, EventArgs e)
    {
        HttpContext context = HttpContext.Current;
        if (context.Request.Url.OriginalString.Contains("aspx") && 
                   context.Request.RawUrl.Contains("?"))
        {
            string query = ExtractQuery(context.Request.RawUrl);
            string path = GetVirtualPath();
 
            if (query.StartsWith(PARAMETER_NAME, StringComparison.OrdinalIgnoreCase))
            {
                // Decrypts the query string and rewrites the path.
                string rawQuery = query.Replace(PARAMETER_NAME, string.Empty);
                string decryptedQuery = Decrypt(rawQuery);
                context.RewritePath(path, string.Empty, decryptedQuery);
            }
            else if (context.Request.HttpMethod == "GET")
            {
                // Encrypt the query string and redirects to the encrypted URL.
                // Remove if you don't want all query strings to be encrypted automatically.
                if (query != "")
                {
                    string encryptedQuery = Encrypt(query);
                    context.Response.Redirect(path + encryptedQuery);
                }
            }
        }
    }
 
    /// <summary>
    /// Parses the current URL and extracts the virtual path without query string.
    /// </summary>
    /// <returns>The virtual path of the current URL.</returns>
    private static string GetVirtualPath()
    {
        string path = HttpContext.Current.Request.RawUrl;
        path = path.Substring(0, path.IndexOf("?"));
        path = path.Substring(path.LastIndexOf("/") + 1);
        return path;
    }
 
    /// <summary>
    /// Parses a URL and returns the query string.
    /// </summary>
    /// <param name="url" />The URL to parse.
    /// <returns>The query string without the question mark.</returns>
    private static string ExtractQuery(string url)
    {
        int index = url.IndexOf("?") + 1;
        return url.Substring(index);
    }
 
    #region Encryption/decryption
 
    /// <summary>
    /// The salt value used to strengthen the encryption.
    /// </summary>
    private readonly static byte[] SALT = Encoding.ASCII.GetBytes(ENCRYPTION_KEY.Length.ToString());
 
    /// <summary>
    /// Encrypts any string using the Rijndael algorithm.
    /// </summary>
    /// <param name="inputText" />The string to encrypt.
    /// <returns>A Base64 encrypted string.</returns>
    public static string Encrypt(string inputText)
    {
        RijndaelManaged rijndaelCipher = new RijndaelManaged();
        byte[] plainText = Encoding.Unicode.GetBytes(inputText);
        PasswordDeriveBytes SecretKey = new PasswordDeriveBytes(ENCRYPTION_KEY, SALT);
 
        using (ICryptoTransform encryptor = 
          rijndaelCipher.CreateEncryptor(SecretKey.GetBytes(32), SecretKey.GetBytes(16)))
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
                {
                    cryptoStream.Write(plainText, 0, plainText.Length);
                    cryptoStream.FlushFinalBlock();
                    return "?" + PARAMETER_NAME + Convert.ToBase64String(memoryStream.ToArray());
                }
            }
        }
    }
 
    /// <summary>
    /// Decrypts a previously encrypted string.
    /// </summary>
    /// <param name="inputText" />The encrypted string to decrypt.
    /// <returns>A decrypted string.</returns>
    public static string Decrypt(string inputText)
    {
        RijndaelManaged rijndaelCipher = new RijndaelManaged();
        byte[] encryptedData = Convert.FromBase64String(inputText);
        PasswordDeriveBytes secretKey = new PasswordDeriveBytes(ENCRYPTION_KEY, SALT);
 
        using (ICryptoTransform decryptor = 
          rijndaelCipher.CreateDecryptor(secretKey.GetBytes(32), secretKey.GetBytes(16)))
        {
            using (MemoryStream memoryStream = new MemoryStream(encryptedData))
            {
                using (CryptoStream cryptoStream = 
                  new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
                {
                    byte[] plainText = new byte[encryptedData.Length];
                    int decryptedCount = cryptoStream.Read(plainText, 0, plainText.Length);
                    return Encoding.Unicode.GetString(plainText, 0, decryptedCount);
                }
            }
        }
    }
 
    #endregion
}

Remember to add this line to the Web.config to make this module work:

<system.web>
  <httpmodules>
          <add type="QueryStringModule" name="QueryStringModule"/>
  </httpmodules>
</system.web>

For debugging purposes, if you need to disable this feature you should clear the add tag in httpmodules in web.config.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Farhad Hazraty Eini
Software Developer رایان پایا داده محاسب
Iran (Islamic Republic Of) Iran (Islamic Republic Of)
Bachelor of computer software engineer at Urmia University of Technology,
 
Masters of computer software engineer at Shahid Beheshti University,
 
Microsoft Certified Solution Developer : Web Applications,
 
Microsoft Specialist : HTML5 , CSS3 , javascript,
 
MCTS at Mojtame Fanni Tehran (MFT)
 

My Server Solution Blog
Follow on   Google+

Comments and Discussions

 
QuestionGlobal Query String Encryption Pinmembernagapavanich5-Dec-14 1:12 
QuestionHow does it stop queryString injections? PinmemberMember 473692519-Aug-14 1:40 
AnswerRe: How does it stop queryString injections? PinprofessionalFarhad Hazraty Eini19-Aug-14 2:19 
Questionفوق العاده بود PinmemberHadi Zaker18-Aug-14 23:07 
AnswerRe: فوق العاده بود PinprofessionalFarhad Hazraty Eini19-Aug-14 2:21 
NewsOriginal Work? PinmemberWenff24-Jul-14 5:50 
Questionnot working when uploading to server Pinmemberjagdish12306125-Jun-14 0:38 
AnswerRe: not working when uploading to server PinprofessionalFarhad Hazraty Eini25-Jun-14 4:52 
Questionhow to load this project in my website Pinmemberjagdish12306124-Jun-14 1:32 
AnswerRe: how to load this project in my website PinprofessionalFarhad Hazraty Eini24-Jun-14 3:17 
QuestionBUG: Unsupported Characters Pinmemberexp_user16-Jun-14 17:15 
AnswerRe: BUG: Unsupported Characters PinprofessionalFarhad Hazraty Eini16-Jun-14 18:28 
GeneralRe: BUG: Unsupported Characters Pinmemberexp_user16-Jun-14 21:58 
GeneralRe: BUG: Unsupported Characters PinprofessionalFarhad Hazraty Eini16-Jun-14 22:52 
AnswerRe: BUG: Unsupported Characters PinprofessionalFarhad Hazraty Eini16-Jun-14 23:46 
QuestionNot yours Pinmembermichel eissa15-Apr-14 7:48 
AnswerRe: Not yours PinprofessionalFarhad Hazraty Eini15-Apr-14 8:13 
QuestionIssue with POST request Pinmembershamas imran14-Apr-14 6:32 
AnswerRe: Issue with POST request PinprofessionalFarhad Hazraty Eini15-Apr-14 1:24 
QuestionHttpModule Giving Error When Uploading To The Server Pinmemberankur dixit19-Dec-13 8:43 
AnswerRe: HttpModule Giving Error When Uploading To The Server PinmemberFarhad Hazraty Eini19-Dec-13 19:16 
GeneralMy vote of 5 Pinmembersagar viradiya9-Oct-13 4:02 
GeneralGood Job albeit some issues Pinmemberice_watch11-Sep-13 1:11 
GeneralExcellent !! PinmemberMember 36708157-Aug-13 18:19 
QuestionMissing download PinstaffSmitha Vijayan26-Apr-13 7:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.141223.1 | Last Updated 26 Apr 2013
Article Copyright 2013 by Farhad Hazraty Eini
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid