Журнал LinuxFormat - перейти на главную

LXF102:Доверительный PHP

Материал из Linuxformat
(Различия между версиями)
Перейти к: навигация, поиск
(Права доступа и последствия)
(Викификация, оформление)
 
Строка 156: Строка 156:
  
 
Чтобы никто не вздумал разрешить выполнение ''CGI'' с использованием файлов ''PHP'' не из каталога '''/usr/local/apache2/cgi-bin''' (или любого другого, явно прописанного вами в директивах '''Directory'''), добавим
 
Чтобы никто не вздумал разрешить выполнение ''CGI'' с использованием файлов ''PHP'' не из каталога '''/usr/local/apache2/cgi-bin''' (или любого другого, явно прописанного вами в директивах '''Directory'''), добавим
 +
 +
Options -Includes -ExecCGI
 +
 +
в главный конфигурационный раздел '''httpd.conf'''.
 +
 +
Нужно также назначить каталог, содержащий ''CGI''-скрипты;
 +
это делается директивой '''SetHandler'''. Тот факт, что мы разрешаем
 +
исполнение ''CGI'' через директиву '''Options''', на вид противоречит предыдущей директиве, но вы ведь помните, что нельзя выполнять только
 +
''CGI''-скрипты, не содержащиеся в указанном ниже каталоге.
 +
 +
<Directory /usr/local/apache2/cgi-bin>
 +
Options +ExecCGI
 +
SetHandler cgi-script
 +
</Directory>
 +
 +
Сперва, однако, не мешает предупредить ''Apache'', с какими файлами следует обращаться как со сценариями ''PHP''. Итак, в главном
 +
файле конфигурации говорим ''Apache'', что мы используем скрипты
 +
''CGI'' – это мы уже сделали, осталось сообщить, что мы используем
 +
файлы ''PHP'':
 +
 +
AddHandler application/x-httpd-php .php
 +
 +
Вы можете добавить другие обработчики-handler’ы и, если захотите, новые расширения файлов, например, ''php3'' или ''php5'', но это на
 +
ваше усмотрение. Здесь приведен фрагмент '''httpd.conf''': понадобится
 +
еще несколько директив, чтобы наш '''httpd.conf''' заработал, но советую
 +
добавить предыдущие директивы, в соответствии с нашими рекомендациями. Я добавил директиву '''ServerRoot''', чтобы '''httpd.conf''' стал
 +
понятнее, и вот наши изменения:
 +
 +
User httpd
 +
Group httpd
 +
ServerRoot /usr/local/apache2
 +
DocumentRoot /usr/local/apache2/htdocs
 +
Options -Includes -ExecCGI
 +
AddHandler application/x-httpd-php .php
 +
<Directory />
 +
Order deny,allow
 +
deny from all
 +
 +
</Directory>
 +
<Directory /usr/local/apache2/htdocs>
 +
Order allow,deny
 +
Allow from all
 +
</Directory>
 +
<Directory /usr/local/apache2/cgi-bin>
 +
Options +ExecCGI
 +
SetHandler cgi-script
 +
</Directory>
 +
 +
Теперь нам понятна основная структура прав доступа и те изменения, что мы сделали в '''httpd.conf''' для стандартного укрепления
 +
''Apache''. Нужно также укрепить нашу установку ''PHP'' – неважно,
 +
выполняются ли приложения ''PHP'' как ''CGI''-скрипты или внутри
 +
модуля ''Apache''.
 +
 +
===Еще о настройке ''Apache''===
 +
 +
Сначала поразмыслим о том, чего именно мы хотим – допустим,
 +
гибкости: например, возможности запуска ''PHP'' и как скрипта ''CGI'', и
 +
как модуля. Если мы добавим еще одну директиву конфигурации,
 +
например
 +
 +
Action application/x-httpd-php /cgi-bin/php
 +
 +
к уже существующей директиве
 +
 +
AddHandler application/x-httpd-php .php
 +
 +
то сможем работать с любой установкой ''PHP'', независимо от того,
 +
где располагается ''PHP''-интерпретатор и запускается ли приложение
 +
''PHP'' как скрипт ''CGI'' или в рамках модуля. Директива '''Action''' включается посредством модулей '''mod_actions''', доступных по умолчанию в
 +
базовом дистрибутиве ''Apache''. Это гарантирует, что все ''PHP''-скрипты могут запускаться как скрипты ''CGI'', так как ''PHP'' определяется
 +
как конкретный тип MIME, который должен запускаться как скрипт
 +
''CGI''. В итоге ''Apache'' сможет обрабатывать все ''PHP''-скрипты.
 +
 +
===Настройка и компиляция ''PHP''===
 +
 +
Нам следует запустить настроечный скрипт со специальной опцией перенаправления, чтобы иметь возможность поместить
 +
''PHP''-интерпретатор в любой указанный нами каталог. Обратите внимание, что ''PHP''-интерпретатор может размещается в потенциально опасном месте, а именно, в любом общедоступном каталоге '''cgi-bin'''.
 +
 +
$ sudo ./configure \
 +
> --enable-force-cgi-redirect \
 +
> --prefix=/usr/local/apache2/php
 +
$ make
 +
$ sudo make install
 +
 +
Взгляните на опцию '''enable-force-cgi-redirect''': вы только что разрешили копирование интерпретатора ''PHP'' в любой каталог '''cgi-bin'''. Опция
 +
настройки сделает невозможной любую попытку получить доступ
 +
