Encriptado de nuestros QueryString con ASP.NET (Fácilmente)

Hola que tal, no vamos a entrar en detalles en los temas de seguridad que pueden verse afectados al enviar parámetros desde una página a otra mediante  el método GET. En donde podríamos tener:

http://www.misitio.com?idtran=12322&tipo=2&usuario=jsoto&priori=5

Obviamente podemos caer en problemas de seguridad al revelar información sensible en las url.

Componente TSHAK  (Descargar este Componente)

Existe un componente muy interesante que hace el trabajo de encriptar las querystring de manera sencilla, solo necesitamos hacer referencia a la DLL descargada y  un arreglo de bits. Veamos el código de la página “llamadora”

Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click

 Dim querystringSeguro As TSHAK.Components.SecureQueryString
querystringSeguro = New TSHAK.Components.SecureQueryString(New Byte() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 8})
‘URL Original del ejemplo
‘http://www.misitio.com?idtran=12322&tipo=2&usuario=jsoto&priori=5
querystringSeguro("idtran") = 12322
querystringSeguro("tipo") = 2
querystringSeguro("usuario") = "jsoto"
querystringSeguro("priori") = 5
Response.Redirect("pagina2.aspx?data=" + HttpUtility.UrlEncode(querystringSeguro.ToString()))

 End Sub

Y en la página “llamada” ponemos el código (disculpen el poco orden del código, pero el formato del blog no ayuda mucho):

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

Dim querystringSeguro As TSHAK.Components.SecureQueryString        ‘instanciamos el objeto y le pasamos como argumento el mismo array de bits mas el parámetro data, que viene de la llamada de la pagina default.aspx que contiene todo el queryString

querystringSeguro = New TSHAK.Components.SecureQueryString(New Byte() {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 8}, Request("data"))

Try
‘Obtenemos las variables que vienen dentro del querystringSeguro
Dim idtran As Integer = Integer.Parse(querystringSeguro("idtran"))
Dim tipo As Integer = Integer.Parse(querystringSeguro("tipo"))
Dim usuario As String = querystringSeguro("usuario").ToString
Dim priori As Integer = Integer.Parse(querystringSeguro("priori"))
lb_msg.Text = "idtran=" & idtran & " tipo=" & tipo & " usuario=" & usuario & " priori=" & priori

Catch ex As Exception
            lb_msg.Text = "ERROR EN RECEPCIÓN DE PARAMETROS"
       End Try
End Sub

El resultado final , gráficamente:

image

y la URL:

http://localhost:51254/querystring/pagina2.aspx?data=EAMsAeJK2BQ7JJuvxHz8rEOhJSo909WAFzClxAqn50JFC%2fsWLt6niWoQBDib2tdOXsXCgnDY5%2f%2bR13ZjQq2c333aXy6%2bQFq%2fu2XRJQMUPONg2VUg3az9KzOIGQVH2imTslJTmyvFwy6N0t7JoSaJIsvdQ2l%2bb5FN07ZtsfcvfMnTEUfz0%2fLAuon0Jvk1%2beoeucumgEQ5h1wYEXtlT%2fBoQfPR2ah8ojFGGPu3RR1mnqExNKh8HbFRYbGId0c15grKbw%3d%3d

Es un poco más complicado leer esto y adivinar los parámetros!
Espero que les sirva,
Saludos,

-Gonzalo

