jueves, 12 de enero de 2012

Crackeando un Hash Cracker (III): SQLi con MD5

Contribución de Julio Gómez: Continuamos el post de ayer y acabamos la serie sobre como se puede crackear un hash cracker:

También veo que almacenan todas las contraseñas que la aplicación rompe en una base de datos... ¿Inyección de SQL? La sentencia que utilizan es similar a la siguiente:

mysql_query ("INSERT INTO table (timestamp, hash, algorithm, pass) VALUES ('".time()."', '".$hash."', '".$algorithm."', '".$pass."')");

Como la inserción sólo se ejecuta si se recupera la contraseña, el hash y el algoritmo de cifrado tienen que haber sido correctos para poder ejecutar findmyhash por debajo. Así que sólo podemos probar a inyectar en el campo 'password'.

Utilizando el mismo método que con el Cross Site Scripting, pruebo primero con una inyección sencilla:
  1. calculo el hash de la cadena a inyectar. En este caso utilizo "password')#a" (sin las comillas): 380af891ac68ababff4d96cb2d242c06
  2. pruebo a introducir el hash para ver si lo rompe la aplicación (que lo hace, ya que lo he calculado en uno de los servicios que utiliza).
  3. accedo a la base de datos para que ver si ha añadido la cadena completa ("password')#a") o tan sólo la palabra "password", que era el objetivo. Y compruebo que la inyección ha funcionado, almacenando una password errónea:

Lo siguiente que se me ocurre es probar a insertar varios registros de una sola vez con una inyección como la siguiente:

fake1'),('1325005093','380af891ac68ababff4d96cb2d242c06','md5','fake2'),('1325005093','380af891ac68ababff4d96cb2d242c06','md5','fake3'),('1325005093','380af891ac68ababff4d96cb2d242c06','md5','fake4

cuyo hash es:

2751527becb471df139eb066442bef74

Si vuelvo a acceder a la base de datos puedo comprobar que se han añadido cuatro filas nuevas con tan sólo una consulta:


Nota Jose Selvi: Ciertamente, teniendo un acceso shell, quizá explotar una SQLi carezca de sentido, puesto que podríamos subir una webshell que accediera a la base de datos y la modificara de la forma que queramos, pero aún así Julio lo ha hecho para demostrar la existencia de la vulnerabilidad.

Como hemos visto, aunque la aplicación valida las entradas del usuario para tratar de evitar los Cross Site Scripting, hay otros vectores de inyección que no se han tenido en cuenta a la hora de implementarla.