к интерпретатору ''PHP'' через URL. В любом случае, исполняемые файлы ''PHP CGI'' не обрабатывают аргументов командной строки.
 +
 +
===Другой путь: подготовить '''php.ini''' для скриптов ''PHP CGI''===
 +
 +
Мы также должны добавить директивы на уровень выше сервера
 +
''Apache'', в файл '''php.ini''' (файл настройки ''PHP''). Удобной возможностью
 +
является ввод так называемой директивы '''doc_root'''.
 +
 +
'''doc_root''' хорошо работает, если при компиляции не используется опция конфигурации '''enable-force-cgi-redirect'''. ''PHP''-интерпретатор
 +
в этом случае будет искать файлы ''PHP'', начиная с каталога, упомянутого в директиве ''doc_root'':
 +
 +
doc_root /var/www
 +
 +
прикажет ''PHP''-интерпретатору искать скрипты ''PHP CGI'' и файлы
 +
данных, начиная с этого каталога. Бывает, что некоторые, а то и все,
 +
''CGI''-скрипты по соображениям безопасности расположены не в обычных каталогах '''cgi-bin'''. Тогда можно создать отдельное дерево каталогов и внести этот путь в '''doc_root'''. Помните, что это не будет работать, если ''PHP'' выполняется как модуль ''Apache''.
 +
 +
Нам также следует сообщить ''PHP''-интерпретатору, к каким файлам
 +
данных он получает доступ, добавив
 +
 +
open_basedir /var/www
 +
 +
или любой другой подобный каталог. Это следует поменять, если вы
 +
используете разные пути каталогов или, естественно, многопользовательский режим.
 +
 +
===Запуск ''PHP'' как модуля===
 +
 +
Для завершения картины запуска ''PHP'' и доступа к файлам с использованием ''PHP'' нам нужно поговорить о запуске ''PHP'' в качестве модуля.
 +
Это имеет решающие преимущества, так как производительность программ ''PHP'' в этой конфигурации наиболее высока. Но в этом случае
 +
сложнее держать разных пользователей в стороне друг от друга.
 +
 +
В то же время, разделение привилегий, хоть и не столь легко
 +
достижимое, все же проще с ''CGI''-скриптами, основанными на ''suEXEC''.
 +
Другими словами, использовать ''PHP'' как модуль в ситуации массового хостинга следует крайне осторожно. Но мы попробуем получить
 +
представление о том, как выглядит этот сценарий и что можно сделать,
 +
чтобы его обезопасить.
 +
 +
Убедитесь, что интерфейс между ''apache'' и его модулями доступен:
 +
он известен как ''apxs2''. Первым делом нужно сменить каталог на то
 +
место, где располагается исходный код ''PHP'', и выполнить настроечный
 +
скрипт вроде следующего:
 +
 +
$ sudo /.configure --with-apxs2=/usr/local/apache2/bin/apxs \
 +
> --prefix=/user/local/apache2/php
 +
 +
Если модули еще не активированы, можете сделать это вручную:
 +
добавьте следующую строку в файл '''httpd.conf''', позаботившись, чтобы
 +
расширения файлов, которые вы собираетесь использовать в вашей
 +
установке ''PHP'', распознавались ''Apache'':
 +
 +
LoadModule php5_module libexec/libphp5.so
 +
 +
Возможно, вам придется добавить директиву '''DirectoryIndex''', чтобы
 +
отображался индексный файл.
 +
 +
DirectoryIndex index.html index.php
 +
 +
===''suEXEC''===
 +
 +
Наконец, классическим решением проблемы запуска ''CGI''-скриптов под
 +
'''UID'''’ами, отличными от '''UID''' пользователя ''Apache'', является ''suEXEC''.
 +
И наоборот, если ''Apache'' установлен вместе с ''suEXEC'', он не станет
 +
выполнять скрипты ''CGI'' под root’ом и/или администратором.
 +
 +
При правильной настройке ''suEXEC'' почти так же эффективен, как
 +
''chroot'', хотя ''chroot'' считается только второй линией защиты: ''suEXEC''
 +
будет выполнять только те скрипты, правом запуска которых обладает
 +
только их владелец. Если, например, права на запись распространяются на группу или на весь мир, скрипт не выполнится; точнее, он не
 +
выполнится, если хоть какое-нибудь право доступа распространяется
 +
на весь мир. В основном будут запускаться скрипты с правами доступа 750.
 +
 +
Сам ''suEXEC'' может быть запущен только ''Apache''. Группа, к которой
 +
принадлежит ''Apache'' – в нашем случае это '''httpd''' – имеет только одного
 +
члена, самого себя. Всему миру нельзя будет запускать ничего, если
 +
''suEXEC'' включен. ''Apache'' следует переключаться между собой и другим пользователем, чтобы запускать ''CGI''-скрипты от его имени. Чтобы
 +
достичь этого, нужно либо запустить ''Apache'' под root’ом (очень плохая
 +
идея), либо в оболочке '''SUID''' – тогда ''Apache'' сможет запускать процесс
 +
под другим '''ID''' для каждого динамического ''CGI''-запроса. Таким образом, для каждого динамического запроса ''Apache'' выполняет два процесса: двоичный файл '''SUID''' и собственно сам скрипт.
 +
 +
===Настройка ''suEXEC''===
 +
 +
Одной из причин, почему ''suEXEC'', будучи довольно продуманным приложением, не сильно популярен, является довольно сложный процесс
 +
