Если PHP установлен как CGIВозможные атаки
Использование PHP как бинарного CGI-приложения
является одним из вариантов, когда по каким-либо причинам нежелательно
интегрировать PHP в веб-сервер (например, Apache) в качестве модуля,
либо предполагается использование различных CGI-обёрток
и таких утилит, как chroot и setuid для организации безопасного
окружения работы скриптов.
Такая установка обычно сопровождается копированием исполняемого
файла PHP в директорию cgi-bin веб-сервера. CERT (организация,
следящая за угрозами безопасности)
CA-96.11 рекомендует не помещать
какие-либо интерпретаторы в каталог cgi-bin. Даже если PHP используется
как самостоятельный интерпретатор, он спроектирован так, чтобы предотвратить
возможность следующих атак:
Доступ к системным файлам: http://my.host/cgi-bin/php?/etc/passwd
Данные, введённые в строке запроса (URL) после вопросительного знака,
передаются интерпретатору как аргументы командной строки с помощью
интерфейса CGI. Обычно интерпретаторы открывают
и исполняют файл, указанный в качестве первого аргумента.
В случае использования PHP в качестве CGI-приложения он не
станет интерпретировать аргументы командной строки.
Доступ к произвольному документу на сервере:
http://my.host/cgi-bin/php/secret/doc.html
Согласно общепринятому соглашению, часть пути в запрошенной
странице, которая расположена после имени выполняемого модуля
PHP, /secret/doc.html,
используется для указания файла, который будет интерпретирован
CGI-программой. Обычно, некоторые конфигурационные
опции веб-сервера (например, Action для сервера Apache) используются
для перенаправления документа, к примеру, для перенаправления запросов
вида http://my.host/secret/script.php интерпретатору PHP.
В таком случае веб-сервер сначала проверяет права доступа к
директории /secret, и после этого
создаёт перенаправленный запрос http://my.host/cgi-bin/php/secret/script.php.
К сожалению, если запрос изначально задан в полном виде,
проверка на наличие прав для файла /secret/script.php не выполняется, она
происходит только для файла /cgi-bin/php.
Таким образом, пользователь имеет возможность обратиться к
/cgi-bin/php,
и, как следствие, к любому защищённому документу на сервере.
Если в PHP указать во время исполнения скрипта опции cgi.force_redirect, doc_root и user_dir, то можно предотвратить
подобные атаки для директорий с ограниченным доступом.
Более детально приведённые опции, а также их комбинации будут рассмотрены ниже.
Вариант 1: обслуживаются только общедоступные файлы
В случае, если на вашем сервере отсутствуют файлы, доступ к
которым ограничен паролем либо фильтром по IP-адресам, нет
никакой необходимости использовать данные опции.
Если ваш веб-сервер не разрешает выполнять перенаправления,
либо не имеет возможности взаимодействовать с исполняемым
PHP-модулем на необходимом уровне безопасности, вы можете
включить ini-директиву cgi.force_redirect.
Но при этом вы всё ещё должны убедиться, что
альтернативные способы вызова скрипта, такие как непосредственный
вызов http://my.host/cgi-bin/php/dir/script.php
либо с переадресацией http://my.host/dir/script.php, недоступны.
В веб-сервере Apache перенаправление может быть сконфигурировано
при помощи директив AddHandler и Action (описано ниже).
Вариант 2: использование cgi.force_redirect
Конфигурационная директива cgi.force_redirect
предотвращает попытки непосредственного вызова PHP по адресу
вида http://my.host/cgi-bin/php/secretdir/script.php.
Вместо этого PHP будет обрабатывать пришедший запрос только в том случае,
если он был перенаправлен веб-сервером.
Обычно перенаправление в конфигурации Apache настраивается при помощи
следующих опций:
Эта опция проверена только с веб-сервером Apache, её работа основывается
на установке в случае перенаправления нестандартной переменной
REDIRECT_STATUS, находящейся в CGI-окружении.
В случае, если ваш веб-сервер не предоставляет возможности
однозначно идентифицировать, является ли данный запрос
перенаправленным, вы не можете использовать описываемую в
данном разделе опцию и должны воспользоваться любым другим
методом работы с CGI-приложениями.
Вариант 3: использование опций doc_root или user_dir
Размещение динамического контента, такого как скрипты или любых
других исполняемых файлов, в директории веб-сервера делает его
потенциально опасным. В случае, если в конфигурации сервера допущена
ошибка, возможна ситуация, когда скрипты не выполняются, а отображаются
в браузере, как обычные HTML-документы, что может привести к утечке конфиденциальной
информации (например, паролей), либо информации, являющейся
интеллектуальной собственностью. Исходя из таких соображений, многие
системные администраторы предпочитают использовать для хранения скриптов
отдельную директорию, работая со всеми размещёнными в ней файлами
по CGI-интерфейсу.
В случае, если невозможно гарантировать, что запросы не перенаправляются,
как было показано в предыдущем разделе, необходимо указывать
переменную doc_root, которая отличается от корневой директории веб-документов.
Вы можете установить корневую директорию для PHP-скриптов, настроив
параметр doc_root в
конфигурационном файле,
либо установив переменную окружения PHP_DOCUMENT_ROOT.
В случае, если PHP используется посредством CGI,
полный путь к открываемому файлу будет построен на основании
значения переменной doc_root и указанного
в запросе пути. Таким образом, вы можете быть уверены,
что скрипты будут выполняться только внутри указанной вами директории
(кроме директории user_dir, которая описана ниже).
Ещё одна используемая при настройке безопасности опция -
user_dir. В случае, если
переменная user_dir не установлена, путь к открываемому файлу
строится относительно doc_root. Запрос
вида http://my.host/~user/doc.php
приводит к выполнению скрипта, находящегося не в домашнем каталоге
соответствующего пользователя, а находящегося в подкаталоге doc_root
скрипта ~user/doc.php (да, имя
директории начинается с символа ~).
Но если user_dir установлена, например, в значение
public_php, то запрос вида
http://my.host/~user/doc.php
откроет файл doc.php, находящийся в
домашнем каталоге пользователя, в директории public_php.
Например, если домашний каталог пользователя /home/user,
будет выполнен файл /home/user/public_php/doc.php.
Установка опции user_dir происходит
независимо от установки doc_root,
таким образом вы можете контролировать корневую директорию веб-сервера
и пользовательские директории независимо друг от друга.
Вариант 4: PHP вне дерева веб-документов
Один из способов существенно повысить уровень безопасности - поместить
исполняемый модуль PHP вне дерева веб-документов, например в /usr/local/bin. Единственным недостатком такого подхода
является то, что первая строка каждого скрипта должна иметь вид:
Также необходимо сделать все файлы скриптов исполняемыми. Таким образом,
скрипт будет рассматриваться так же, как и любое другое CGI-приложение,
написанное на Perl, sh или любом другом скриптовом языке, который использует
#! в начале файла для запуска самого себя.
Для корректной обработки PHP переменных
PATH_INFO и PATH_TRANSLATED
директива ini cgi.discard_path должна быть включена.