FlawOpen

flawopen.com/Inclusion de fichiers/PHP include()

include() de PHP est-il sûr avec des données utilisateur ?

CWE-98: PHP Remote File InclusionPage de référence
Réponse courte

Non. include() analyse le fichier choisi comme du PHP, mais l’impact dépend du fichier atteint et de son contenu. Une faille peut révéler du code source via un wrapper, inclure un fichier local inattendu ou exécuter du PHP contrôlé par un attaquant seulement s’il peut fournir du contenu balisé PHP que l’application inclut. L’inclusion d’une URL distante dépend aussi de la configuration PHP. Associez une clé choisie par l’utilisateur à une liste fixe ; ne construisez jamais le chemin include depuis la requête.

VULNÉRABLE
<?php
// User-controlled path: unintended local file
include $_GET['page'] . '.php';

// Example selector: ../../private/sample
// Impact depends on the resolved file and
// whether it contains PHP code to interpret.

// Remote URL inclusion requires the relevant
// URL wrapper and allow_url_include setting.

// Wrappers can change which resource is read;
// php://filter is a read filter, not a path
// containment check.
CORRIGÉ
<?php
// Allowlist: input selects a KEY,
// never a path or wrapper.
$pages = [
    'home'    => __DIR__ . '/pages/home.php',
    'about'   => __DIR__ . '/pages/about.php',
    'contact' => __DIR__ . '/pages/contact.php',
];

$key = $_GET['page'] ?? 'home';

if (!is_string($key) || !array_key_exists($key, $pages)) {
    http_response_code(404);
    exit;
}

include $pages[$key];

Pourquoi une inclusion locale ne signifie pas automatiquement exécution de code

Une inclusion locale n’exécute pas automatiquement du code. PHP analyse le fichier inclus : les instructions entre balises PHP valides s’exécutent dans le contexte appelant, tandis que les autres octets peuvent être envoyés en sortie. L’exécution exige un fichier accessible contenant du PHP contrôlé par l’attaquant ou un autre comportement exploitable. Une faille d’envoi de fichier ou d’écriture de journal peut former une chaîne si elle place du contenu PHP contrôlé dans un fichier ensuite inclus.

Par ailleurs, php://filter applique un filtre à l’ouverture d’un flux. Dans un flux de lecture ou d’inclusion vulnérable, un filtre adapté peut révéler du texte source sans l’exécuter ; l’accès dépend du wrapper, des permissions et de la configuration.

Pourquoi nettoyer le chemin ne suffit pas

Retirer ../, ajouter une extension fixe ou préfixer un répertoire ne garantit pas que la ressource finale soit autorisée. Encodages, chemins absolus, règles de la plateforme et wrappers peuvent modifier l’interprétation. Supprimez le contrôle utilisateur de la ressource : autorisez uniquement des clés d’une liste fixe définie par l’application.

Si vous devez résoudre un chemin, canonisez-le avec realpath() et vérifiez qu’il reste dans le répertoire, comme dans le guide Path Traversal. Limitez le résultat aux fichiers approuvés et tenez compte des symlinks et des courses entre contrôle et utilisation. Une liste de cibles fixes est plus sûre.

Questions fréquentes

allow_url_include=Off suffit-il ?

Cette option désactive les wrappers URL pour include/require. PHP indique qu’elle est désactivée par défaut et obsolète depuis PHP 7.4. Elle réduit l’exposition au RFI, mais n’empêche ni le traversal local ni les inclusions locales risquées. Gardez-la désactivée et supprimez le contrôle utilisateur de la cible.

La technique de l’octet nul fonctionne-t-elle encore ?

PHP 5.3.4 a corrigé la terminaison par octet nul dans les chemins. Ne comptez pas sur l’absence de cette ancienne technique : une cible include non fiable reste dangereuse.

Et require, include_once et readfile ?

require et les variantes _once incluent aussi la cible et l’analysent ; leurs comportements d’échec et de répétition diffèrent, mais ne sécurisent pas une cible non fiable. readfile() et file_get_contents() renvoient des données sans les analyser comme PHP ; un chemin non fiable peut causer traversal ou divulgation, pas une exécution par include.

Références

À voir aussi Traversée de répertoires (CWE-22) : fonctionnement et prévention dans tous les langages — flawopen.com Corriger le path traversal avec Python os.path.join() Qu’est-ce qu’une vulnérabilité Zip Slip ? Node.js path.join() ne bloque pas Path Traversal