Sunday, April 03, 2011

ASP.NET: Obfuscating the Querystring

Some time ago I answered somebody's post on the MS C# newsgroup. This person was trying to "pass a connection" to another ASP.NET application from a redirect or a link and couldn't figure out how to do it. Of course, you wouldn't be able to pass the connection object itself (nor should you even try) but you could put the connection string to create it on the QueryString, grab it back out in the Page_Load event of the receiving page, and then simply re-create the same connection.

That was the essence of my suggestion - put the connection string on the QueryString. 
Shortly thereafter Steve Orr, whose work I respect, responded that putting a connection string on the querystring posed a substantial security risk, which is correct. So what I'm about to offer here is a nice, compact way to encapsulate the QueryString in ASP.NET as an object that makes it much easier to manipulate, along with some nice code that will perform ASCII-to-HEX scrambling on both the names -- and the values -- of everything on the querystring. Actually you probably could never get an unencrypted connection string on the querystring anyway, it contains illegal "=" characters, so you'd have no choice but to mangle it in some way. (Similarly, we cannot use Base64 encoding since a Base64 encoded string ends with one or two equals signs.)

This is not "encryption" - it's only scrambling or "obfuscation" - which is typically all you need to keep your "stuff" away from prying eyes. If you truly need strong encryption, my suggestion is -- don't use the querystring at all; find another way. Of course, you can add to this, for example doing TRIPLE-DES encryption before performing the ASCI-To-HEX, and the reverse for decrypting, if you wanted to do "overkill". But the bottom line is, it's best not to put sensitive data on the querystring at all -- there are other ways to pass the data. 
First, I make use of Bobby DeRosa's QueryString class which is shown here virtually unchanged from his original post:

using System.Collections.Specialized ;
using System.Collections;
using System.Web;
using System;
namespace PAB.Utils
{
   // from Bobby DeRosa : 
   // querystring_class_useful_for_querystring_manipulation__appendage__etc.aspx
    public class QueryString : NameValueCollection
    {
         private string document;
        public string Document
        {
             get
             {
                  return document;
             }
        }
        public QueryString()
        {
         }
         public QueryString(NameValueCollection clone) : base(clone)
        {
         }
         public static QueryString FromCurrent()
        {
            return FromUrl(HttpContext.Current.Request.Url.AbsoluteUri);    
         }
         public static QueryString FromUrl(string url)
        {
            string[] parts = url.Split("?".ToCharArray());
            QueryString qs = new QueryString();
            qs.document = parts[0];
             if(parts.Length == 1)
                 return qs;
            string[] keys = parts[1].Split("&".ToCharArray());
            foreach(string key in keys)
            {
                string[] part = key.Split("=".ToCharArray());
                 if(part.Length == 1)
                     qs.Add(part[0], "");
                 qs.Add(part[0], part[1]);
             }
             return qs;
        }
         public void ClearAllExcept(string except)
        {
            ClearAllExcept(new string[] { except });
        }
        public void ClearAllExcept(string[] except)
        {
            ArrayList toRemove = new ArrayList();
            foreach(string s in this.AllKeys)
            {
                foreach(string e in except)
                 {
                     if(s.ToLower() == e.ToLower())
                          if(!toRemove.Contains(s))
                              toRemove.Add(s);
                }
            }

Read more: eggheadcafe