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
NGINX-ngx_http_rewrite_module-heap-buffer-overflow-CVE-2026-9256 | Kitploit
Outils/GitHubGitHub/w5m1n9/nginx-ngx_http_rewrite_module-heap-buffer-overflow-cve-2026-9256
Analyse des VulnérabilitésExploitationSécurité WebFuzzingTests d'Intrusion
GitHubw5m1n9/nginx-ngx_http_rewrite_module-heap-buffer-overflow-cve-2026-9256

NGINX-ngx_http_rewrite_module-heap-buffer-overflow-CVE-2026-9256

Voir le dépôt

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
2il y a 2 moisPas encore vérifié

CVE-2026-9256 NGINX ngx_http_rewrite_module : dérivation du PoC et réflexions

Champ d'application : à utiliser uniquement sur des environnements de test locaux, des environnements de reproduction autorisés, pour la validation de vulnérabilités et l'analyse de règles de protection. Ne pas utiliser sur des cibles non autorisées. Le principe du PoC présenté dans ce document ne valide que le comportement de crash du worker NGINX observable à distance ; il n'inclut pas de RCE, de contournement d'ASLR ni de chaîne d'exploitation stable.

1. Contexte de la vulnérabilité

CVE-2026-9256 est une vulnérabilité de débordement de tas (heap buffer overflow) dans ngx_http_rewrite_module de NGINX. Le déclenchement de la vulnérabilité ne consiste pas simplement à accéder à un URI fixe, mais dépend d'un modèle de configuration rewrite spécifique : la regex de rewrite contient des groupes de capture PCRE se chevauchant, et la partie replacement référence plusieurs variables de capture, par exemple $1, $2.

Lorsqu'un attaquant construit un URI spécial qui fait entrer la logique de rewrite dans le chemin concerné, NGINX peut présenter une incohérence entre le calcul de longueur et l'écriture effective lors du traitement du contenu capturé, de la concaténation du résultat de rewrite ou de l'échappement URI/paramètres, ce qui finit par provoquer une corruption de la mémoire tas du processus worker.

Par conséquent, le point clé de cette vulnérabilité n'est pas le chemin /api en lui-même, mais l'existence ou non, dans la configuration NGINX cible, de règles rewrite vulnérables pouvant être atteintes par une requête. Le /api utilisé par défaut dans le PoC n'est qu'un chemin d'exemple de l'environnement de reproduction actuel ; lors des tests réels, le chemin de requête doit être ajusté en fonction des règles rewrite de la configuration NGINX qui contiennent des groupes de capture se chevauchant et référencent plusieurs variables de capture.

L'objectif du PoC actuel est de valider le comportement de crash du worker / déni de service. Il ne tente pas de construire un agencement précis du tas, ne tente pas d'écraser l'adresse de retour ou des pointeurs de fonction, et ne prouve pas l'exécution de code à distance. Les preuves stables observables côté distant sont principalement : la connexion de la requête de déclenchement est interrompue anormalement, puis le service NGINX reprend ses réponses, et les connexions keep-alive sont coupées par le crash du worker après le déclenchement.

2. Pourquoi ne pas se fier uniquement à un code de statut HTTP ?

Après le déclenchement de cette vulnérabilité, le résultat ne se manifeste pas nécessairement par un code de statut HTTP fixe 500, 502 ou 400. La raison est que le modèle master-worker de NGINX fait que, lorsqu'un processus worker plante, le master relance un nouveau worker. Le phénomène observé côté distant par l'attaquant n'est généralement pas une indisponibilité totale du service, mais plutôt une connexion soudainement interrompue, un dépassement de délai de lecture, une connexion réinitialisée, puis un nouvel accès à / qui renvoie une réponse normale.

Par conséquent, le PoC ne peut pas déterminer l'existence de la vulnérabilité uniquement à partir du code de statut HTTP d'une seule requête. Si l'on envoie une seule fois un URI long, que l'on voit la connexion s'interrompre et que l'on conclut directement « vulnérabilité présente », le risque de faux positif est élevé. Une interruption de connexion peut également provenir d'une instabilité réseau, d'un dépassement de délai du proxy, d'une requête bloquée par un équipement intermédiaire, d'une limitation de débit côté backend ou d'une fermeture proactive de la connexion par le serveur.