настройки: его необходимо сконфигурировать и скомпилировать вручную, так как ''suEXEC'' не есть часть дистрибутива ''Apache''. Однако он
 +
полностью поддерживается Apache Foundation и чрезвычайно хорошо
 +
интегрируется с web-сервером. Некоторые дистрибутивы Linux или
 +
пакеты ''LAMP'' могут содержать уже настроенный ''suEXEC'', однако это
 +
лучше проверить лично.
 +
 +
Вам придется немного поиграть с опциями настройки. Пожалуйста,
 +
обращайте пристальное внимание на детали: ''suEXEC'' чрезвычайно
 +
суров, когда дело касается ошибок в информации о пути к каталогу или
 +
'''UID'''’ов, которые не соответствуют выдаваемым базовой системой.
 +
 +
$ ./configure --enable-suexec \
 +
> --suexec-bin /usr/local/apache2/bin/suexec
 +
 +
Предыдущую опцию следует проверить: она должна быть работоспособной и жестко закодированной для вашей системы. Если вы случайно
 +
ее пропустите, ''Apache'' даже не сможет найти ''suEXEC''. Переменные '''PATH'''
 +
работать не будут. (Документация по ''Apache'' рекомендует '''/usr/sbin/suexec'''). Проверьте ваше систему на предмет размещения ''Apache'' по
 +
умолчанию и ваших требований.
 +
 +
> --with-suexec-caller=httpd
 +
 +
Теперь вы понимаете, почему мы так настаивали, чтобы ''Apache''
 +
запускался под пользователем ''httpd''. При использовании ''suEXEC'' не
 +
обязательно позволять ''Apache'' отступать к пользователю root или
 +
пытаться запускать ''Apache'' и ''PHP'' в системе, требующей каждому
 +
запросу выполняться от имени отдельного пользователя. Это возможно, но в таком случае вам следует перекомпилировать ''Apache'' с другой
 +
потоковой моделью.
 +
 +
  > -- with-suexec-userdir=public_html
 +
 +
Если вы запускаете ''PHP''-скрипты, на которые имеет права только
 +
определенный пользователь, отличный от '''httpd''', вам следует указать
 +
здесь родительский каталог для всех пользовательских директорий;
 +
то есть независимо от того, кто пишет скрипты – Петя, Вася или Коля,
 +
''PHP''-скрипты должны быть доступны из каталога '''public_html''', например, каталога '''html/cgi-bin'''. Несмотря на мое обещание не говорить
 +
о виртуальных хостах, пожалуйста, убедитесь, что все они совместно
 +
используют корневой каталог, упомянутый здесь!
 +
 +
  > --with-suexec-docroot=/home
 +
 +
задает каталоги, начиная с которых ''suEXEC'' будет проводить поиск
 +
файлов и скриптов каждого пользователя.
 +
 +
Если виртуальные хосты и файлы '''.htaccess''' не используются, это
 +
должно соответствовать конфигурации, представленной файлом '''httpd.conf'''. Мы можем оставить установки в '''.config''' по умолчанию, но стоит
 +
проверить документацию ''Apache'', чтобы понять, какие опции не совсем отвечают условиям вашей системы: ''suEXEC'' имеет много правил,
 +
но мало исключений.
 +
 +
===Доступ ''suEXEC'' к ''PHP''===
 +
 +
Нам также нужно убедиться, что ''suEXEC'' позволяет обычному пользователю иметь доступ к ''PHP''. Как уже говорилось, каждый пользователь
 +
должен иметь копию ''PHP''-интерпретатора в своей каталоге '''cgi-bin'''.
 +
 +
Теперь следует подключить модуль ''Apache mod_rewrite''. Сделав это,
 +
мы можем добавить следующие правила в '''httpd.conf''':
 +
 +
  RewriteCond %{REQUEST_URI} .\php
 +
 +
Они гарантируют, что любое преобразование '''URI''' затрагивает
 +
только ''PHP''-файлы. Вам нужно убедиться, что все запросы, которые
 +
должен обрабатывать ''PHP''-интерпретатор, действительно доходят до
 +
него; в то же время '''mod_userdir''' должен увидеть запрос и послать
 +
его в нужное место: интерпретатор ''php'', расположенный в каталоге
 +
