vendredi 25 septembre 2026

À propos

Contact

Sécurité

Path traversal dans une extension : les inclusions de fichiers dangereuses

Un simple paramètre de template mal contrôlé peut suffire à lire n'importe quel fichier du serveur. Trois cas vus en audit, trois corrections.

Par Clément Hadrot • 3 mars 2021 • 4 min de lecture • Aucun commentaire
Path traversal dans une extension : les inclusions de fichiers dangereuses

Lors de l’audit d’une extension maison développée pour un client, nous avons trouvé le même schéma vulnérable répété à trois endroits distincts du code : un paramètre transmis par l’utilisateur, utilisé sans validation pour construire un chemin de fichier, lui-même transmis directement à une fonction d’inclusion ou de lecture de fichier. Ce schéma porte un nom bien identifié en sécurité applicative : le path traversal, ou traversée de répertoire.

Le principe est simple à comprendre et pourtant facile à introduire par inadvertance : en insérant des séquences ../ dans un paramètre censé désigner un nom de fichier interne, un attaquant remonte l’arborescence du serveur jusqu’à atteindre des fichiers qui n’ont jamais été destinés à être exposés, y compris en dehors du dossier de l’extension elle-même.

Ce qu’on voit : un paramètre utilisateur dans une fonction d’inclusion

Le premier des trois cas ressemblait à ceci, dans une fonctionnalité censée charger un template de mise en page parmi une liste proposée à l’utilisateur :

// Code vulnérable
$template = $_GET['template'] ?? 'defaut';
include plugin_dir_path( __FILE__ ) . 'templates/' . $template . '.php';

Le deuxième cas concernait une fonction d’export qui lisait un fichier journal désigné par son nom, transmis via un formulaire d’administration :

// Code vulnérable
$fichier = $_POST['nom_fichier'];
readfile( '/var/www/exemple/logs/' . $fichier );

Pourquoi c’est un problème

Dans le premier cas, une requête vers ?template=../../../../wp-config.php%00 visait, sur les versions de PHP anciennes qui interprétaient encore l’octet nul en fin de chaîne, à contourner l’ajout de l’extension .php pour lire directement le fichier de configuration. Sur les versions modernes de PHP, où cette technique par octet nul ne fonctionne plus, une simple séquence de remontée suffisait déjà à sortir du dossier templates/ pour atteindre n’importe quel fichier .php du système accessible en lecture par l’utilisateur PHP, avec les conséquences que cela suppose : exécution de code arbitraire si le fichier atteint contient du PHP interprétable.

Dans le deuxième cas, readfile() n’exécute pas de code, mais expose directement le contenu du fichier ciblé en réponse HTTP : une requête avec nom_fichier=../../../wp-config.php aurait révélé les identifiants de connexion à la base de données en clair.

L'essentiel à retenir : Ce qu'on voit : un paramètre GET utilisé tel quel dans include() ou readfile() ; Pourquoi c'est un problème : ../../../../wp-config.php devient lisible ; Quoi faire : validate_file, liste blanche et chemins absolus fixes

Quoi faire : valider avant de construire le chemin

WordPress fournit une fonction précisément conçue pour détecter les tentatives de traversée : validate_file(). Elle retourne un code différent de zéro si le chemin contient une séquence suspecte ou pointe en dehors d’une racine autorisée :

$template = $_GET['template'] ?? 'defaut';

if ( validate_file( $template ) !== 0 ) {
    wp_die( __( 'Paramètre invalide.', 'mon-extension' ) );
}

$chemin = plugin_dir_path( __FILE__ ) . 'templates/' . $template . '.php';

if ( ! file_exists( $chemin ) ) {
    wp_die( __( 'Template introuvable.', 'mon-extension' ) );
}

include $chemin;

Pour le cas de l’export de journal, une liste blanche explicite des fichiers autorisés reste la solution la plus sûre, plus robuste qu’une simple validation de format :

$fichiers_autorises = array( 'acces.log', 'erreurs.log', 'audit.log' );
$fichier = $_POST['nom_fichier'] ?? '';

if ( ! in_array( $fichier, $fichiers_autorises, true ) ) {
    wp_die( __( 'Fichier non autorisé.', 'mon-extension' ) );
}

readfile( '/var/www/exemple/logs/' . $fichier );

Le troisième cas : un correctif à ne pas négliger

Le troisième cas suivait exactement le même schéma que le premier, dans une fonctionnalité distincte de sélection de feuille de style. Sa présence répétée dans la même extension illustre un point important : une faille de ce type est rarement isolée une fois qu’un développeur reproduit un modèle de code sans en connaître le risque sous-jacent. Un correctif ponctuel sans recherche systématique dans le reste du code laisse les autres occurrences intactes.

  • Rechercher systématiquement include, require, readfile et file_get_contents combinés à une variable issue de $_GET, $_POST ou $_REQUEST.
  • Préférer une liste blanche fermée de valeurs possibles à une simple validation de format quand le nombre de cas légitimes est limité et connu à l’avance.
  • Ne jamais faire confiance à l’absence apparente de ../ dans la valeur brute : certains encodages d’URL ou variations d’encodage peuvent la dissimuler avant décodage.

Un chemin de fichier construit à partir d’une entrée utilisateur doit toujours être vérifié après construction, jamais seulement avant.

En résumé

Le path traversal reste une classe de vulnérabilité simple à comprendre mais facile à introduire dès qu’un paramètre utilisateur intervient dans la construction d’un chemin de fichier. validate_file() et les listes blanches explicites forment les deux réflexes de correction les plus fiables, et une recherche systématique dans le reste du code évite de laisser des occurrences jumelles non corrigées.

Partager :

À propos de l'auteur

Clément Hadrot

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi