Je ne décrirais pas ce changement comme « critique » en soi, mais il a toujours des implications en matière de sécurité. Je ne suis pas au courant de quoi que ce soit qui ait fondamentalement changé depuis que ce conseil est devenu pertinent - le comportement de PHP tend fortement vers la rétrocompatibilité, même lorsque cela a des implications en matière de sécurité. Imaginez que vous avez un serveur qui permet aux gens de télécharger des fichiers sur le serveur, par exemple dans un répertoire appelé upload
. Maintenant, votre script de téléchargement prend soin de n'autoriser que les fichiers avec certaines extensions (disons uniquement .png
) pour s'assurer que personne ne télécharge un fichier PHP malveillant.
Maintenant, en tant qu'attaquant, je vais essayer d'écrire un shell PHP dans un fichier, nommez le fichier evil.png
, et téléchargez-le. Lorsqu'il sera téléchargé, je visiterai http://example.com/upload/evil.png
, mais je découvrirai que cela me télécharge simplement le fichier - nginx n'a jamais envoyé la demande à php-fcgi pour qu'elle soit traitée comme php, car le nom du fichier se termine par .png
.
Si je suis un attaquant au courant de PATH_INFO
, ensuite j'essaierai http://example.com/upload/evil.png/index.php
. Si votre serveur est ainsi configuré, cela entraînera l'exécution de PHP (car nginx voit le index.php
à la fin) et PHP suivra le chemin jusqu'à ce qu'il trouve un composant qui est un fichier, pas un répertoire (evil.png
) et essayez de l'exécuter. Ensuite, mon shell est exécuté et je gagne.
Cela étant dit, il existe de meilleures façons de gérer cela en faisant en sorte que la configuration NGINX divise le chemin à l'avance, afin que PHP ne parcoure pas le système de fichiers.
Extrait de l'excellent article de blog de Neal Poole sur la question :
# Pass all .php files onto a php-fpm/php-fcgi server.
location ~ \.php$ {
# Zero-day exploit defense.
# http://forum.nginx.org/read.php?2,88845,page=3
# Won't work properly (404 error) if the file is not stored on this server, which is entirely possible with php-fpm/php-fcgi.
# Comment the 'try_files' line out if you set up php-fpm/php-fcgi on another machine. And then cross your fingers that you won't get hacked.
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass php;
}
Même maintenant, cela semble présenter un danger en raison de la façon dont PHP traite toujours le script à partir de la première occurrence du fichier trouvé. Alors pourquoi ont-ils gardé la valeur par défaut en tant que ;cgi.fix_pathinfo=1
alors ?
Parce que CGI est indépendant de PHP et possède son propre standard. CGI (Common Gateway Interface) est une interface qui indique au serveur comment communiquer des données avec des applications, comment les informations et le corps de la requête sont transmis, de l'entrée à la sortie. Les serveurs du Web peuvent être configurés pour exécuter un programme en tant que CGI
, ce qui signifie qu'ils transmettront les données de la demande à un programme spécifique. Et c'est ainsi que NGinx transmet la requête à PHP.
En parlant de norme CGI , PHP-FPM
les développeurs doivent se conformer à la norme CGI comme ils l'ont indiqué dans le PHP-FPM
fichier ini ex :/etc/php/7.2/fpm/php.ini
:
; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI. PHP's
; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok
; what PATH_INFO is. For more information on PATH_INFO, see the cgi specs. Setting
; this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting
; of zero causes PHP to behave as before. Default is 1. You should fix your scripts
; to use SCRIPT_FILENAME rather than PATH_TRANSLATED.
; http://php.net/cgi.fix-pathinfo
;cgi.fix_pathinfo=1
Donc je suppose que le texte Setting this to 1 will cause PHP CGI to fix its paths to conform to the spec. A setting of zero causes PHP to behave as before.
explique le choix. Voici le PATH_INFO
Spécification CGI.