TL;DR - la solution (dont vous n'avez peut-être même pas besoin) est TRÈS SIMPLE et se trouve à la fin de cette réponse.
Je vais essayer de répondre à vos questions spécifiques, mais votre mauvaise compréhension de ce qu'est PATH_INFO rend les questions elles-mêmes un peu fausses.
-
La première question à se poser est la suivante : "Quelle est cette entreprise d'information sur les chemins ?"
-
Votre prochaine question aurait dû être : "Comment PHP détermine-t-il PATH_INFO
y SCRIPT_FILENAME
sont ?"
- Les versions antérieures de PHP étaient naïves et ne supportaient même pas techniquement
PATH_INFO
donc ce qui était censé être PATH_INFO
a été transformé en SCRIPT_FILENAME
qui, oui, est cassé dans de nombreux cas. Je n'ai pas une version assez ancienne de PHP pour la tester, mais je pense qu'elle a vu SCRIPT_FILENAME
comme tout le tralala : "/path/to/script.php/THIS/IS/PATH/INFO" dans l'exemple ci-dessus (préfixé avec le docroot comme d'habitude).
- Avec l'activation de cgi.fix_pathinfo, PHP trouve maintenant correctement "/THIS/IS/PATH/INFO" pour l'exemple ci-dessus et le place dans le fichier
PATH_INFO
y SCRIPT_FILENAME
récupère juste la partie qui pointe vers le script demandé (préfixé avec le docroot bien sûr).
- Note : quand PHP a commencé à supporter
PATH_INFO
ils ont dû ajouter un paramètre de configuration pour la nouvelle fonctionnalité afin que les personnes exécutant des scripts qui dépendaient de l'ancien comportement puissent exécuter les nouvelles versions de PHP. C'est pourquoi il y a même un commutateur de configuration pour cela. Il aurait dû être intégré (avec le comportement "dangereux") dès le début.
-
Mais comment PHP sait-il quelle partie est le script et quelle est l'information sur le chemin ? Et si l'URI est quelque chose comme :
http://example.com/path/to/script.php/THIS/IS/PATH/INFO.php?q=foo
- Cela peut être une question complexe dans certains environnements. Ce qui se passe en PHP, c'est qu'il trouve la première partie du chemin de l'URI qui ne correspond à rien dans le docroot du serveur. Dans cet exemple, il voit que sur votre serveur vous n'avez pas "/docroot/path/to/script.php/THIS" mais que vous avez certainement "/docroot/path/to/script.php".
SCRIPT_FILENAME
a été déterminé et PATH_INFO
obtient le reste.
- Voici maintenant le bon exemple du danger qui est joliment détaillé dans la documentation de Nginx et dans La réponse de Hrvoje Špoljar (on ne peut pas être pointilleux sur un exemple aussi clair) devient encore plus clair : étant donné l'exemple de Hrvoje (" http://example.com/foo.jpg/nonexistent.php "), PHP voit un fichier sur votre docroot "/foo.jpg" mais il ne voit rien appelé "/foo.jpg/nonexistent.php" donc
SCRIPT_FILENAME
obtient "/foo.jpg" (encore une fois, préfixé avec docroot) et PATH_INFO
obtient "/nonexistent.php".
-
Le pourquoi et le comment de ce danger devraient maintenant être clairs :
- Le serveur web n'est pas vraiment en faute - il transmet simplement l'URI à PHP, qui trouve innocemment que "foo.jpg" contient en fait du contenu PHP, et l'exécute (vous êtes maintenant punis !). Ceci est PAS particulier à Nginx en soi.
-
En REAL Le problème est que vous laissez du contenu non fiable être téléchargé quelque part sans le nettoyer et vous autorisez d'autres requêtes arbitraires au même endroit, que PHP exécute joyeusement quand il le peut.
-
Nginx et Apache pourraient être construits ou configurés pour empêcher les requêtes utilisant cette astuce, et il y a beaucoup d'exemples sur la façon de le faire, y compris dans le document suivant La réponse de l'utilisateur2372674 . Cet article de blog explique bien le problème, mais il manque la bonne solution.
-
Cependant, la meilleure solution est de s'assurer que PHP-FPM est configuré correctement afin qu'il n'exécute jamais un fichier à moins qu'il ne se termine par ".php". Il est à noter que les versions récentes de PHP-FPM (~5.3.9+ ?) ont cette configuration par défaut, donc ce danger n'est plus un problème.
La solution
Si vous avez une version récente de PHP-FPM (~5.3.9+ ?), alors vous n'avez rien à faire, car le comportement sûr ci-dessous est déjà par défaut.
Sinon, trouvez le fichier de php-fpm www.conf
(peut-être /etc/php-fpm.d/www.conf
(cela dépend de votre système). Assurez-vous que vous avez ceci :
security.limit_extensions = .php
Encore une fois, c'est le défaut dans de nombreux endroits de nos jours.
Notez que cela n'empêche pas un attaquant de télécharger un fichier ".php" dans un dossier de téléchargement de WordPress et de l'exécuter en utilisant la même technique. Vous devez toujours assurer une bonne sécurité pour vos applications.