Par conséquent, le PoC doit être conçu comme une validation en plusieurs étapes :

  1. Confirmer d'abord que la cible est active.
  2. Confirmer ensuite que le chemin rewrite d'exemple peut être effectif.
  3. Envoyer la requête de déclenchement du débordement et observer si la connexion est interrompue anormalement ou expire.
  4. Envoyer immédiatement une requête normale pour confirmer que NGINX a repris ses réponses.
  5. Vérifier de manière répétée, via keep-alive, si la connexion worker tombe de façon stable après le déclenchement.

Ce n'est que lorsque « connexion de déclenchement anormale + reprise du service ensuite + plusieurs interruptions keep-alive » apparaissent simultanément que l'on peut conclure de manière plus fiable à l'existence d'un comportement de crash du worker de type CVE-2026-9256.

3. Principe de construction du PoC

Le chemin de déclenchement central du PoC actuel est :

root@kitploit:~
GET /api/++++++++++++++++++++++++++++++++... HTTP/1.1
Host: 127.0.0.1:19321

/api/ est la route d'exemple utilisée dans l'environnement de test actuel pour atteindre la règle rewrite ; un grand nombre de caractères + y est concaténé. Le nombre par défaut est de 4096.

Le choix de + repose principalement sur trois raisons.

Premièrement, + est un caractère URI valide ; lorsqu'il est envoyé via un client HTTP ordinaire, il n'est généralement pas tronqué ou réécrit de force comme le seraient des caractères tels que l'espace ou #. Par conséquent, le PoC actuel n'a pas besoin, contrairement à certaines vulnérabilités de contournement du request-target, d'utiliser un raw socket pour construire une ligne de requête invalide.

Deuxièmement, une longue répétition de caractères permet aux groupes de capture de rewrite d'obtenir une entrée suffisamment longue, ce qui amplifie la taille de sortie de la concaténation ou du traitement d'échappement du replacement ultérieur, rendant ainsi plus facile le déclenchement d'une incohérence entre le calcul de longueur et l'écriture effective.

Troisièmement, la structure du payload constitué de + répétés est simple, ce qui facilite son observation dans les captures de paquets, les journaux et les règles IDS, et permet aussi d'ajuster la longueur pour effectuer des tests de seuil.

Il faut toutefois noter que + n'est pas le seul caractère de déclenchement théorique de la vulnérabilité. La véritable condition de déclenchement reste « atteindre une configuration rewrite vulnérable + entrée pouvant entrer dans les groupes de capture concernés + traitement de la sortie de rewrite déclenchant le débordement de tas ». Selon l'environnement, la route de déclenchement, le type de caractères et le seuil de longueur peuvent tous devoir être ajustés.

3.1 Explication des autres caractères pouvant déclencher la vulnérabilité

Le PoC actuel choisit par défaut une grande quantité de + comme caractère de déclenchement, mais cela ne signifie pas que seul + peut déclencher le problème. + est simplement le caractère le plus adapté à un PoC générique, car il est relativement stable dans un URI, facilement envoyé par un client HTTP ordinaire, et sa signature dans les captures de paquets est claire.

D'un point de vue théorique, dès lors qu'un caractère entre dans la logique d'échappement NGX_ESCAPE_ARGS lors du traitement de rewrite par NGINX et passe de 1 octet original à 3 octets sous forme %XX, cela peut créer une différence où « la valeur de longueur calculée est inférieure à la valeur réellement écrite ». En d'autres termes, le point de déclenchement n'est pas essentiellement + lui-même, mais « l'apparition dense de caractères pouvant être échappés en mode args ».

Outre +, les caractères qui méritent théoriquement une attention particulière sont :

root@kitploit:~
空格:0x20
#:0x23
%:0x25
&:0x26
?:0x3F
控制字符:0x00-0x1F
高位字节:0x7F-0xFF

Ces caractères, s'ils entrent dans la capture concernée et sont traités comme contenu args lors de l'échappement dans le replacement de rewrite, produiront tous un effet d'expansion similaire. Par exemple :

root@kitploit:~
+      -> %2B
&      -> %26
%      -> %25
#      -> %23
?      -> %3F
空格   -> %20