23 comentarios en “Encriptado de nuestros QueryString con ASP.NET (Fácilmente)”

  1. Es interesantísimo el hacer notar que puedes realizar una pequeña encriptación en los parámetros que se le pasan al URL. Creo que todos alguna vez hemos visto una URL y hemos estado jugueteando con los parámetros para modificar el comportamiento de la página Web, así que en determinadas ocasiones es importante el realizar este procedimiento de cifrado.

    De todas formas, la plataforma .NET tiene casi todas las formas de cifrado conocidas para que haya que buscar un componente externo que te realize ese cifrado.

    Dentro de System.Security.Cryptography tienes cifrados DES, Triple DES, AES, RC2 y Rijndael sin tener que salir “fuera de casa”.

    A mi nunca me ha gustado el usar componentes externos en VB y pienso que es una práctica generalizada arrastrada de los VB 4, 5 y 6. En este caso, añadir un componente externo no aporta mucho (salvo la facilidad de usar y listo). Pero no es mucho más difícil tirarse a la MSDN y sacar la misma funcionalidad con clases .NET nativas. Es más, en temas tan sensibles como el cifrado es mejor saber lo que estás haciendo (es decir, qué características tiene el algoritmo que estás usando para saber la fortaleza del mismo) que usar otro componente que no sabes qué tipo de cifrado usa.

    Evidentemente, tampoco se trata de usar el sistema criptográfico del pentágono, pero tampoco cuesta tanto.

    Si te parece interesante esto, me comprometo a ponerte un código de ejemplo de cómo cifrar URLs con las clases de cifrado nativas .NET y si lo ves interesante, te propongo otro artículo:

    Con el cifrado ocultamos la información que pasamos y también nos “casi” aseguramos que la información que se ha pasado es válida. Pero por otra parte también te dificultas a tí mismo el poder depurar tu aplicación. Si hay problemas, en el log del IIS lo único que verás serán cadenas de datos sin sentido y no sabrás muy bien qué es lo que ha pasado.

    Si no nos interesa tanto el ocultar información como el verificar que los datos pasados son los que deberían ser (es decir, que no hay nadie detrás modificando parámetros para “jugar” con la aplicación, o para provocar algún SLQ inyection o algún otro tipo de desbordamiento).

    Por eso habría otra forma de “asegurar” tus URLs, que es con un algoritmo de hash. En los hashs, lo que generas es un resumen de un conjunto de datos. Cambiando un único byte de la cadena de entrada, el resumen hash cambia dramáticamente. Lo que habría que hacer sería hacer un hash de los parámetros que se le pasan. Es decir, tienes los parámetros y un número que es el resumen de los parámetros que se han pasado.

    Tu URL sería http://www.misitio.com?param1=a&param2=b&param3=c&hash=xxxxxxxxxxxxx

    Cada vez que recibas la petición, coges los parámetros, calculas el hash y lo compraras con el hash pasado en la URL. Si alguien cambiase un único byte de los parámetros de entrada, el hash cambiaría y por tanto sabrías que los parámetros que te han pasado han sido alterados.

    Los algoritmos de hash más usados son MD5 (del cual hay que olvidarse porque ya está considerado como inseguro) y la familia de los SHA (SHA-1 (el cual en 1 año seguramente ya se considere como inseguro), SHA256, SHA512, …).

    Evidentemente, el que conociese tu algoritmo podría recrear tu URL. Es decir, puedo modificar los parámetros, calcular el HASH de los mismos y directamente invocar la misma URL con los parámetros y el hash cambiados.

    Pero para eso lo que se suele hacer es cifrar el hash. De esta forma, aunque sepan qué tipo de algoritmo estoy usando para el cálculo del hash, éste no puede ser recreado porque no saben qué tipo de cifrado estoy aplicando (y aunque lo supiesen, no sabrían qué clave de cifrado estoy usando).

    Con esto incluso podría pasar parámetros entre servidores. Es decir, imagina que tengo una aplicación en un servidor y otra en otro. Yo me autentico en el servidor A, con lo que mi sesión está en A, pero quiero en un momento dado procesar algo en el servidor B. Pero no quiero que ese proceso sea lanzado más que por el proceso legítimo de A. Con este sistema podría hacerlo y de esta forma cuando se invocase el proceso en B, éste sabría que puede confiar en que ese proceso viene de A puesto que es el único que ha sido capaz de generar una URL confiable.

    Como ves, el tema da para mucho. Si aceptas colaboraciones para echarte una mano en esto, aquí tienes la mía.

  2. Hola José!
    Muy buenos alcances!!, y concuerdo contigo en el tema de que componentes externos en temas de seguridad pudiesen ser inseguros, pero no estoy de acuerdo cuando generalisas diciendo que componentes externos no ayudan en nada (diles eso a Telerik o a Dundas!)

    Sobre él código nativo de encriptación tambien lo conozco, obviamente hay más de una forma, pero acá mostramos una manera muuuy sencilla. Pero por favor! esto no significa que no postees tu código acá por que será muy bien recibido y lo esperamos!

    Te parece abrir un thread en donde conversemos sobre este interesante tema,se ve que te manejas bastante en esto y sin duda tus aportes serán muy importantes.

    Saludos!!!

  3. Yo hace tiempo escribi un articulo en Solo Programadores sobre un componente que añadido a nuestro sitio web se encargaba de hacer esto automaticamente.

    La idea era muy sencilla, os pego aqui parte del articulo:


    Vamos a construir un módulo http que se encargará de analizar todas las peticiones de páginas .aspx y .ashx. En caso de que la petición incluya parámetros en la url el módulo analizará dichos parámetros. Si los parámetros no están encriptados, o si lo están pero han sido alterados, el módulo elevará una excepción. En caso de que se cumplan todas las medidas de seguridad, el módulo se encargará de convertir la cadena encriptada en texto claro. Así para nuestro código la encriptación será como si no hubiese existido.
    Además de esto, el módulo también se encargará de encriptar todas las cookies antes de que estas lleguen al cliente. Cuando las cookies vuelvan al servidor el módulo las analizará, elevando una excepción en caso de que detecte alteraciones o cookies que no hayan sido encriptadas. Si las cookies no han sido alteradas serán desencriptadas automáticamente, para que no nos tengamos que preocupar de nada (logrando de nuevo total transparencia en este aspecto).
    Para llevar a cabo todo esto nuestro módulo se apoyará en el uso de httpmodules, filtros html y expresiones regulares. También hará uso de secciones de configuración personalizadas en el web.config, que nos permitirán variar el comportamiento del módulo en tiempo de ejecución.

    Voy a ver si consigo un blog aqui en geeks.ms para poner los articulos, puesto que ya ha pasado tiempo suficiente como para poderlos publicar sin problemas legales.

  4. vaya! este post y los comentarios son recientes!
    …y yo que andaba buscando lo que propone Jose Merino, porque me han pedido usar clases nativas de .net.

  5. Efectivamente, creo que los componentes son útiles. Pero siempre me lo pienso 2 veces antes de meter cualquier componente y hay que saber elegir muy bien.

    El meter un componente externo implica una dependencia. Es decir, librerías de las que hay que hacer un “deploy” en producción. Algunas veces sólo es copiar la DLL correspondiente y listo, pero otras veces es instalar la librería en su versión correspondiente (si en desarrollo decides actualizar la librería te encuentras con que al subir a producción tienes un “pequeño problema”). E incluso otras veces tienes que hacer “encaje de bolillos” (por ejemplo con Crystal Reports).

    Evidentemente, para el caso del Crystal Reports, no te quedan muchas más alternativas. Mi opinión con respecto a los componentes es que hay que pensar un poco antes de usarlos indiscriminadamente y preguntarse: ¿Puedo sustituir fácilmente su funcionalidad con código fuente propio? ¿Qué tipo de dependencias me generan en el proyecto y en el servidor de producción? ¿Existe algún otro componente en el mercado con funcionalidad similar que tenga menos dependencias o que sea más robusto?

    Lo que yo criticaba (y lo que no me gusta) es que se suele usar controles externos en VB con demasiada ligereza a veces. Lo cual es heredado de lo que se solía hacer en VB 4, 5 y 6, pues en VB.NET se puede hacer casi de todo con código de forma muy simple.

    Con respecto a lo del hilo para conversar sobre seguridad por mi estupendo. Como tu dices estoy metido hasta las orejas en temas de seguridad y escalabidad. Así que también podríamos tratar temas esos temas. De hecho considero que es uno de los más grandes handicaps de un desarrollador/arquitecto. Ya no sólo hay que hacer aplicaciones bien, sino seguras y escalables.

    El equipo de desarrollo tiene unos sistemas y se encarga de desarrollar una serie de funcionalidades y entregarla en tiempo y forma. Y luego viene el encargado de los sistemas que se encuentra con una “caja negra” que tiene que evitar que eso se caiga y que encima esté a salvo de posibles ataques.

    A pesar que ya han publicado respuestas sobre el temas del cifrado de las URLs, mi disposición a echar una mano es firme, así que sólo tienes que decirme cómo y qué considerarías que es más interesante.

  6. En efecto, un componente DLL tiene la ventaja de dar una funcionalidad facilmente, pero a cambio dependes de cómo se haya hecho el componente y sus agujeros de seguridad y esto no lo sabes.

    Creo, como en muchos comentarios, que es mejor utilizar componentes y llamadas a librerías nativas en los que tenemos la seguridad de saber qué hacen y sus limitaciones.

    Además es mejor que el manejador sea puesto dentro del web.config o global.asax debido a que es una forma de encapsular las encriptaciones y ,si hubiese de modificar algo grave, tendría sólo que modificarse allí y no cada vez que se llama a una página y se recuperan los datos y también habría posibilidad de ponerlo/quitarlo en un momento.

    De todas formas, este tema es muy interesante para el desarrollo web y de ocultar los datos que pueden ser críticos, desencadenar errores o mostrar elementos del usuario que no deberían mostrarse (dni, fechas, datos bancarios, datos medicos, etc).

  7. Hola…
    (esto parece mas un foro que comentarios :)…

    No todo es adminitrado por el FW .NET en System.Security.Cryptography
    Con respecto a componentes nativos .NET de criptografia? si bien el framework nos da la potencia de utilizarlos mediante clases, el unico que es un “componente administrado” es el AES o Rijndael, todos los damas lo tenemos gracias a componentes “externos” (que viene en el framework pero que no estan embebdiso en algoritmo dentro del sino separados) que FW NET hace de wrapper (nunca supe porque era asi, creeria que por licencias)

    Siguiendo con esto…
    Un ejemplo no tan sencillo es utilizar Rijndael, y crear el vector IV o no me acuerdo que cosas mas con el Salto etc etc (como el ejemplo que nos deja @skar)… gracias a componentes “externos” como: The Cryptography Application Block
    http://msdn.microsoft.com/en-us/library/cc511721.aspx
    Que simplemente hacen uso “mas facil” para nosotros de las clases que nos proporciona .NET

    Asi que cuando podamos utilizarlo mucho mejor, es mi opinion. Ya que es un componente que nos brinda buena y mejores practivas…
    NOTA: Acaso .NET no se asemeja a un componente externo (sabemos que es mas que eso)a nuetra app que nos ayuda, y mas aun en nuevas versions que vemos que las tareas se van reduciendo en lineas de codigo 😉 (no quiero debatir sobre esto solamente lo dejo para pensar)… acaso se vendra un Sistema Operativo .NET? 🙂

    Finalmente…
    Algo que nos comenta @José Ignacio Merino lo tenia en este enlace
    – Módulo HTTP para encriptar automáticamente los query strings.
    http://www.mvps.org/emorcillo/es/codigo/aspnet/qse.shtml
    @Jose cuando quieras postearlo por aqui o en cualquier blog que puedas crearte pon aqui el enlace, seguro que “tu componente externo” (va en broma) que nos ayude a estas tareas de encriptacion de querystring nos seran de ayuda, y si es transparente mucho mejor

    Algunos enlaces que los tenia tageados con este tema
    – Securing Query Strings with SecureQueryString 2.0
    http://www.dotnetjunkies.com/Article/3ABCD244-CC7C-4CED-B64E-BCF05191CDAB.dcik
    – ASP.NET: Obfuscating the Querystring
    http://www.eggheadcafe.com/articles/20060427.asp
    – Secure Query Strings: Preventing the Tampering of Data Passed between Applications
    http://www.dotnetjunkies.com/how%20to/99201486-ACFD-4607-A0CC-99E75836DC72.dcik

  8. Actualmente estoy utilizando este dll en el desarrollo de un proyecto y funciona de maravilla.

    Considero que el uso de un componente externo como ahorra programación y además se puede confiar en este en particular ya que nos permite definir los bytes que van a realizar la encriptación por lo que no hay problemas de seguridad, por lo que lo recomiendo.

  9. Esto funciona muy bien cuando la pagina al que se direcciona esta en el mismo proyecto web. Pero yo tengo una pagina que me lleva a otra pagina web. solo con un Response.redirec(“OTRA PAGINA”) y con esto no me resulta.
    usa una sesion o algo parecido?

    este es mi correo : clip_120@hotmail.com

  10. Tuve un problema similar y me parece que la manera mas comoda, sencilla, rapida y de facil implantacion para encriptar querystring es crear para los ID a encriptar(en SqlServer) en la tabla un columna con un campo de tipo GUID, y en los querystring utilizar el valor de esa columna.

  11. José I. Merino me gustaria que me ayudaras a hacer lo que comentas arriba. la encriptacion con .net sin componentes de 3ros.

    de igual forma. el ejemplo sta perfecto. no tengo nada en contra de los componenctes externs a .net

    saludos!!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *