Skip to content

HTTP Directory Listing : navigation libre dans les fichiers d'un serveur

Quand un serveur reçoit une requête sur un répertoire qui ne contient pas de fichier index.html, il a deux options : retourner une erreur 403 Forbidden, ou lister le contenu du répertoire. Beaucoup de serveurs font la deuxième par défaut.

Le directory listing est une fonctionnalité de serveur web qui génère automatiquement une page HTML listant les fichiers et sous-répertoires d’un dossier demandé. Aucun code d’exploitation n’est nécessaire — un simple navigateur suffit.

La RFC 2616 (HTTP/1.1) ne définit pas de comportement standard pour les requêtes sur un répertoire. Chaque serveur implémente sa propre logique, et l’activation du listing est souvent le comportement par défaut à l’installation.

En naviguant librement dans l’arborescence exposée, on trouve couramment :

  • des sauvegardes : db_dump.sql, backup.zip, config.bak
  • des fichiers d’environnement : .env, settings.py, config.php
  • des logs applicatifs : identifiants, stack traces, adresses IP internes
  • des clés et certificats : id_rsa, *.pem, *.key
  • du code source : fichiers .php, .py, .js non destinés à être servis directement

Une page de directory listing retourne un code 200 OK avec un titre du type :

Index of /uploads/

Tester directement avec curl :

Terminal window
curl -s https://cible.fr/uploads/ | grep -i "Index of"

Dans un navigateur, naviguer vers un répertoire suspect. Les serveurs courants affichent :

Apache :

Index of /backup
Name Last modified Size Description
[DIR] configs/ 2024-01-15 10:23 -
[ ] .env 2024-01-10 08:12 1.2K
[ ] db.sql 2024-01-10 08:14 4.5M

Nginx :

<h1>Index of /backup/</h1>
<hr>
<a href=".env">.env</a>
<a href="db.sql">db.sql</a>

Fichiers de sauvegarde des éditeurs de texte

Section titled “Fichiers de sauvegarde des éditeurs de texte”

Quand un développeur édite un fichier directement sur le serveur avec vim, nano ou gedit, l’éditeur crée automatiquement un fichier de sauvegarde en ajoutant un tilde ~ au nom d’origine. Si ce fichier reste sur le serveur et que la racine web est mal isolée, il devient accessible via HTTP.

Terminal window
# Si config.php existe, tester l'existence de sa sauvegarde
curl -s -o - https://cible.fr/config.php~
# Tester sur d'autres fichiers courants
curl -I https://cible.fr/index.php~
curl -I https://cible.fr/.htpasswd~
curl -I https://cible.fr/wp-config.php~

Un code 200 OK retourne le contenu brut du fichier PHP — le serveur ne l’exécute pas, il le sert comme texte. Les identifiants de base de données, clés API et mots de passe en clair sont directement lisibles.

Cette technique fonctionne même si le directory listing est désactivé : le fichier ~ est servi individuellement sans nécessiter de navigation dans l’arborescence.

Combiner un outil de fuzzing avec la détection du listing :

Terminal window
# Gobuster avec détection des codes 200 et 403
gobuster dir -u https://cible.fr -w /usr/share/wordlists/dirb/common.txt -s 200,403
# Feroxbuster avec récursion automatique
feroxbuster -u https://cible.fr --depth 3

Un répertoire /backup/ exposé contient souvent cette structure :

backup/
├── 2024-01-10/
│ ├── db_dump.sql # dump complet de la base de données
│ ├── config.php.bak # configuration avec identifiants BDD
│ └── uploads.tar.gz # fichiers uploadés par les utilisateurs
├── .env # variables d'environnement (clés API, mots de passe)
└── deploy.sh # script de déploiement avec credentials SSH

Le fichier .env est la cible prioritaire : il contient systématiquement les secrets applicatifs.

Télécharger l’intégralité du répertoire exposé

Section titled “Télécharger l’intégralité du répertoire exposé”
Terminal window
# Téléchargement récursif sans remonter au répertoire parent
wget -r --no-parent -nH --cut-dirs=1 https://cible.fr/backup/
# Avec authentification si un formulaire HTTP Basic est présent
wget -r --no-parent --user=user --password=pass https://cible.fr/backup/

Extraire les secrets d’un fichier .env récupéré

Section titled “Extraire les secrets d’un fichier .env récupéré”
Terminal window
# Afficher les variables sensibles
grep -E "(KEY|SECRET|PASSWORD|TOKEN|DATABASE)" .env

Dans httpd.conf ou .htaccess :

Options -Indexes

Pour désactiver globalement et réactiver uniquement pour des répertoires spécifiques :

# Désactivation globale dans httpd.conf
<Directory />
Options -Indexes
</Directory>
# Réactivation ciblée si nécessaire
<Directory /var/www/html/public>
Options +Indexes
</Directory>

Dans le bloc server ou location :

server {
location / {
autoindex off;
}
}

Dans web.config :

<configuration>
<system.webServer>
<directoryBrowse enabled="false" />
</system.webServer>
</configuration>

Ou via l’interface graphique : IIS Manager → Site → Directory Browsing → Disable.

ServeurComportement par défautOption à modifier
Apache 2.xListing activé si Options Indexes présentOptions -Indexes
NginxDésactivé par défautautoindex off (si activé)
IISDésactivé par défautdirectoryBrowse enabled="false"
LighttpdDésactivé par défautdir-listing.activate = "disable"

Bloquer l’accès aux fichiers sensibles même si un répertoire venait à être exposé :

Apache (.htaccess) :

# Interdire l'accès aux fichiers de configuration, sauvegardes et fichiers éditeur
<FilesMatch "\.(env|sql|bak|log|key|pem|sh)$|~$">
Require all denied
</FilesMatch>

Nginx :

location ~* \.(env|sql|bak|log|key|pem|sh)$|~$ {
deny all;
return 404;
}

Ne jamais éditer des fichiers de configuration directement sur le serveur de production. Passer par un pipeline de déploiement évite de laisser des fichiers ~ dans la racine web.

Ne jamais stocker des sauvegardes, des dumps ou des fichiers de configuration dans un répertoire servi par le serveur web. Ces fichiers appartiennent en dehors de la racine web (/var/www/html), ou dans un stockage objet avec contrôle d’accès explicite.

Désactiver le directory listing est une mesure de base à vérifier avant toute mise en production. L’absence d’un fichier index.html dans un répertoire ne le protège pas — si le serveur liste son contenu, n’importe qui peut naviguer dedans.

Un répertoire non référencé dans l’interface reste accessible : si le serveur le sert, un attaquant peut le trouver par fuzzing.