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

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

Материал из Linuxformat
(Различия между версиями)
Перейти к: навигация, поиск
(Новая: ==Доверимся ''PHP''== : В определенных кругах разработчиков безопасность ''PHP'' ставится под сомнение. '''Фрэ...)
 
(Викификация, оформление)
 
(не показана 1 промежуточная версия 1 участника)
Строка 48: Строка 48:
  
 
Следует принять в расчет два сценария:
 
Следует принять в расчет два сценария:
 +
 
'''a''' Различные пользователи не должны иметь возможность случайно или умышленно перезаписывать файлы или каталоги друг друга.
 
'''a''' Различные пользователи не должны иметь возможность случайно или умышленно перезаписывать файлы или каталоги друг друга.
  
Строка 155: Строка 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>
Персональные инструменты
купить
подписаться
Яндекс.Метрика