Chaque apparition de ce type de caractère passe théoriquement de 1 octet à 3 octets, la longueur réellement écrite augmentant de 2 octets. Si l'entrée contient un grand nombre de ces caractères, la longueur réellement écrite peut dépasser significativement la longueur de tampon calculée précédemment de manière erronée, ce qui rend le déclenchement d'un heap buffer overflow plus facile.

Cependant, la disponibilité des différents caractères dans le PoC n'est pas identique.

+ est le plus stable. Il peut généralement apparaître directement dans le request-target HTTP, n'est pas facilement tronqué par les navigateurs ou les outils en ligne de commande, et ne modifie pas naturellement la structure path/query de l'URI. C'est pourquoi le PoC actuel utilise 4096 + comme payload par défaut.

& peut également être un caractère candidat, car il est échappé en %26 en mode args. Mais dans un shell, & a une signification d'exécution en arrière-plan, et dans une URL, il est souvent utilisé comme séparateur de paramètres de query ; il faut donc être attentif aux guillemets et à la position lors des tests, sinon la requête pourrait ne pas être envoyée comme prévu.

% peut également être un caractère candidat, car il est échappé en %25. Mais % est aussi lui-même le préfixe de l'encodage URL ; certains clients, proxys ou frameworks peuvent tenter d'interpréter les séquences %XX. Si la construction est inadaptée, la cible risque de ne pas recevoir le caractère % d'origine, mais un contenu prétraité par le client.

? est théoriquement aussi un caractère échappable, mais il sépare le path et la query dans le request-target HTTP. S'il est placé directement dans le chemin, le contenu suivant risque d'être analysé comme une query string, modifiant ainsi la portée de capture du rewrite. Il est donc plus adapté comme caractère de test complémentaire que comme caractère principal par défaut du PoC.

# peut théoriquement déclencher l'échappement, mais les navigateurs n'envoient pas # ni le fragment qui le suit au serveur, et de nombreux clients HTTP avancés l'encodent ou le tronquent également. Par conséquent, pour tester le # littéral, il faut généralement un raw socket, Burp Repeater ou un outil capable de conserver le request-target d'origine ; on ne peut pas se fier directement à la barre d'adresse du navigateur.

L'espace 0x20 est aussi un caractère échappable, mais dans une ligne de requête HTTP/1.1 ordinaire, l'espace est lui-même un séparateur ; l'insérer directement dans le request-target briserait la structure de la ligne de requête. Lors des tests réels, si l'on écrit %20, que le serveur voie la forme encodée ou l'espace décodé à l'étape de traitement dépend du processus d'analyse précis et de l'emplacement du rewrite. L'espace est donc plus adapté à l'explication du principe et aux tests auxiliaires qu'au payload par défaut.

Les caractères de contrôle 0x00-0x1F et les octets élevés 0x7F-0xFF sont également dans la plage d'échappement, mais dans une chaîne HTTP réelle, ils sont plus facilement interceptés, normalisés ou rejetés par les clients, proxys, WAF ou le parseur HTTP de NGINX. Ils peuvent servir à illustrer les objets d'échappement au niveau du code source, mais il n'est pas recommandé d'en faire les caractères de déclenchement par défaut d'un PoC classique.

Par conséquent, si le PoC actuel utilise +, ce n'est pas parce que la vulnérabilité ne peut être déclenchée que par +, mais parce que + satisfait simultanément trois conditions : il peut déclencher l'expansion d'échappement args, il est facile à envoyer de manière stable, et il ne modifie pas sensiblement la structure de l'URI. Pour les règles de protection ou l'analyse du trafic, il ne faut pas se limiter à détecter des + consécutifs ; il faut aussi prendre en compte les combinaisons à haute densité d'autres caractères échappables, en particulier les cas où +, &, %, ?, # apparaissent en grand nombre dans un URI long.

D'un point de vue détection, la caractérisation la plus raisonnable n'est pas :

root@kitploit:~
/api/ 后面出现大量 +

mais :

root@kitploit:~
长 URI 中出现大量会在 NGX_ESCAPE_ARGS 模式下扩张为 %XX 的特殊字符

