Cette page a été traduite par la communauté et n'est pas forcément à jour. Consultez la version de référence (en anglais).
Cette page a été traduite par la communauté et n'est pas forcément à jour. Consultez la version de référence (en anglais).
Cette page a été traduite par la communauté et n'est pas forcément à jour. Consultez la version de référence (en anglais).
Ce document décrit le modèle de confiance de FrankenPHP : quelles sont les entrées fiables, quelles ne le sont pas, et où se situe la limite entre elles. Il est destiné à aider les audits de sécurité et les scanners automatisés à raisonner sur FrankenPHP lui-même, et non sur les applications PHP qu’il sert.
Pour les mécanismes internes référencés ici (threads, la limite CGO, le sandboxing d’environnement), voir Fonctionnement interne. Pour la persistance d’état dans les processus de longue durée, voir Mode Travailleur.
FrankenPHP s’exécute dans une pile avec quatre acteurs distincts :
| Acteur | Confiance | Notes |
|---|---|---|
| Client distant | Non fiable | La requête HTTP (méthode, URI, en-têtes, cookies, corps, uploads) est la principale source d’entrée contaminée. |
| Opérateur | Fiable | Fournit la configuration de déploiement : le Caddyfile, les variables d’environnement, php.ini, les extensions PHP et modules Caddy installés, et le code de l’application lui-même. |
| Code d’application PHP | Fiable par provenance | Déployé par l’opérateur, donc FrankenPHP n’exécute jamais de code fourni par un attaquant, mais ce code consomme des données de requête non fiables. |
| FrankenPHP (Go + C) | Base de calcul fiable | Intègre PHP, transporte les données entrantes et sortantes, et isole les requêtes et les threads. Ce document couvre ses propres défauts. |
C’est la distinction la plus importante, et celle qui résout la plupart des confusions “faut-il faire confiance à PHP ou non ?” :
$_GET, $_POST, $_COOKIE, $_FILES, $_SERVER, php://input) est non fiable, exactement comme dans toute SAPI PHP. La désinfection de ces données est le travail de l’application.Ainsi, “nous faisons confiance à ce qui vient de PHP” est vrai pour le code, tandis que “la SAPI transporte des entrées non fiables” est vrai pour les données : les deux ne sont pas en conflit. Le rôle de FrankenPHP est de transporter fidèlement ces données contaminées et d’empêcher les données d’une requête de fuir vers une autre.
La base de calcul fiable a trois tâches. Les défauts de sécurité dans FrankenPHP se situent dans l’une d’entre elles :
php://input, et transporter la sortie et les en-têtes de PHP vers le client, sans introduire d’injection (injection d’en-tête/CRLF, contrebande de requête, exécution du mauvais fichier).Voici les surfaces que FrankenPHP gère. Une vulnérabilité ici est une vulnérabilité de FrankenPHP :
cgi.go, frankenphp_register_server_vars) : construction de $_SERVER, REMOTE_ADDR, SCRIPT_NAME, PATH_INFO et des autres variables CGI à partir de la requête.split_path (.php par défaut) en SCRIPT_NAME / PATH_INFO, puis joint à la racine du document avec sanitizedPathJoin (filepath.Join(root, filepath.Clean("/"+reqPath))), ce qui empêche SCRIPT_FILENAME de s’échapper de la racine du document (traversée de chemin). La directive php_server définit en outre une réécriture try_files par défaut qui achemine les requêtes vers les fichiers existants ou le contrôleur frontal, atténuant ainsi le piège classique de PHP-FPM d’exécuter le mauvais fichier.$_GET, $_POST, $_COOKIE, $_FILES, $_SERVER et $_REQUEST entre les requêtes, efface explicitement $_SESSION (qui autrement fuirait entre les requêtes) et les erreurs retournées par error_get_last() et libxml_get_errors(), ainsi que les en-têtes retournés par http_get_last_response_headers(), l’état de strtok(), et les variables ajoutées par output_add_rewrite_var(), mais $_ENV n’est pas réinitialisé, et les écritures de putenv(), les variables static, les propriétés statiques de classe, les globales et les paramètres du moteur d’exécution (ini_set(), le contexte de flux par défaut, le fuseau horaire par défaut, le répertoire de travail, …) persistent entre les requêtes sur le même thread. Les données spécifiques à la requête ou à l’utilisateur laissées dans cet état peuvent fuir vers une requête ultérieure (voir Mode Travailleur).frankenphp_putenv() / frankenphp_getenv() opèrent sur un sandboxed_env local au thread. Les écritures de putenv() restent dans ce bac à sable et n’atteignent jamais l’environnement OS global du processus, de sorte qu’un secret défini par une requête ne peut pas fuir vers les processus enfants (proc_open, exec, …), vers le côté Go/Caddy, ou vers d’autres requêtes. Un processus enfant qui doit voir une telle variable doit la recevoir explicitement, via l’argument d’environnement de proc_open() ou exec() (voir Fonctionnement interne).C.CString() / free() à travers la limite Go ↔ C./frankenphp/workers/restart et /frankenphp/threads, exposés via l’API d’administration de Caddy (qui écoute sur localhost:2019 par défaut). L’exposition de ce point de terminaison au-delà de localhost est une décision de l’opérateur.X-Forwarded-* entrants parviennent toujours à PHP en tant que valeurs $_SERVER['HTTP_X_FORWARDED_*'] contaminées ; ils ne sont fiables pour dériver l’IP et le schéma du client réel que lorsque trusted_proxies est configuré (proxies_de_confiance).delai_d_attente_du_corps_de_la_requete), réinitialisant la date limite avant chaque lecture afin qu’un téléchargement stable de toute taille réussisse tandis qu’un téléchargement bloqué est interrompu et le thread libéré.Consultez SECURITY.md pour savoir comment signaler un problème de sécurité affectant FrankenPHP.