'''cgi-bin'''.
 +
 +
  RewriteRule ^/~(w+)/(.*)$ /~$1/cgi-bin/php/$1/$2 [NS, L, PT,
 +
E=Redirect_STATUS:302
 +
 +
Флаги '''Rewrite''' гарантируют, что
 +
* '''(NS)''': внутренние подзапросы игнорируются;
 +
* '''(L)''': это последний запрос – после него не допускается запросов на перезапись;
 +
* '''(PT)''': сейчас mod_rewrite остановит обработку, а '''mod_userdir''' примется за дело, и, наконец, переменной '''REDIRECT_STATUS''' будет присвоено значение 302, чтобы ''PHP'' мог обработать скрипт.
 +
 +
Этот последний штрих в заклинании завершит нашу попытку создать безопасный ''PHP''-сервер. Существуют другие модули для
 +
содержания ''PHP''-скриптов в безопасности, а их доступа к файлам –
 +
в четких границах. ''suPHP'', которому требуется ''suEXEC'', запускает только ''PHP''-скрипты, безопасно и под различными '''UID'''’ами. '''LXF'''
 +
 +
===Настройка безопасности===
 +
 +
Поскольку мы будем иметь дело с настройками безопасности вашего web-сервера, само
 +
собой разумеется, что не рекомендуется трогать копию ''Apache'', поставляемой с вашей
 +
системой. Проверьте, запущена ли копия ''Apache'':
 +
 +
$ ps -aux | grep httpd
 +
 +
Обнаружив, что ''Apache'' невозмутимо накручивает обороты, на время остановите web-сервер. Если у вас Debian или Ubuntu или любая
 +
другая система на базе Debian, сработает следующее:
 +
 +
$ sudo /etc/init.d/Apache2 stop
 +
 +
Чтобы обеспечить эксперименты исключительно с копией ''Apache'' и ''PHP'' собственной
 +
сборки, установите ''Apache 2.2.6'' из исходных
 +
текстов:
 +
 +
$ lynx http://httpd.Apache.org/download. Cgi
 +
$ gzip -d httpd-2.2.6.tar.gz
 +
$ tar xvf httpd-2.2.6.tar
 +
$ cd httpd-2.2.6 $ ./configure
 +
$ make
 +
$ make install
 +
 +
Ваша копия ''Apache'' будет установлена
 +
в '''/usr/local/apache2'''; если вы желаете установить его в другое место, видоизмените команду '''configure''' таким образом:
 +
 +
./configure -prefix=/path/to/Apache
 +
 +
===Больше защиты===
 +
 +
К проведенному нами исследованию безопасности нужно добавить новый уровень защиты:
 +
создать отдельный каталог '''cgi-bin''', не являющийся частью установки ''Apache''. Затем мы
 +
можем поместить туда ''PHP''-интерпретатор и
 +
добавить следующие строки
 +
 +
<Directory /var/www/cgi-php>
 +
Order allow,deny
 +
Deny from all
 +
</Directory>
 +
 +
в файл '''httpd.conf'''. Причина, почему это работает, в том, что мы добавили внутреннюю переадресацию посредством директивы '''Action''':
 +
 +
Action application/x-httpd-php /cgi-bin/php
 +
 +
Добавляя максимально строгий контроль
 +
внешнего доступа и озаботившись правами
 +
доступа к файлам, мы не прекратим работу
 +
''PHP''-интерпретатора, так как контроль доступа по сети работает только для внешней
 +
переадресации, а не для внутренней: он закроет любой прямой доступ к ''PHP''-
 +
интерпретатору или каталогу '''cgi-bin''' из нелокального источника, но при вызовах правильным пользователем ''PHP''-скрипты будут
 +
работать идеально.
 +
 +
===Запуск ''suEXEC'' и ''PHP''===
 +
 +
Надо добавить к ''Apache'' модуль '''mod_userdir'''
 +
посредством ''apxs'', и добавить директивы '''UserDir''' в файл '''httpd.conf''', например:
 +
 +
UserDir public_html
 +
UserDir disabled root
 +
 +
''suEXEC'' находит файлы по запросу пользователя, в данному случае – каноническому '''~user''',
 +
и приставляет к имени пользователя '''docroot'''.
 +
''suEXEC'' может добавлять к имени пользователя
 +
общий подкаталог, что приводит к
 +
 +
/docroot/~username/publicfolder
 +
 +
Чтобы было совсем здорово, ему также нужно найти '''cgi-bin''', что мы ранее уже разрешали, но только для пользователя ''Apache'', а
 +
именно, '''httpd'''.
 +
 +
Так как же средний держатель учетной записи на хостинге ''Apache'' сможет получить выделенный '''cgi-bin'''?
 +
 +
Очень просто:
 +
 +
<Directory /home/*/public_html/cgi-bin/>
 +
Options +ExecCGI
 +
SetHandler cgi_script
 +
</Directory>

Текущая версия на 07:39, 29 мая 2009

Содержание

[править] Доверимся PHP

В определенных кругах разработчиков безопасность PHP ставится под сомнение. Фрэнк Полманн развенчивает многие из этих мифов...

Все мы знаем, что PHP может быть источником весьма серьезных проблем с безопасностью. Регулярно обнаруживаются новые эксплойты, атакующие непосредственно интерпретатор; PHP-программисты часто имеют дело с системами управления контентом (CMS), нередко становясь при этом жертвами взломщиков.

Однако существуют весьма простые способы обеспечить безопасность, приняв во внимание то, на чем базируется работа PHP, а именно, web-сервер. За основу возьмем Apache, хотя часть последующих примеров применима также и к другим серверам.

[править] Как запускать PHP-программы

Разбираться придется с несколькими различными случаями. Программы PHP могут, во-первых, выполняться как CGI-скрипты; во-вторых, запускаться в рамках модуля Apache; и в-третьих, программы PHP можно писать как CGI-скрипты, но выполнять как часть так называемого модуля FastCGI. Скрипты CGI вызывают особенно неприятные проблемы с безопасностью, ибо каждый CGI-скрипт выполняется как отдельный процесс. А каждый процесс, выполняемый web-сервером, наследует идентификатор пользователя (uid) web-сервера, что не есть хорошо, если кто-нибудь заполучит контроль либо над CGI-скриптом, либо над исполняемым файлом Apache: тогда выполнение Apache и всех других CGI-скриптов будут во власти атакующего.

Существуют, однако, способы держать PHP-скрипты в безопасности без обращения к средствам второй линии защиты, вроде применения chroot’а к Apache и оставшейся части пакета {L,M}AMP. Зададимся вопросом о способах присвоить каждому CGI-скрипту отдельный uid; в частности, поговорим о suEXEC. Но есть более фундаментальные приемы, с которыми нужно ознакомиться, прежде чем прибегать к средствам типа suEXEC и suPHP.

[править] Первичное укрепление Apache

Практическую безопасность PHP можно подразделить на четыре части: безопасность файловой системы, безопасность Apache, уровень безопасности PHP-интерпретатора и безопасность PHP-клиента. Первыми тремя мы займемся целиком, а говоря о suEXEC, кратко остановимся на четвертой. Предположим, имеется стандартная схема размещения файлов: все файлы Apache расположены в /usr/local/apache2/.

ServerRoot                                /usr/local/apache2
DocumentRoot                              /usr/local/apache2/htdocs
Основной конфигурационный файл             /usr/local/apache2/conf/httpd.conf
Параметры SSL                              /usr/local/apache2/conf/ssl.conf
ErrorLog                                  /usr/local/apache2/logs/error_log
AccessLog                                 /usr/local/apache2/logs/access_log
cgi-bin                                   /usr/local/apache2/cgi-bin
Исполняемые файлы Apache                   /usr/local/apache2/bin

Можно, а иногда и нужно, иметь несколько каталогов cgi-bin; этим мы воспользуемся при разговоре о местоположении PHP-интерпретатора.

[править] Права доступа и последствия

Следует принять в расчет два сценария:

a Различные пользователи не должны иметь возможность случайно или умышленно перезаписывать файлы или каталоги друг друга.

b Каждый пользователь может иметь дело с виртуальной копией Apache, избегая таким образом некоторых, но не всех, проблем с правами доступа.

Данная возможность отражается на производительности и безопасности, но в данном контексте мы ее обсуждать не будем.

[править] Права доступа PHP CGI

Когда PHP скомпилирован для запуска с Apache, и используется файл конфигурации по умолчанию, рабочий режим PHP – это режим CGI-скрипта. Каждый CGI-скрипт, независимо от языка программирования, должен иметь необходимые права доступа, чтобы владелец скрипта мог запустить его. Это значит, что владелец скрипта должен уметь считывать и запускать сам скрипт, а Apache должно быть достаточно только прав на запуск. Если верить документации Apache, права доступа каталогов cgi-bin, где Apache ищет CGI-скрипты, должны быть таковы:

drwxrwxrwx

что также известно как права доступа 0777. Как мы увидим позже, все сценарии внутри каталогов cgi-bin должны восприниматься Apache как CGI-скрипты, и не иначе; отсюда следует, что надо привести в согласие права доступа всех скриптов, размещенных в каталоге cgi-bin (о файлах с данными и с контентом речь пока не идет). Права 0777 допустимы, но это рискованно, так как если вы предоставите их, любая брешь в защите приведет к тому, что люди смогут запросто перезаписывать и даже заменять CGI-скрипты, если они вызываются и модифицируются напрямую.

Строго говоря, единственный пользователь (или группа!), кто во время разработки и тестирования должен иметь право считывать, записывать и получать доступ к каталогу cgi-bin – это web-разработчик, или группа таковых. Тогда права на каталог cgi-bin снижаются до

drwxrwxr-x

они же – права доступа 775. Имеет смысл также предположить, что web-разработчику нужно считывать, изменять и выполнять файлы внутри каталога cgi-bin (и выводить их список!). По завершении разработки, когда CGI-скрипты попали на сервер, группе web-разработчиков в целом, по идее, незачем в них писать.

Выходит, права доступа для cgi-bin755, как и сделано по умолчанию на многих установках Apache и пакета LAMP (Linux, Apache, MySQL, и PHP). Они также подразумевают, что пользователь Apache, если таковой существует, сможет выводить список файлов в данном каталоге, исполнять и считывать их.

[править] Права доступа CGI-скрипта

Так как всем остальным пользователям нужно уметь считывать CGI-скрипты, но только Apache приходится их выполнять, администратор должен установить всем CGI-скриптам права 644.

$ chmod 644 {любое_имя_файла}.cgi

[править] Настройка Apache для PHP

Чтобы заставить web-сервер действовать по заданному сценарию, мы должны удостовериться, что прописаны определенные директивы Apache, и присутствуют определенные модули. Прежде всего следует убедиться, что пользователь Apache – единственный, которому система разрешает запускать Apache, и что этот пользователь – единственный член группы Apache. Назовем этого пользователя httpd, и группу тоже назовем httpd.

$ groupadd httpd
$ useradd httpd -g httpd -d /dev/null -s /sbin/nologin

Нам нужно создать для Apache нового пользователя, чтобы пресечь любые попытки взломщиков «угадать» владельца скрипта во время работы. Мы не дадим самому Apache многих привилегий: у него даже не будет отдельного входа в систему. Владельцу скриптов и файлов данных, конечно, полагается быть web-разработчиком или кем-то из группы web-дизайна.

Данная мера безопасности окажется бесполезной, только если кто-нибудь сумеет «угадать» идентификатор web-сервера, но для этого требуется несколько больше, чем способность выполнять CGI-скрипты.

Еще нам понадобится возможность создавать другие каталоги cgi, чтобы объединять наши скрипты вместе по типам. Желательно группировать вместе PHP-скрипты, так как можно, а иногда даже нужно, иметь копию интерпретатора PHP, запущенную внутри CGI-каталогов. Обычно считается, что это – дыра в безопасности, но с ней можно управиться способом, которым мы потом займемся отдельно.

UID и GID созданного в системе Linux/Unix пользователя httpd, отображаемые в списке Linux-пользователей, должны совпадать с UID и GID пользователя и группы Apache.

Директивы http.conf, присутствующие в главном разделе конфигурации Apache, таковы:

User httpd
Group httpd

Позаботимся, чтобы Apache мог выполнять CGI-скрипты. Это гарантируется модулем mod_cgi (он доступен как часть базового дистрибутива Apache), но существуют некоторые директивы, которые следует добавить к httpd.conf еще до работы модуля. Нам нужно сообщить httpd.conf, что CGI-скрипты могут запускаться, и откуда они могут запускаться. PHP должен запускаться из какого-либо каталога cgi-bin, независимо от того, один или несколько пользователей работают с CGI-скриптами. Мы должны начать с директивы, запрещающей всему, что располагается за пределами дерева web-сервера, запускаться владельцем или любым пользователем Apache. Потом мы сможем ослабить наши правила, но для начала лучше проявить максимум консерватизма.

Следующие директивы тривиальны, но совершенно необходимы для безопасных операций Apache:

<Directory />
Order deny,allow
deny from all
</Directory>

Это – стандартная директива, она гарантирует, что Apache не сможет обслуживать файлы по всей файловой системе, даже дерево web- сервера. Конечно, теперь придется потрудиться, чтобы Apache СМОГ обслуживать нужные файлы, так что добавим другую директиву, сообщающую, что Apache может обслуживать файлы данных и контента из DocumentRoot:

DocumentRoot /usr/local/apache2/htdocs
<Directory /usr/local/apache2/htdocs>
Order allow,deny
Allow from all
</Directory>

Для правильной работы PHP-скрипты обязаны восприниматься как CGI-скрипты.

Чтобы никто не вздумал разрешить выполнение CGI с использованием файлов PHP не из каталога /usr/local/apache2/cgi-bin (или любого другого, явно прописанного вами в директивах Directory), добавим

Options -Includes -ExecCGI

в главный конфигурационный раздел httpd.conf.

Нужно также назначить каталог, содержащий CGI-скрипты; это делается директивой SetHandler. Тот факт, что мы разрешаем исполнение CGI через директиву Options, на вид противоречит предыдущей директиве, но вы ведь помните, что нельзя выполнять только CGI-скрипты, не содержащиеся в указанном ниже каталоге.

<Directory /usr/local/apache2/cgi-bin>
Options +ExecCGI
SetHandler cgi-script
</Directory>

Сперва, однако, не мешает предупредить Apache, с какими файлами следует обращаться как со сценариями PHP. Итак, в главном файле конфигурации говорим Apache, что мы используем скрипты CGI – это мы уже сделали, осталось сообщить, что мы используем файлы PHP:

AddHandler application/x-httpd-php .php

Вы можете добавить другие обработчики-handler’ы и, если захотите, новые расширения файлов, например, php3 или php5, но это на ваше усмотрение. Здесь приведен фрагмент httpd.conf: понадобится еще несколько директив, чтобы наш httpd.conf заработал, но советую добавить предыдущие директивы, в соответствии с нашими рекомендациями. Я добавил директиву ServerRoot, чтобы httpd.conf стал понятнее, и вот наши изменения:

User httpd
Group httpd
ServerRoot /usr/local/apache2
DocumentRoot /usr/local/apache2/htdocs
Options -Includes -ExecCGI
AddHandler application/x-httpd-php .php
<Directory />
Order deny,allow
deny from all
</Directory>
<Directory /usr/local/apache2/htdocs>
Order allow,deny
Allow from all
</Directory>
<Directory /usr/local/apache2/cgi-bin>
Options +ExecCGI
SetHandler cgi-script
</Directory>

Теперь нам понятна основная структура прав доступа и те изменения, что мы сделали в httpd.conf для стандартного укрепления Apache. Нужно также укрепить нашу установку PHP – неважно, выполняются ли приложения PHP как CGI-скрипты или внутри модуля Apache.

[править] Еще о настройке Apache

Сначала поразмыслим о том, чего именно мы хотим – допустим, гибкости: например, возможности запуска PHP и как скрипта CGI, и как модуля. Если мы добавим еще одну директиву конфигурации, например

Action application/x-httpd-php /cgi-bin/php

к уже существующей директиве

AddHandler application/x-httpd-php .php

то сможем работать с любой установкой PHP, независимо от того, где располагается PHP-интерпретатор и запускается ли приложение PHP как скрипт CGI или в рамках модуля. Директива Action включается посредством модулей mod_actions, доступных по умолчанию в базовом дистрибутиве Apache. Это гарантирует, что все PHP-скрипты могут запускаться как скрипты CGI, так как PHP определяется как конкретный тип MIME, который должен запускаться как скрипт CGI. В итоге Apache сможет обрабатывать все PHP-скрипты.

[править] Настройка и компиляция PHP

Нам следует запустить настроечный скрипт со специальной опцией перенаправления, чтобы иметь возможность поместить PHP-интерпретатор в любой указанный нами каталог. Обратите внимание, что PHP-интерпретатор может размещается в потенциально опасном месте, а именно, в любом общедоступном каталоге cgi-bin.

$ sudo ./configure \
> --enable-force-cgi-redirect \
> --prefix=/usr/local/apache2/php
$ make
$ sudo make install

Взгляните на опцию enable-force-cgi-redirect: вы только что разрешили копирование интерпретатора PHP в любой каталог cgi-bin. Опция настройки сделает невозможной любую попытку получить доступ к интерпретатору PHP через URL. В любом случае, исполняемые файлы PHP CGI не обрабатывают аргументов командной строки.

[править] Другой путь: подготовить php.ini для скриптов PHP CGI

Мы также должны добавить директивы на уровень выше сервера Apache, в файл php.ini (файл настройки PHP). Удобной возможностью является ввод так называемой директивы doc_root.

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

doc_root /var/www

прикажет PHP-интерпретатору искать скрипты PHP CGI и файлы данных, начиная с этого каталога. Бывает, что некоторые, а то и все, CGI-скрипты по соображениям безопасности расположены не в обычных каталогах cgi-bin. Тогда можно создать отдельное дерево каталогов и внести этот путь в doc_root. Помните, что это не будет работать, если PHP выполняется как модуль Apache.

Нам также следует сообщить PHP-интерпретатору, к каким файлам данных он получает доступ, добавив

open_basedir /var/www

или любой другой подобный каталог. Это следует поменять, если вы используете разные пути каталогов или, естественно, многопользовательский режим.

[править] Запуск PHP как модуля

Для завершения картины запуска PHP и доступа к файлам с использованием PHP нам нужно поговорить о запуске PHP в качестве модуля. Это имеет решающие преимущества, так как производительность программ PHP в этой конфигурации наиболее высока. Но в этом случае сложнее держать разных пользователей в стороне друг от друга.

В то же время, разделение привилегий, хоть и не столь легко достижимое, все же проще с CGI-скриптами, основанными на suEXEC. Другими словами, использовать PHP как модуль в ситуации массового хостинга следует крайне осторожно. Но мы попробуем получить представление о том, как выглядит этот сценарий и что можно сделать, чтобы его обезопасить.

Убедитесь, что интерфейс между apache и его модулями доступен: он известен как apxs2. Первым делом нужно сменить каталог на то место, где располагается исходный код PHP, и выполнить настроечный скрипт вроде следующего:

$ sudo /.configure --with-apxs2=/usr/local/apache2/bin/apxs \
> --prefix=/user/local/apache2/php

Если модули еще не активированы, можете сделать это вручную: добавьте следующую строку в файл httpd.conf, позаботившись, чтобы расширения файлов, которые вы собираетесь использовать в вашей установке PHP, распознавались Apache:

LoadModule php5_module libexec/libphp5.so

Возможно, вам придется добавить директиву DirectoryIndex, чтобы отображался индексный файл.

DirectoryIndex index.html index.php

[править] suEXEC

Наконец, классическим решением проблемы запуска CGI-скриптов под UID’ами, отличными от UID пользователя Apache, является suEXEC. И наоборот, если Apache установлен вместе с suEXEC, он не станет выполнять скрипты CGI под root’ом и/или администратором.

При правильной настройке suEXEC почти так же эффективен, как chroot, хотя chroot считается только второй линией защиты: suEXEC будет выполнять только те скрипты, правом запуска которых обладает только их владелец. Если, например, права на запись распространяются на группу или на весь мир, скрипт не выполнится; точнее, он не выполнится, если хоть какое-нибудь право доступа распространяется на весь мир. В основном будут запускаться скрипты с правами доступа 750.

Сам suEXEC может быть запущен только Apache. Группа, к которой принадлежит Apache – в нашем случае это httpd – имеет только одного члена, самого себя. Всему миру нельзя будет запускать ничего, если suEXEC включен. Apache следует переключаться между собой и другим пользователем, чтобы запускать CGI-скрипты от его имени. Чтобы достичь этого, нужно либо запустить Apache под root’ом (очень плохая идея), либо в оболочке SUID – тогда Apache сможет запускать процесс под другим ID для каждого динамического CGI-запроса. Таким образом, для каждого динамического запроса Apache выполняет два процесса: двоичный файл SUID и собственно сам скрипт.

[править] Настройка suEXEC

Одной из причин, почему suEXEC, будучи довольно продуманным приложением, не сильно популярен, является довольно сложный процесс настройки: его необходимо сконфигурировать и скомпилировать вручную, так как suEXEC не есть часть дистрибутива Apache. Однако он полностью поддерживается Apache Foundation и чрезвычайно хорошо интегрируется с web-сервером. Некоторые дистрибутивы Linux или пакеты LAMP могут содержать уже настроенный suEXEC, однако это лучше проверить лично.

Вам придется немного поиграть с опциями настройки. Пожалуйста, обращайте пристальное внимание на детали: suEXEC чрезвычайно суров, когда дело касается ошибок в информации о пути к каталогу или UID’ов, которые не соответствуют выдаваемым базовой системой.

$ ./configure --enable-suexec \
> --suexec-bin /usr/local/apache2/bin/suexec

Предыдущую опцию следует проверить: она должна быть работоспособной и жестко закодированной для вашей системы. Если вы случайно ее пропустите, Apache даже не сможет найти suEXEC. Переменные PATH работать не будут. (Документация по Apache рекомендует /usr/sbin/suexec). Проверьте ваше систему на предмет размещения Apache по умолчанию и ваших требований.

> --with-suexec-caller=httpd

Теперь вы понимаете, почему мы так настаивали, чтобы Apache запускался под пользователем httpd. При использовании suEXEC не обязательно позволять Apache отступать к пользователю root или пытаться запускать Apache и PHP в системе, требующей каждому запросу выполняться от имени отдельного пользователя. Это возможно, но в таком случае вам следует перекомпилировать Apache с другой потоковой моделью.

 > -- with-suexec-userdir=public_html

Если вы запускаете PHP-скрипты, на которые имеет права только определенный пользователь, отличный от httpd, вам следует указать здесь родительский каталог для всех пользовательских директорий; то есть независимо от того, кто пишет скрипты – Петя, Вася или Коля, PHP-скрипты должны быть доступны из каталога public_html, например, каталога html/cgi-bin. Несмотря на мое обещание не говорить о виртуальных хостах, пожалуйста, убедитесь, что все они совместно используют корневой каталог, упомянутый здесь!

 > --with-suexec-docroot=/home

задает каталоги, начиная с которых suEXEC будет проводить поиск файлов и скриптов каждого пользователя.

Если виртуальные хосты и файлы .htaccess не используются, это должно соответствовать конфигурации, представленной файлом httpd.conf. Мы можем оставить установки в .config по умолчанию, но стоит проверить документацию Apache, чтобы понять, какие опции не совсем отвечают условиям вашей системы: suEXEC имеет много правил, но мало исключений.

[править] Доступ suEXEC к PHP

Нам также нужно убедиться, что suEXEC позволяет обычному пользователю иметь доступ к PHP. Как уже говорилось, каждый пользователь должен иметь копию PHP-интерпретатора в своей каталоге cgi-bin.

Теперь следует подключить модуль Apache mod_rewrite. Сделав это, мы можем добавить следующие правила в httpd.conf:

 RewriteCond %{REQUEST_URI} .\php

Они гарантируют, что любое преобразование URI затрагивает только PHP-файлы. Вам нужно убедиться, что все запросы, которые должен обрабатывать PHP-интерпретатор, действительно доходят до него; в то же время mod_userdir должен увидеть запрос и послать его в нужное место: интерпретатор php, расположенный в каталоге cgi-bin.

 RewriteRule ^/~(w+)/(.*)$ /~$1/cgi-bin/php/$1/$2 [NS, L, PT,
E=Redirect_STATUS:302

Флаги Rewrite гарантируют, что

  • (NS): внутренние подзапросы игнорируются;
  • (L): это последний запрос – после него не допускается запросов на перезапись;
  • (PT): сейчас mod_rewrite остановит обработку, а mod_userdir примется за дело, и, наконец, переменной REDIRECT_STATUS будет присвоено значение 302, чтобы PHP мог обработать скрипт.

Этот последний штрих в заклинании завершит нашу попытку создать безопасный PHP-сервер. Существуют другие модули для содержания PHP-скриптов в безопасности, а их доступа к файлам – в четких границах. suPHP, которому требуется suEXEC, запускает только PHP-скрипты, безопасно и под различными UID’ами. LXF

[править] Настройка безопасности

Поскольку мы будем иметь дело с настройками безопасности вашего web-сервера, само собой разумеется, что не рекомендуется трогать копию Apache, поставляемой с вашей системой. Проверьте, запущена ли копия Apache:

$ ps -aux | grep httpd

Обнаружив, что Apache невозмутимо накручивает обороты, на время остановите web-сервер. Если у вас Debian или Ubuntu или любая другая система на базе Debian, сработает следующее:

$ sudo /etc/init.d/Apache2 stop

Чтобы обеспечить эксперименты исключительно с копией Apache и PHP собственной сборки, установите Apache 2.2.6 из исходных текстов:

$ lynx http://httpd.Apache.org/download. Cgi
$ gzip -d httpd-2.2.6.tar.gz
$ tar xvf httpd-2.2.6.tar
$ cd httpd-2.2.6 $ ./configure
$ make
$ make install

Ваша копия Apache будет установлена в /usr/local/apache2; если вы желаете установить его в другое место, видоизмените команду configure таким образом:

./configure -prefix=/path/to/Apache

[править] Больше защиты

К проведенному нами исследованию безопасности нужно добавить новый уровень защиты: создать отдельный каталог cgi-bin, не являющийся частью установки Apache. Затем мы можем поместить туда PHP-интерпретатор и добавить следующие строки

<Directory /var/www/cgi-php>
Order allow,deny
Deny from all
</Directory>

в файл httpd.conf. Причина, почему это работает, в том, что мы добавили внутреннюю переадресацию посредством директивы Action:

Action application/x-httpd-php /cgi-bin/php

Добавляя максимально строгий контроль внешнего доступа и озаботившись правами доступа к файлам, мы не прекратим работу PHP-интерпретатора, так как контроль доступа по сети работает только для внешней переадресации, а не для внутренней: он закроет любой прямой доступ к PHP- интерпретатору или каталогу cgi-bin из нелокального источника, но при вызовах правильным пользователем PHP-скрипты будут работать идеально.

[править] Запуск suEXEC и PHP

Надо добавить к Apache модуль mod_userdir посредством apxs, и добавить директивы UserDir в файл httpd.conf, например:

UserDir public_html
UserDir disabled root

suEXEC находит файлы по запросу пользователя, в данному случае – каноническому ~user, и приставляет к имени пользователя docroot. suEXEC может добавлять к имени пользователя общий подкаталог, что приводит к

/docroot/~username/publicfolder

Чтобы было совсем здорово, ему также нужно найти cgi-bin, что мы ранее уже разрешали, но только для пользователя Apache, а именно, httpd.

Так как же средний держатель учетной записи на хостинге Apache сможет получить выделенный cgi-bin?

Очень просто:

<Directory /home/*/public_html/cgi-bin/>
Options +ExecCGI
SetHandler cgi_script
</Directory>
Персональные инструменты
купить
подписаться
Яндекс.Метрика