Si l'on ne détecte que ++++, la règle ne couvre que la forme par défaut du PoC actuel ; si l'attaquant remplace le payload par &&&&, %%%%, ????, ou utilise un mélange de +%&?#, une signature basée uniquement sur + risque de manquer la détection. Une approche de détection plus fiable consiste à combiner la longueur de l'URI, la densité de caractères spéciaux, le nombre de répétitions consécutives, les chemins de rewrite à risque et la surface d'exposition du service NGINX.

4. Logique de normalisation de la cible

La fonction normalize_target du PoC traite l'entrée en ligne de commande et prend en charge trois formes :

root@kitploit:~
python3 CVE-2026-9256-poc.py 127.0.0.1:19321
python3 CVE-2026-9256-poc.py 127.0.0.1 19321
python3 CVE-2026-9256-poc.py http://127.0.0.1:19321

Si l'utilisateur ne saisit que host:port sans indiquer de schéma, le script ajoute automatiquement http://host:port. Il utilise ensuite urllib.parse.urlparse pour extraire le hostname et le port, puis génère base, par exemple :

root@kitploit:~
host = 127.0.0.1
port = 19321
base = http://127.0.0.1:19321

L'implémentation actuelle cible principalement les environnements de test HTTP en clair. Bien que normalize_target accepte la forme https://, la détection keep-alive ultérieure utilise un socket TCP ordinaire, sans couche TLS, aussi le crash probe serait inexact dans un scénario HTTPS. Pour prendre en charge HTTPS, il faudrait ajouter ssl.wrap_socket ou ssl.create_default_context().wrap_socket() au socket.

5. Détection de disponibilité et sondage du rewrite

Le PoC appelle d'abord check_alive(base) pour accéder au chemin racine / :

root@kitploit:~
GET /

Si la cible renvoie un code de statut HTTP quelconque, cela signifie que le service est globalement actif et que l'on peut continuer les tests. Si la connexion échoue, le script se termine directement, afin d'éviter de confondre une cible injoignable avec un échec de déclenchement de la vulnérabilité.

Ensuite, il appelle check_rewrite(base) pour accéder à :

root@kitploit:~
GET /api/test