En general, todos los datos de entrada de una aplicación, provengan de donde provengan (entradas de usuario, bases de datos, ficheros de configuración, salida de otras aplicaciones...), deben validarse de la manera más restrictiva posible y no hay que confiar en que el origen de los datos sea "confiable", porque como acabamos de ver, no siempre es realmente confiable todo lo que lo parece.
    Espero que esta entrada haya servido para echarle un poco de imaginación a la hora de descubrir posibles vectores de inyección y para comprobar que todas las aplicaciones son susceptibles de tener alguna vulnerabilidad (hemos explotado tres vulnerabilidades diferentes a través del mismo parámetro).

    miércoles, 11 de enero de 2012

    Crackeando un Hash Cracker (II): CMDi

    Contribución de Julio Gómez: Continuamos el post de antes de ayer sobre como se puede crackear un hash cracker:

    Después de haber utilizado la aplicación varias veces, vemos que los mensajes que devuelve en la salida son exactamente iguales a los de la herramienta que os comentaba al comienzo de la entrada. Además de que si consultamos la sección "What's this site?" dice específicamente que el sitio está basado en findmyhash.

    Sabiendo que findmyhash es un script en Python que se llama desde la línea de comandos y que la aplicación web está implementada en PHP, podría ser que el sitio estuviera realizando alguna llamada al sistema de la forma:

    exec ("python findmyhash.py " . $_POST['encrypt-method'] . " -h " . $_POST['hash']);

    Sabiendo que el servidor que utiliza es un Apache sobre Debian (se puede ver en la cabecera Server de la respuesta HTTP), se me ocurre probar una inyección de comandos en Linux. Algo parecido a "; ls":


    La salida aparece estar acotada a un espacio demasiado limitado para poder hacer un 'cat' de algún fichero o utilizar cualquier otro comando cuya salida sea de más de unas pocas líneas. Sería genial si tuvieran instalado el netcat para ponerlo a escuchar en algún puerto y tener una shell...

    ; nc -v -l -p 22022 -e /bin/sh


    Si no lo hubiera tenido hubiéramos podido hacer otras cosas, pero en este caso ha sido mucho más fácil de lo que esperábamos, con el netcat instalado, todos los puertos abiertos, etc.

    Una vez dentro, le podemos pegar un vistazo al código de la aplicación y confirmar que codifican los parámetros de entrada con la función de PHP 'htmlentities' para tratar de prevenir los Cross Site Scripting, pero por desgracia para el desarrollador, no solo existen los XSS.

    Nota Jose Selvi: Como nota curiosa, cuando estuvimos pegándole un vistazo a la aplicación a ver lo que hacía, vimos que guardaba en una base de datos local cada hash que se le introducía y contraseña exitosa calculada. En este caso no guardaba ninguna información más, pero podría estar guardando la IP de origen, con lo cual estaríamos proporcionando a un desconocido las llaves de nuestra casa, y además le habríamos puesto la etiqueta con la dirección. Es necesario tener mucho cuidado cuando se usan servicios públicos de crackeo de contraseñas, ya que si se crackea con éxito, no sabemos que va a pasar con esa contraseña.

    ¿Hemos dicho que la aplicación almacena en base de datos? Quizá podríamos explotar una Inyección SQL... En el próximo post.

    lunes, 9 de enero de 2012

    Crackeando un Hash Cracker (I): XSS con MD5

    Contribución de Julio Gómez: Empezamos el año con una contribución de Julio Gómez, compañero mio en el departamento de auditoría de S21sec y redactor del blog "La X Marca el Lugar" junto con otros compañeros. En su colaboración, va a destripar una de estas webs que ofrecen la posibilidad de introducirles un hash y que te devuelven su contraseña, que como veremos sufre algunos problemillas de seguridad, algo que no deja de ser gracioso teniendo en cuenta su función:

    Cada vez es más habitual que la seguridad sea una característica a tener en cuenta durante los desarrollos de cualquier tipo de software. Dentro del ámbito de las aplicaciones web, es muy frecuente que los desarrolladores estén familiarizados con los términos Cross Site Scripting o Inyección de Código SQL. El problema es que, en muchos casos, no terminan de comprender del todo los diferentes tipos de vulnerabilidades y se conforman con seguir algún manual de buenas prácticas.

    Éste es el caso de una aplicación web que recientemente me he encontrado en Internet y con la que no tengo nada que ver aunque haya gente que piense que está relacionada con una herramienta (findmyhash) que publiqué durante 2011.

    La aplicación es un muy simple. Tan sólo tiene un formulario en el que se puede introducir un hash de cualquiera de los tipos soportados. Tras hacerlo, la aplicación parece que busca en varios servicios públicos de Internet el hash para tratar de recuperar el valor de la cadena que genera dicho hash.


    Jugando un poco con la aplicación, intentando probar si es vulnerable a Cross Site Scripting, se puede comprobar que parece que filtra correctamente las entradas.

    Cuando por mi profesión tengo que recomendar cómo prevenir los Cross Site Scripting en una aplicación web, siempre recomiendo que por un lado se validen todas las entradas de la aplicación y que, además, los valores dinámicos que se generen sean codificados utilizando HTML entities.

    En la práctica, la realidad es que tan sólo se suelen validar las entradas que provengan directamente del usuario y no en todos los casos los desarrolladores se acuerdan de codificar las salidas. En el caso de esta aplicación en cuestión, las entradas de usuario están convenientemente validadas y codificadas, pero ¿y las salidas?

    Partiendo de la base de que "no sabemos" (luego veremos que sí) cómo funciona la aplicación a nivel interno. Si seguimos trasteando vemos que nos devuelve si ha sido o no capaz de romper el hash y, de hacerlo, nos indica la cadena original que genera dicho hash.

    No sé si ya habréis intuido por dónde voy... Las entradas se validan correctamente, pero ¿y si introducimos un hash que se corresponda con alguna cadena HTML? ¿Estarán codificando también la salida de la aplicación?

    Si probamos a introducir hashes correspondientes a cadenas de inyección típicas (<script>alert("XSS")</script>) vemos que directamente la aplicación no es capaz de romperlas. Que por otro lado tiene sentido porque este tipo de aplicaciones suelen utilizarse para romper contraseñas y ¿quién utiliza como contraseña un vector de inyección para XSS? (que por otro lado sería una contraseña bastante buena...)

    No obstante, como en la respuesta de la aplicación nos muestra algunos de los servicios que utiliza, al cabo de un rato de investigar encontramos uno que nos permite no sólo romper un hash, sino calcular uno nuevo a partir de una cadena. De este modo, se queda almacenada en su base de datos la cadena original y el hash asociado.


    Para el ejemplo, he utilizado la cadena:
    <iframe src="http://www.bing.com" style="position:absolute;z-index:200;display:inline;"></iframe>
    cuyo MD5 es:
    e8de8366340de0d9bda9858e97b42573
    Si ahora probamos a introducir este MD5 en el buscador... ¡Bingo! La aplicación no codifica las salidas correctamente. Tenemos un Cross Site Scripting en toda regla, aunque algo rebuscado y de poca utilidad en un caso real.


    Ahora que hemos conseguido realizar un XSS de esta forma un tanto alternativa, podemos irnos a probar otro tipo de vulnerabilidades en la página. Pero eso en el post de mañana.