TL; DR - исправление (которое вам может даже не понадобиться) ОЧЕНЬ ПРОСТО и в конце этого ответа.
Я постараюсь ответить на ваши конкретные вопросы, но ваше неправильное понимание того, что такое PATH_INFO, делает вопросы немного неправильными.
Первый вопрос должен быть «Что это за бизнес информация о пути?»
Ваш следующий вопрос должен был звучать так: «Как PHP определяет, что PATH_INFO
и SCRIPT_FILENAME
как?»
- Более ранние версии PHP были наивны и технически даже не поддерживались
PATH_INFO
, поэтому то, что предполагалось, PATH_INFO
было спрятано SCRIPT_FILENAME
, а во многих случаях оно нарушалось . У меня нет достаточно старой версии PHP для тестирования, но я полагаю, что она SCRIPT_FILENAME
выглядела так: «/path/to/script.php/THIS/IS/PATH/INFO» в приведенном выше примере (с префиксом докрут как обычно).
- С включенной cgi.fix_pathinfo, PHP теперь правильно находит «/ THIS / IS / PATH / INFO» для приведенного выше примера и помещает его в
PATH_INFO
и SCRIPT_FILENAME
получает только ту часть, которая указывает на запрашиваемый скрипт (разумеется, с префиксом docroot).
- Примечание: когда PHP получил поддержку
PATH_INFO
, им пришлось добавить параметр конфигурации для новой функции, чтобы люди, запускающие сценарии, которые зависели от старого поведения, могли запускать новые версии PHP. Вот почему есть даже переключатель конфигурации для него. Он должен был быть встроенным (с «опасным» поведением) с самого начала.
Но как PHP знает, какая часть скрипта и какая информация о пути к нему? Что делать, если URI что-то вроде:
http://example.com/path/to/script.php/THIS/IS/PATH/INFO.php?q=foo
- Это может быть сложным вопросом в некоторых условиях. Что происходит в PHP, так это то, что он находит первую часть пути URI, которая не соответствует ничему в docroot сервера. В этом примере он видит, что на вашем сервере у вас нет «/docroot/path/to/script.php/THIS», но у вас наверняка есть «/docroot/path/to/script.php», так что теперь
SCRIPT_FILENAME
был определен и PATH_INFO
получает остальное.
- Так что теперь хороший пример опасности, который подробно описан в документах Nginx и в ответе Хрвого Шполяра (вы не можете суетиться по поводу такого ясного примера), становится еще более ясным: на примере Хрвого (пример http: //). com / foo.jpg / nonexistent.php "), PHP видит файл в вашем docroot" /foo.jpg ", но не видит ничего с именем" /foo.jpg/nonexistent.php ", поэтому
SCRIPT_FILENAME
получает" /foo.jpg " (опять же с префиксом docroot) и PATH_INFO
получает "/nonexistent.php".
Почему и как это может быть опасно, теперь должно быть понятно:
- Веб-сервер на самом деле не виноват - он просто передает URI в PHP, который невинно обнаруживает, что «foo.jpg» фактически содержит контент PHP, поэтому он выполняет его (теперь вы pwned!). Это НЕ частности, Nginx таковой.
- РЕАЛЬНАЯ проблема заключается в том , что вы позволяете ненадежное содержимое будет загружено где - то без дезинфицирующего и вы позволяете другим произвольные запросы в том же месте, что PHP счастливо выполняет , когда это возможно.
Nginx и Apache могут быть построены или настроены для предотвращения запросов, использующих эту хитрость, и существует множество примеров того, как это сделать, в том числе в ответе пользователя user2372674 . Эта статья блога хорошо объясняет проблему, но в ней отсутствует правильное решение.
Тем не менее, лучшим решением будет просто убедиться, что PHP-FPM настроен правильно, чтобы он никогда не выполнял файл, если он не заканчивается на «.php». Стоит отметить, что в последних версиях PHP-FPM (~ 5.3.9 +?) Это по умолчанию, так что эта опасность больше не является проблемой.
Решение
Если у вас последняя версия PHP-FPM (~ 5.3.9 +?), То вам ничего не нужно делать, поскольку приведенное ниже безопасное поведение уже используется по умолчанию.
В противном случае найдите www.conf
файл php-fpm (возможно /etc/php-fpm.d/www.conf
, зависит от вашей системы). Убедитесь, что у вас есть это:
security.limit_extensions = .php
Опять же, это по умолчанию во многих местах в эти дни.
Обратите внимание, что это не мешает злоумышленнику загрузить файл «.php» в папку загрузки WordPress и выполнить его, используя ту же технику. Вы все еще должны иметь хорошую безопасность для своих приложений.