Cette requête sert à observer si /api/* peut atteindre la logique de rewrite de l'environnement de test actuel. Si des codes de statut de redirection tels que 301, 302, 303, 307, 308 sont renvoyés, cela indique que le comportement de redirect du rewrite est relativement net ; le PoC affiche alors l'en-tête Location comme preuve auxiliaire.

Mais cette étape n'est pas une condition de succès obligatoire. En effet, dans certaines configurations de reproduction, /api/* peut lui-même entrer dans le chemin de rewrite problématique, et même une requête de sondage ordinaire peut expirer ou être traitée anormalement. Le script poursuit donc la phase de déclenchement même s'il n'a pas obtenu de réponse de rewrite normale.

6. Conception de la requête de déclenchement du débordement

La fonction de déclenchement est send_trigger(base, plus_count=4096) ; sa logique centrale consiste à concaténer :

root@kitploit:~
payload = "/api/" + ("+" * plus_count)

Le chemin de requête final par défaut ressemble à :

root@kitploit:~
/api/++++++++++++++++++++++++++++++++...  共 4096 个 +

La requête est ensuite envoyée via requests.get(base + payload, timeout=10, allow_redirects=False).

La désactivation du suivi automatique des redirections obéit à deux raisons.

Premièrement, le rewrite peut lui-même renvoyer un redirect. Si le client HTTP suit automatiquement la redirection, la requête de déclenchement d'origine et la requête de redirection suivante se mélangent, ce qui ne facilite pas la détermination de ce qui s'est réellement passé lors de la première requête.

Deuxièmement, le PoC s'intéresse à l'état de la connexion pendant la phase de déclenchement, et non à la page métier après la redirection. Conserver la réponse d'origine est plus propice à l'analyse.

Les résultats de déclenchement sont répartis en plusieurs catégories :

Si une ConnectionError est capturée, cela signifie que la connexion a été fermée anormalement pendant la requête de déclenchement ; cela peut être la manifestation distante d'un crash du worker.

Si un ReadTimeout est capturé, cela signifie qu'aucune réponse normale n'est parvenue longtemps après l'envoi de la requête ; il peut s'agir d'un worker bloqué, d'un worker qui n'est pas revenu normalement avant le crash, ou d'un dépassement de délai dû à l'environnement réseau.

Si une réponse HTTP normale est reçue, le code de statut et la longueur du corps de la réponse sont affichés, mais on ne peut pas infirmer la vulnérabilité sur la seule base d'une réponse normale, car dans certains environnements les conditions de déclenchement peuvent ne pas être entièrement réunies, ou la longueur du payload peut être insuffisante.

7. Pourquoi une détection de reprise follow-up est-elle nécessaire ?

Après la requête de déclenchement, le PoC attend 1 seconde, puis appelle follow_up(base) pour accéder à nouveau au chemin racine /.

Le but de cette étape n'est pas de prouver le débordement lui-même, mais de déterminer si NGINX présente la caractéristique d'un « worker relancé par le master après un crash ».

Si la connexion de la requête de déclenchement est interrompue anormalement, mais que l'accès ultérieur à / renvoie à nouveau 200 ou un autre code de statut HTTP normal, cela signifie que le service n'est pas tombé dans son ensemble ; il ressemble davantage à un processus worker individuel qui a été abattu puis s'est rétabli.

Si le service reste longtemps injoignable après le déclenchement, il peut s'agir d'un arrêt complet du service, d'un crash du conteneur ou d'une anomalie réseau ; un tel résultat ne peut pas être directement assimilé à un déclenchement réussi de CVE-2026-9256.

Par conséquent, le critère de jugement du PoC actuel est : un crash de worker visible à distance, et non un simple « service indisponible ».

8. Conception de la sonde de crash keep-alive

La validation de stabilité la plus critique du PoC est keepalive_probe(host, port, rounds=5, plus_count=4096).

Il n'utilise pas requests, mais établit directement une connexion TCP via socket.create_connection, puis envoie successivement trois requêtes sur la même connexion keep-alive.

La première requête est une requête normale :

root@kitploit:~
GET / HTTP/1.1
Host: 127.0.0.1
Connection: keep-alive

Cette requête sert à confirmer que la connexion actuelle est utilisable et à faire en sorte, autant que possible, que la requête de déclenchement ultérieure passe par la même connexion.

La deuxième requête est la requête de déclenchement :

root@kitploit:~
GET /api/++++++++++++++++++++++++++++++++... HTTP/1.1
Host: 127.0.0.1
Connection: keep-alive

Si cette requête déclenche un crash du worker, la connexion keep-alive maintenue par ce worker sera très probablement interrompue directement.

La troisième requête est à nouveau une requête normale :

root@kitploit:~
GET / HTTP/1.1
Host: 127.0.0.1
Connection: close

Si une réponse est encore reçue pour la troisième requête, cela signifie que la connexion n'a pas été interrompue par la requête de déclenchement ; cette itération n'est pas considérée comme un crash du worker.

Si l'envoi de la troisième requête échoue, qu'aucune donnée ne peut être lue, ou que la connexion a déjà été fermée, l'événement est enregistré comme :

root@kitploit:~
keepalive connection dropped

Le PoC répète 5 itérations par défaut. L'intérêt de répéter plusieurs fois est de réduire les erreurs de jugement dues à des anomalies réseau ponctuelles. Si, sur 5 itérations, la connexion keep-alive tombe à plusieurs reprises et que le service parvient ensuite à reprendre ses réponses, les preuves côté distant sont plus solides.

9. Logique de détermination du succès

Le jugement final du PoC comporte trois niveaux.

Premier niveau : vulnérabilité confirmée.

La condition est :

root@kitploit:~
crash_count > 0 and recovered == True

C'est-à-dire qu'au moins une itération de la sonde keep-alive détecte une chute de connexion, et que la requête normale follow-up prouve que le service a repris ses réponses. Le script affiche :

root@kitploit:~
VULNERABILITY CONFIRMED - CVE-2026-9256 style crash behavior
Impact confirmed: worker crash / denial of service
RCE is not proven by this script

Cela indique que l'environnement actuel présente un comportement de crash du worker de type CVE-2026-9256, mais ne prouve pas l'exécution de code à distance.

Deuxième niveau : vulnérabilité suspectée.

La condition est :

root@kitploit:~
kind == "connection_error" and recovered == True

C'est-à-dire que la requête de déclenchement principale a subi une interruption de connexion et que le service a ensuite repris, mais que la sonde keep-alive n'a pas confirmé de manière stable le crash du worker. Le script affiche VULNERABILITY SUSPECTED.

Cette situation indique qu'un phénomène anormal existe, mais que les preuves ne sont pas assez stables ; une confirmation supplémentaire est nécessaire en s'appuyant sur l'error.log du serveur, un core dump, les journaux du conteneur ou un débogueur.

Troisième niveau : non confirmé.

Si l'on n'observe ni chute fiable de la connexion keep-alive, ni combinaison d'interruption anormale de la connexion de déclenchement avec reprise du service, le script affiche :

root@kitploit:~
VULNERABILITY NOT CONFIRMED

Cela ne signifie pas nécessairement que la cible est absolument exempte de vulnérabilité ; il peut aussi s'agir d'un chemin qui n'atteint pas le rewrite, d'une longueur de payload insuffisante, d'un choix de caractères inadapté, d'une version cible déjà corrigée, d'un proxy amont qui modifie l'URI, ou du fait que le script actuel n'est pas adapté à HTTPS.

10. Flux d'exécution complet du PoC actuel

Le flux d'exécution du script peut se résumer ainsi :

  1. Analyser l'adresse cible et générer host, port, base.
  2. Afficher les informations de base du PoC, en précisant clairement qu'il ne valide que le crash du worker et n'implémente pas de RCE.
  3. Envoyer une requête à / pour confirmer que le service cible est actif.
  4. Envoyer une requête à /api/test pour tenter de déterminer si le chemin rewrite d'exemple est actif.
  5. Envoyer la requête de déclenchement avec l'URI long composé de /api/ suivi de 4096 +.
  6. Enregistrer le premier résultat de déclenchement selon l'interruption de connexion, le dépassement de délai ou la réponse HTTP.
  7. Après une attente de 1 seconde, envoyer à nouveau une requête à / pour confirmer si le worker a repris.
  8. Établir une connexion keep-alive via socket et envoyer successivement une requête normale, la requête de déclenchement, puis une requête normale.
  9. Répéter la sonde keep-alive sur 5 itérations et compter le nombre de chutes de connexion.
  10. Afficher confirmed, suspected ou not confirmed selon crash_count, l'état de la connexion trigger et la reprise observée par follow-up.

11. Exemples d'utilisation

Exemple avec un environnement de test local :

root@kitploit:~
python3 CVE-2026-9256-poc.py http://127.0.0.1:19321

ou :

root@kitploit:~
python3 CVE-2026-9256-poc.py 127.0.0.1 19321

Lorsque le déclenchement réussit, la sortie typique ressemble à :

root@kitploit:~
[+] Connection dropped during trigger request
[+] Worker is responding after trigger (HTTP 200)
round 1: worker likely crashed (keepalive connection dropped)
round 2: worker likely crashed (keepalive connection dropped)
...
[+] VULNERABILITY CONFIRMED - CVE-2026-9256 style crash behavior
[+] Impact confirmed: worker crash / denial of service
[*] RCE is not proven by this script

Ce type de sortie indique que des preuves relativement stables de crash du worker ont été observées côté distant.

12. Limites de sécurité dans la conception du PoC

Les limites de sécurité de ce PoC sont relativement claires :

Premièrement, il ne fait que valider le crash, sans exploitation RCE.

Deuxièmement, il ne construit pas de heap spray, de ROP, de contournement d'ASLR, de shellcode ni de logique d'exécution de commandes.

Troisièmement, son critère de succès est la chute de la connexion worker et la reprise du service, et non l'obtention d'un shell ou la lecture de fichiers.

Quatrièmement, il convient à la reproduction locale, à la validation de vulnérabilités, à la construction de règles IDS/IPS et aux tests comparatifs avant/après correctif.

Pour renforcer encore la sécurité, les limitations suivantes peuvent être ajoutées :

  1. N'autoriser l'accès qu'à 127.0.0.1, localhost, aux adresses privées ou aux segments de réseau expérimentaux explicitement autorisés.
  2. Ajouter le paramètre --plus-count pour éviter d'envoyer par défaut un payload trop volumineux.
  3. Ajouter le paramètre --route pour permettre à l'utilisateur de spécifier explicitement le chemin de déclenchement au lieu d'un /api/ codé en dur.
  4. Ajouter le paramètre --rounds pour contrôler le nombre d'itérations de la sonde keep-alive.
  5. Ajouter la prise en charge de HTTPS, sinon la logique actuelle du socket keep-alive ne convient qu'aux services HTTP en clair.
  6. Ajouter le paramètre de débogage --print-request pour afficher la requête HTTP réellement envoyée, ce qui facilite la comparaison avec les captures de paquets.

13. Enseignements pour l'écriture de règles de protection

Du point de vue de la dérivation du PoC, les règles de détection ne doivent pas se focaliser uniquement sur /api/, car /api n'est pas le chemin fixe de la vulnérabilité, mais seulement un exemple de l'environnement de test actuel. Les points de détection réellement plus précieux devraient être :

  1. La direction de la requête doit être du client vers le serveur.
  2. La longueur de l'URI est nettement anormale.
  3. L'URI contient un grand nombre de caractères consécutifs ou à haute densité susceptibles de déclencher l'expansion/échappement de la sortie du rewrite, par exemple une grande quantité de +, ou un mélange de caractères spéciaux tels que +, &, %, ?, #.
  4. Le risque d'atteinte est plus élevé lorsque le service cible présente une surface d'exposition NGINX rewrite.

Si la règle se limite à écrire en dur /api/++++, elle ne couvre que le PoC actuel et l'environnement de test actuel ; pour couvrir un trafic d'attaque plus générique, il convient d'extraire des signatures autour de « URI long + apparition dense de nombreux caractères spéciaux + direction de la requête HTTP + chemins de rewrite NGINX à risque ».

Par ailleurs, comme des URL longues ou de nombreux caractères encodés peuvent aussi exister dans un trafic métier légitime, les règles doivent réduire les faux positifs en combinant un seuil de longueur, la densité de caractères, le nombre de répétitions et le contexte du chemin. Une orientation de détection relativement fiable est :

root@kitploit:~
长 URI
+
大量可被 NGX_ESCAPE_ARGS 转义扩张的特殊字符
+
请求方向 to_server
+
NGINX rewrite 相关暴露面

plutôt que de détecter simplement :

root@kitploit:~
/api/++++

Pour les règles Suricata / Snort, si l'on souhaite uniquement couvrir le PoC public actuel, on peut utiliser les + consécutifs comme l'une des signatures fortes ; si l'on souhaite couvrir les variantes, il faut intégrer la plage des caractères spéciaux dans le PCRE, par exemple +, %, #, &, ? ainsi que d'autres caractères susceptibles d'être échappés avec expansion. Mais ce type de règle est aussi plus sujet aux faux positifs ; il doit être utilisé conjointement avec urilen, un seuil de répétition de caractères, des contraintes de chemin et le périmètre des actifs NGINX.

14. Résumé

Le point central de la dérivation du PoC pour CVE-2026-9256 n'est pas de chercher un chemin de vulnérabilité fixe, mais de comprendre d'abord les conditions de déclenchement : une configuration rewrite vulnérable, des groupes de capture se chevauchant, la référence à plusieurs variables de capture, ainsi que des entrées URI spéciales capables de faire anormalement grossir le résultat du traitement de rewrite.

Le script actuel choisit /api/ suivi de 4096 + parce que ce chemin atteint la règle rewrite de l'environnement de reproduction actuel, et qu'une grande quantité de + permet de créer de manière stable une pression par entrée longue. Le script n'implémente pas de RCE ; il prouve le crash du worker par l'interruption de connexion, la reprise du service et les chutes de connexion keep-alive sur plusieurs itérations.

Par ailleurs, + n'est que le caractère par défaut le plus stable et le plus facile à envoyer ; ce n'est pas le seul caractère susceptible de déclencher la vulnérabilité. Tous les caractères qui s'expandent en %XX en mode NGX_ESCAPE_ARGS doivent être pris en compte dans l'analyse du principe et dans l'élaboration des règles de protection. La compréhension la plus juste est la suivante : l'apparition dense, dans un URI long, de caractères échappables avec expansion, entrant dans la capture du rewrite vulnérable puis dans le traitement du replacement, provoque une incohérence entre le calcul de longueur et l'écriture effective, conduisant finalement à un crash du worker ou à une corruption mémoire plus grave.

Télécharger l’outil