Учебник РНР
НазадГлава 4. Безопасность Вперёд

CGI-двоичный

Возможные атаки

Использование PHP как двоичного CGI это опция установки, когда, по некоторым соображениям, нет желания интегрировать PHP как модуль в программу-сервер (такую как Apache) или когда PHP будет использоваться с различными видами CGI-оболочек для создания для скриптов безопасной среды chroot и setuid. Такая инсталяция обычно заключается в установке исполняемого файла PHP в директорию cgi-bin web-сервера. CERT advisory CA-96.11 рекомендует не помещать никакие интерпретаторы в директорию cgi-bin. Даже если исполняемый файл PHP используется как самостоятельный интерпретатор, PHP разработан таким образом, чтобы предотвратить атаки при таком варианте установки:

  • Доступ к системным файлам: http://my.host/cgi-bin/php?/etc/passwd

    Информация запроса в url после знака вопроса (?) передаётся интерпретатору как аргументы командной строки CGI-интерфейсом. Обычно интерпретаторы открывают и выполняют файл, специфицированный как первый аргумент командной строки.

    При вызове как исполняемый CGI, PHP не выполняет аргументы командной строки.

  • Доступ к любому web-документу на сервере: http://my.host/cgi-bin/php/secret/doc.html

    Информация пути/path в url после имени PHP-экзешника, /secret/doc.html, используется по соглашению для специфицирования имени файла, открываемого и исполняемого CGI -программой. Обычно некоторые директивы конфигурации web-сервера (Apache: Action) используются для перенаправления запросов документа, например, http://my.host/secret/script.php, интерпретатору PHP. При такой установке web-сервер сначала проверяет права доступа к директории /secret, а затем создаёт перенаправленный запрос http://my.host/cgi-bin/php/secret/script.php.
    К сожалению, если запрос в оригинале задан в этой форме, проверка доступа к файлу /secret/script.php web-сервером не выполняется, и он делает её только для файла /cgi-bin/php. Этим способом любой пользователь может получить доступ к /cgi-bin/php и к любому защищённому документу на web-сервере.

    В PHP опция конфигурации времени компиляции --enable-force-cgi-redirect и директивы времени выполнения doc_root и user_dir могут использоваться для предотвращения таких нападений, если дерево документов сервера содержит директории с ограниченным доступом. См. далее рассмотрение различных комбинаций.

Вариант 1: обслуживаются только public-файлы

Если на вашем сервере нет содержимого, доступ к которому ограничен паролем или ip, то нет необходимости в применении этих опций конфигурации.
Если ваш web-сервер не разрешает выполнять перенаправление или если он не имеет способа такого взаимодействия с исполняемым PHP, чтобы запрос был безопасным, вы можете специфицировать опцию --enable-force-cgi-redirect для конфигурирования скрипта. Вы также должны гарантировать, что ваши PHP-скрипты не основываются на каком-либо другом способе вызова скриптов: ни на прямом http://my.host/cgi-bin/php/dir/script.php, ни на перенаправлении http://my.host/dir/script.php.

Перенаправление может быть сконфигурировано в Apache через использование директив AddHandler и Action (см. ниже).

Вариант 2: использование --enable-force-cgi-redirect

Эта опция времени компиляции предотвращает вызов PHP кем бы то ни было прямо в url, например, http://my.host/cgi-bin/php/secretdir/script.php. Вместо этого PHP будет разбирать в этом режиме только в том случае, если пройдено правило перенаправления web-сервера.

Обычно перенаправление в конфигурации Apache выполняется следующими директивами:

Action php-script /cgi-bin/php
AddHandler php-script .php

Эта опция была проверена только на сервере Apache и основывается на установке Apache нестандартной переменной окружения CGI REDIRECT_STATUS для перенаправленных запросов. Если ваш web-сервер не поддерживает способ сообщения того, является ли запрос перенаправляемым или прямым, вы не можете использовать эту опцию и обязаны использовать один из других вариантов запуска CGI-версии из указанных здесь.

Вариант 3: установка doc_root или user_dir

Включение активного содержимого, такого как скрипты и исполняемые файлы, в директорию документов web-сервера считается небезопасным. Если они, из-за какой-нибудь ошибки конфигурации, не исполняются, а выводятся как обычные HTML-документы, это может привести к потере интеллектуальной собственности или закрытой информации вроде паролей. Поэтому многие sysadmins предпочитают устанавливать другую структуру директорий для скриптов, когда они доступны только для PHP CGI и, следовательно, всегда интерпретируются и не выводятся как текст.

Также, если невозможно гарантировать, что запросы не перенаправляются, как указано в предыдущем разделе, необходимо установить doc_root скриптов, которая отличается от web document root.

Вы можете установить корневую директорию скриптов PHP директивой конфигурации doc_root в файле конфигурации или можете установить переменную окружения PHP_DOCUMENT_ROOT. Если она установлена, CGI-версия PHP всегда будет конструировать имя открываемого файла с применением doc_root и информации пути к файлу из запроса, поэтому вы можете быть уверены, что никакие скрипты не будут исполняться вне этой директории (за исключением user_dir ниже её).

Другая используемая здесь опция - user_dir. Когда user_dir не установлена/unset, единственное, что контролирует имя открываемого файла, это doc_root. Открытие url вроде http://my.host/~user/doc.php приводит к открытию не файла под home-директорией пользователя, а файла, вызываемого ~user/doc.php под doc_root (да, директории с именем, начинающимся с тильды [~]).

Если user_dir установлена для, например, public_php, запрос вроде http://my.host/~user/doc.php откроет файл doc.php под директорией public_php ниже home-директории пользователя. Если home пользователя это /home/user, выполняется файл /home/user/public_php/doc.php.

Расширение user_dir происходит независимо от установки doc_root, поэтому вы можете контролировать доступ к директории document root и пользовательской директории независимо друг от друга.

Вариант 4: разборщик PHP вне дерева web

Очень надёжной опцией является помещение исполняемого файла разборщика PHP где-нибудь вне дерева файлов web. В /usr/local/bin, например. Единственным недостатком этой опции является то, что вы теперь должны помещать строку вроде следующей:

#!/usr/local/bin/php

как первую строку любого файла, содержащего тэги PHP. Вы также должны сделать файл исполняемым. То есть рассматривать его так же, как любой другой CGI-скрипт, написанный на Perl или sh или любом другом языке скриптинга, который использует механизм замены #! оболочки для запуска самого себя.

Чтобы PHP корректно обрабатывал информацию PATH_INFO и PATH_TRANSLATED при такой установке, разборщик РНР должен быть скомпилирован с опцией конфигурации --enable-discard-path.


НазадОглавление Вперёд
Безопасность ВверхApache-модуль