PHP как FastCGI и распределение прав
Базовая информация
------------------
Все процессы Apache запускаются от одного непривилегированного
пользователя (nobody, www или apache). Для того, чтобы статические
файлы были доступны Apache, они должны быть world readable или входить
в группу Apache и быть group readable.
CGI-скрипты запущенные, с suEXEC выполняются уже от владельца скрипта,
и им не нужно иметь права world/group readable. Но PHP-скрипты
запущенные через mod_php, также как статические файлы, нуждаются в
world/group readable правах, так как они не используют suEXEC.
Проблема
--------
World readable или group readable доступны на чтения всем или тем, кто
входит в их группу. Поэтому все статические файлы и PHP-скрипты, в
которых может храниться конфиденциальная информация (пароли к базам
данных, аутентификационные данные или просто исходные тексты),
доступны всем пользователям системы.
Простое "решение"
-----------------
Для mod_php можно настроить open_basedir и отключить такие функции,
как exec, system, passthru (похожих функций намного больше). Однако
этим можно защитить только чтение PHP-скриптами, CGI-скрипты все ещё
могут читать world/group readable файлы. Поэтому вам ещё надо
запретить любые другие возможности доступа (CGI, Cron, Shell).
Для защиты CGI-скриптов достаточно выставить chmod 700. Это решение не
самое удобное, так как chmod придётся делать каждый раз при создании
или загрузке нового скрипта.
Отключение CGI неприемлемо для виртуального хостинга, а выставление
chmod вручную не удобно, да и CGI-скрипты намного медленней mod_php.
Также не надо забывать, что статические файлы (.htaccess, .htpasswd)
всё ещё доступны всем.
Распределение прав
------------------
Главная причина этой проблемы, это неправильное распределение прав.
Статические файлы доступны на чтение всем.
Нам же нужно, чтобы файлы были доступны только Apache и самому
владельцу, а не всем. Для этого достаточно каждому пользователю
создать персональную группу (на хостинге чаще всего так и есть) и
добавить в эту группу пользователя Apache (www или apache). После
этого каждый пользователь хостинга является участником только своей
группы, а Apache является участником всех этих групп.
Пример с двумя пользователями
#user1# id
uid=101(user1) gid=101(user1) groups=101(user1)
#user2# id
uid=102(user2) gid=102(user2) groups=102(user2)
#apache# id
uid=100(apache) gid=100(apache) groups=101(user1),102(user2)
# cat /etc/passwd
apache:x:100:100::/var/www:/bin/sh
user1:x:101:101::/home/user1:/bin/sh
user2:x:102:102::/home/user1:/bin/sh
# cat /etc/group
apache:x:100:
user1:x:101:apache
user2:x:102:apache
FreeBSD по умолчание имеет ограничение на количество групп, в
которые может входит один пользователь. В /usr/src/sys/sys/syslimits.h
следует заменить #define NGROUPS_MAX 16 на нужное значение.
Следующий этап, это выставление прав на $HOME папки пользователей,
они должны быть доступны для группы и владельца, но не для всех.
#root# chmod 750 /home/*
Все файлы в $HOME директории будут недоступны другим пользователям,
неважно какие у них будут права. Этим мы решаем проблему выставления
прав для каждого файла/скрипта вручную.
Отказ от mod_php
----------------
Теперь самое главное не дать пользователям возможности заполучить
права Apache, а значит надо отказаться от mod_php. Конечно его можно
просто безопасней настроить, но этого не достаточно, так как в PHP
множество опасных функций и возможностей обхода open_basedir. Поэтому
мы выбираем CGI или FastCGI и suEXEC.
Настройка PHP как FastCGI
-------------------------
Есть два модуля Apache mod_fastcgi и mod_fcgid. mod_fcgid более новей
и поэтому лучше использовать его, но если вы упорно решили оставаться
на Apache 1.3 и не хотите переходить на более быстрый и
функциональный Apache 2.2, то вам придётся установить mod_fastcgi.
PHP надо пересобрать добавив опции
***************************
--enable-fastcgi
--enable-force-cgi-redirect
***************************
Если вы всё ещё используете старую версию PHP, то это хороший повод
обновить его до последней версии, что также даст прирост в
производительности и новые возможности.
Настройка mod_fcgid, добавляем в httpd.conf
************************************************
Options +ExecCGI
AddHandler fcgid-script .php
FCGIWrapper /usr/apache/htdocs/fcgid-php.sh .php
************************************************
Также очень важно добавить в каждый виртуальный хост строку
*************************************
SuexecUserGroup user-login user-group
*************************************
fcgid-php.sh должен находится в suexec-docroot, иначе он не будет
запускаться из-за строгой политики suEXEC.
Содержание выполняемого скрипта fcgid-php.sh, который и будет
запускать персональный FastCGI демон для каждого пользователя.
******************************
#!/bin/sh
export PHP_FCGI_MAX_REQUESTS=0
exec /usr/bin/php
******************************
Последнее действие, это упрощение политики безопасности suEXEC, а
именно удаление проверки запускаемого скрипта (fcgid-php.sh) и
директории в которой он находится (/usr/apache/htdocs) на
соответствие их владельца с пользователем указанным в SuexecUserGroup.
Для этого надо закомментировать строки (566-576 в 2.2.3)
************************************************************
if ((uid != dir_info.st_uid) ||
(gid != dir_info.st_gid) ||
(uid != prg_info.st_uid) ||
(gid != prg_info.st_gid)) {
log_err("target uid/gid (%ld/%ld) mismatch "
"with directory (%ld/%ld) or program (%ld/%ld)\n",
uid, gid,
dir_info.st_uid, dir_info.st_gid,
prg_info.st_uid, prg_info.st_gid);
exit(120);
}
************************************************************
в файле [httpd-2.x]/support/suexec.c и пересобрать suEXEC. Иначе
пришлось бы копировать fcgid-php.sh каждому пользователю и указывать
путь в каждом виртуальном хосте.
Лицензия (GFDL)
---------------
Copyright (c) 2007 Sergej Ermakov (Roxis)
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
Texts. A copy of the license can be downloaded from
http://www.gnu.org/licenses/fdl.html