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
додає його до та отримує лише ту частину, яка вказує на запит скрипта (з префіксом звичайно докрокота).
- Примітка: коли PHP обійшов фактичну підтримку
PATH_INFO
, їм довелося додати налаштування конфігурації для нової функції, щоб люди, що виконують сценарії, які залежать від старої поведінки, могли запускати нові версії PHP. Ось чому для нього навіть є перемикач конфігурації. Він повинен був бути вбудованим (з "небезпечною" поведінкою) з самого початку.
Але як PHP знає, яка частина скрипту та яка інформація про нього? Що робити, якщо URI щось таке:
http://example.com/path/to/script.php/THIS/IS/PATH/INFO.php?q=foo
- Це може бути складним питанням у деяких середовищах. Що відбувається в PHP, це те, що він знаходить першу частину шляху URI, яка не відповідає нічого під докроотводом сервера. У цьому прикладі видно, що на вашому сервері у вас немає "/docroot/path/to/script.php/THIS", але у вас, безумовно, є "/docroot/path/to/script.php", тож
SCRIPT_FILENAME
був визначений і PATH_INFO
отримує решту.
- Тож тепер хороший приклад небезпеки, який добре описаний у документах Nginx та у відповіді Хрвіо Шполяра (ти не можеш метушитися з такого чіткого прикладу), стає ще більш зрозумілим: з огляду на приклад Хрвоя (" http: // example." com / foo.jpg / noexistent.php "), PHP бачить файл на вашій docroot" /foo.jpg ", але він не бачить нічого з назвою" /foo.jpg/nonexistent.php "так
SCRIPT_FILENAME
отримує" /foo.jpg " (знову ж, з префіксом docroot) і PATH_INFO
отримує "/noexistent.php".
Чому і як це може бути небезпечно, тепер має бути зрозуміло:
- Веб-сервер насправді не винен - це просто наближення URI до PHP, який невинно виявляє, що "foo.jpg" насправді містить вміст PHP, тому він виконує його (тепер ви вже були виконані!). Це НЕ особливо для 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 і виконувати його за допомогою тієї ж методики. Ви все ще повинні мати хороший захист своїх програм.