La faille CVE-2026-42945 de Nginx, restée latente pendant 18 ans : principe, PoC et correctifs décryptés

🚨 CVE-2026-42945 : une faille critique de Nginx restée latente pendant 18 ans — principe, PoC et correctifs
Le 13 mai 2026, le cabinet de recherche en sécurité depthfirsta révélé conjointement avec F5 l'une des failles les plus critiques de l'histoire de NGINX — CVE-2026-42945 :
- Score CVSS v4.0 de 9.2 : une vulnérabilité de gravité critique
- Dépassement de tampon sur le tas (heap) : peut conduire à une exécution de code à distance (RCE)
- 18 ans de latence : le code était présent dans la base depuis 2008
- 9,75 millions de sites touchés dans le monde : plus de 2,54 millions de sites web en Chine concernés
- PoC public : reproduction confirmée par QiAnXin
Il s'agit d'une faille historique du cœur même de NGINX : l'attaquant peut prendre le contrôle du serveur à distance avec une simple requête HTTP spécialement forgée.
🔍 Aperçu de la vulnérabilité
Informations générales
| Propriété | Détails |
|---|---|
| Identifiant de la faille | CVE-2026-42945 |
| Score CVSS | v4.0: 9.2 | v3.1: 8.1 |
| Type de faille | Dépassement de tampon sur le tas (Heap-based Buffer Overflow) |
| Type de menace | Exécution de code à distance (RCE), déni de service (DoS) |
| Conditions d'exploitation | Aucune authentification requise, une simple requête HTTP suffit |
| Composant concerné | ngx_http_rewrite_module (module natif au cœur de NGINX) |
| Découverte par | depthfirst (découverte par un système automatisé en 6 heures) |
Portée de l'impact
- 9,75 millions de sites dans le mondeconcernés
- 2,54 millions de sites web en Chineconcernés
- NGINX sert environ 1/3 des sites web mondiaux, d'où une surface d'impact immense
- Le code est présent depuis 2008, soit une latence de 18 ans
⚠️ Conditions de déclenchement
Trois conditions à réunir simultanément
Le déclenchement de la faille exige une combinaison précise de conditions de configuration :
| Condition | Description | Exemple |
|---|---|---|
| 1. Capture PCRE anonyme | la directive rewrite utilise des groupes de capture anonymes | $1, $2, $3… |
| 2. Chaîne de remplacement contenant un point d'interrogation | la chaîne de remplacement contient un caractère ? | /profile.php?id=$1&tab=$2 |
| 3. Suivie d'une directive rewrite/if/set | la directive rewrite est immédiatement suivie d'une autre directive | rewrite … last; if (…) { … } |
Exemple de configuration vulnérable
# 易受攻击配置
rewrite ^/users/([0-9]+)/profile/(.*)$ /profile.php?id=$1&tab=$2 last;
# 后跟其他指令
if ($arg_debug) {
set $debug_flag 1;
}
Cette configuration réunit les trois conditions : captures anonymes $1/$2, chaîne de remplacement contenant un ?, suivie d'une directive if.
🔬 Fonctionnement de la faille
Une incohérence d'état entre deux phases de traitement
Le moteur de script de NGINX fonctionne en deux phases :
- Phase 1 : calcul de la taille de tampon nécessaire
- Phase 2 : copie des données dans le tampon
Le cœur de la faille tient à une mauvaise gestion de l'indicateur is_args :
| Phase | État de is_args | Logique de traitement | Résultat |
|---|---|---|---|
| Phase de calcul de longueur | is_args = 0 | renvoie la longueur brute des captures | taille du tampon sous-estimée |
| Phase de copie des données | is_args = 1 | appelle ngx_escape_uri : chaque octet peut s'étendre à 3 octets | dépassement de tampon sur le tas |
Déroulé détaillé
- La directive rewrite contient des captures anonymes $1/$2
- La chaîne de remplacement contient un ?, ce qui force is_args = 1
- Phase de calcul de longueur : un sous-moteur fraîchement initialisé est utilisé, avec is_args = 0
- il renvoie la longueur brute : un tampon de tas trop petit est alloué
- Phase de copie des données : le moteur principal prend le relais, avec is_args = 1
- il appelle ngx_escape_uri : les octets s'étendent et débordent du tampon
- Les données d'URI contrôlées par l'attaquant s'écrivent dans la zone de débordement
Mode d'exploitation
Heap Feng Shui à travers plusieurs requêtes :
- corps de requêtes POST pour asperger la mémoire du tas (car les URI ne peuvent pas contenir d'octets null)
- Les données du débordement corrompent le pointeur cleanup d'une structure ngx_pool_t adjacente
- une structure ngx_pool_cleanup_s forgée , pointant vers system()
- Lors de la destruction du pool, l'appel à system() est déclenché
- et la RCE est obtenue
Effet de l'ASLR
- ASLR activé : uniquement un plantage du processus worker (DoS)
- ASLR désactivé : l'exécution de code à distance (RCE) devient possible
📊 Versions concernées
NGINX Open Source
| Plage de versions | Version corrigée |
|---|---|
| 0.6.27 – 1.30.0 | 1.31.0, 1.30.1 |
NGINX Plus
| Plage de versions | Version corrigée |
|---|---|
| R32 – R36 | R36 P4, R35 P2, R32 P6 |
Autres composants concernés
- NGINX Instance Manager : 2.16.0 – 2.21.1
- NGINX App Protect WAF : 4.9.0 – 5.8.0
- NGINX Ingress Controller : 3.5.0 – 5.4.1
- NGINX Gateway Fabric : 1.3.0 – 2.5.1
- F5 DoS for NGINX : 4.8.0
🔥 État du PoC
PoC public
- Dépôt GitHub :https://github.com/DepthFirstDisclosures/Nginx-Rift
- Reproduction confirmée par QiAnXin : les chercheurs du centre de threat intelligence ont réussi à la reproduire
- Détails techniques publiés : depthfirst a publié son analyse technique
- Exploitation en conditions réelles : aucun cas recensé à ce jour
Mode d'emploi du PoC
# 构建容器 ./setup.sh # 启动易受攻击的 NGINX 服务器 docker compose -f env/docker-compose.yml up # 执行 PoC 获取 Shell python3 poc.py --shell
✅ Correctifs
Méthode 1 : mettre à jour les versions
# 升级到修复版本 NGINX Open Source >= 1.31.0 NGINX Open Source >= 1.30.1 NGINX Plus >= R32 P6 NGINX Plus >= R36 P4 # 升级后重启 NGINX nginx -s reload
Méthode 2 : modifier la configuration (mesure d'atténuation)
Remplacer les groupes de capture anonymes par des groupes de capture nommés :
# 易受攻击配置(未命名捕获) rewrite ^/users/([0-9]+)/profile/(.*)$ /profile.php?id=$1&tab=$2 last; # 修复后配置(命名捕获) rewrite ^/users/(?[0-9]+)/profile/(?.*)$ /profile.php?id=$user_id&tab=$section last;
Les groupes de capture nommés ne déclenchent pas la faille.
Méthode 3 : vérifier sa configuration
Rechercher les configurations vulnérables :
# 搜索易受攻击的 rewrite 指令 grep -E "rewrite.*\$[0-9]+.*\?.*(rewrite|if|set)" /etc/nginx/nginx.conf grep -rE "rewrite.*\$[0-9]+.*\?.*(rewrite|if|set)" /etc/nginx/conf.d/
🔍 Processus de découverte
Découverte par un système automatisé
depthfirst : son système d'analyse de sécurité a,
- en 6 heures, trouvé 5 problèmes
- dont 4 confirmés par NGINX
- CVE-2026-42945est la plus grave des failles
- Elle remonte à 2008 et est présente dans presque toutes les builds standards
Autres failles associées
- CVE-2026-42946 : corruption mémoire
- CVE-2026-40701 : corruption mémoire
- CVE-2026-42934 : corruption mémoire
📝 En résumé
CVE-2026-42945est l'une des failles les plus critiques de l'histoire de NGINX :
- 18 ans de latence : le code est présent dans la base depuis 2008
- CVSS 9.2 : dépassement de tampon sur le tas, pouvant mener à une RCE
- Conditions de déclenchement : directive rewrite avec captures anonymes + chaîne de remplacement contenant un ? + suivie d'une autre directive
- Portée : 9,75 millions de sites dans le monde, dont 2,54 millions de sites web en Chine
- PoC public : dépôt GitHub + reproduction confirmée par QiAnXin
- Correctifs : mise à jour des versions ou adoption de groupes de capture nommés
Une faille restée 18 ans dans l'ombre vient d'éclater : il est vivement conseillé de mettre à jour ou d'ajuster sa configuration sans tarder.
Annonce officielle :https://my.f5.com/manage/s/article/K000161019
Dépôt du PoC :https://github.com/DepthFirstDisclosures/Nginx-Rift
Analyse technique :https://depthfirst.com/research/nginx-rift