Nelle proprie applicazioni ASP.Net la querystring è un modo comodo per passare parametri tra le pagine, questo spesso però può rendere la propria applicazione poco sicura. Il problema è che spesso questa tecnica viene usata per specificare id o dati similari, ad esempio si mostra una pagina con una lista di oggetti e poi premendo un link di dettaglio si viene mandati ad esempio alla ShowDetail.aspx?id=34. Un attaccante può naturalmente provare a sostituire al valore 34 altri valori ed avere accesso magari a oggetti a lui non permessi. Solitamente la propria applicazione dovrebbe quindi fare un controllo accurato sui parametri di querystring per evitare problemi di sicurezza. Una soluzione che rende il tutto più sicuro è quella di utilizzare la UrlRewriting per criptare la querystring. Prima di tutto inserire nel proprio web.config le chiavi crittografiche da utilizzare. (In una situazione più sicura le chiavi non andrebbero nel web.config)
<add key="QueryStringEncryptionKey" value="E26AABA4745F…"/>
<add key="InitializationVector" value="C6571078191F67093117D76CFD8B9A40"/>
Ora si crea una semplice funzione a cui verrà passata la stringa rappresentante il querystring e che restituisce un nuovo querystring cifrato
public static String EncodeQueryString(String queryString) {
MemoryStream ms = new MemoryStream();
RijndaelManaged crypto = new RijndaelManaged();
ICryptoTransform ct = crypto.CreateEncryptor(
HexEncoding.GetBytes(ConfigurationManager.AppSettings["QueryStringEncryptionKey"]),
HexEncoding.GetBytes(ConfigurationManager.AppSettings["InitializationVector"]));
CryptoStream cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
Byte[] rawQueryString = Encoding.ASCII.GetBytes(queryString);
cs.Write(rawQueryString, 0, rawQueryString.Length);
cs.Close();
return "ck=" + HttpContext.Current.Server.UrlEncode(Convert.ToBase64String(ms.ToArray()));
}
La cifratura scelta è la AES, la chiave e l'initialization vector sono tenuti nel web.config, la funzione di cifratura è standard e l'unica particolarità è la classe HexEncoding che ho preso dal libro "Developing more secure asp.net 2.0" che converte da una rappresentazione esadecimale stringa ad un array di byte, ma la sua implementazione è veramente banale. A questo punto si fa un HttpModule che elabora la BeginRequest e che automaticamente controlla se nella querystring è presente la chiave ck indice del fatto che è stata passata una querystring cifrata
public void Application_BeginRequest(object sender, System.EventArgs args) {
if (HttpContext.Current.Request.QueryString["ck"] != null) {
String criptedQueryString = HttpContext.Current.Request.QueryString["ck"];
Byte[] rawQueryString = Convert.FromBase64String(criptedQueryString);
MemoryStream ms = new MemoryStream();
RijndaelManaged crypto = new RijndaelManaged();
ICryptoTransform ct = crypto.CreateDecryptor(
HexEncoding.GetBytes(ConfigurationManager.AppSettings["QueryStringEncryptionKey"]),
HexEncoding.GetBytes(ConfigurationManager.AppSettings["InitializationVector"]));
CryptoStream cs = new CryptoStream(ms, ct, CryptoStreamMode.Write);
cs.Write(rawQueryString, 0, rawQueryString.Length);
cs.Close();
String decryptedQueryString = Encoding.ASCII.GetString(ms.ToArray());
HttpContext.Current.RewritePath(HttpContext.Current.Request.Path + "?" + decryptedQueryString);
}
}
Grazie al metodo RewritePath della httpcontext è possibile modificare il path della richiesta in modo che le pagine non si accorgano nemmeno della cifratura della querystring, ecco infatti una pagina in azione.
protected void Page_Load(object sender, EventArgs e) {
foreach(String key in Request.QueryString.AllKeys) {
Response.Write(key + "=" + Request.QueryString[key] + "<BR />");
}
}
protected override void OnPreRender(EventArgs e) {
String querystring = "a=pippo&b=pluto";
HyperLink1.NavigateUrl = "/SecureQueryString.aspx?" + QueryStringSecure.EncodeQueryString(querystring);
base.OnPreRender(e);
}
Come si può vedere nell'OnPreRender si crea un link per un oggetto hyperlink, notate come la querystring sia prima preparata e poi cifrata dal metodo Statico EncodeQueryString del mio modulo. Il link cosi generato è: http://localhost:49998/SecureQueryString.aspx?ck=3TOZStpI8jIkeoCOEjfoVQ%3d%3d e come potete vedere è ora impossibile per il chiamante giocherellare con i parametri di querystring per cercare di trovare qualche falla nella vostra applicazione anche perché se non si è in possesso delle chiavi crittografiche giuste non si può manipolare in nessun modo la querystring. Nel load viene invece effettuato un dump dei parametri che si trovano nella querystring per verificare che effettivamente i dati ricevuti siano quelli attesi.
Naturalmente non dimenticate di proteggere le chiavi del web.config con aspnet_regiis o con aspnet_setreg.
Alk.