Представляем вашему вниманию вторую статью Артура Маджа из цикла Шаг-за-Шагом.
Перевод осуществлен в рамках проекта GFS. Перевел Cobalt. Текст статьи на
английском можно взять здесь: http://www.symantec.com/connect/articles/securing-php-step-step.
В моей предыдущей статье (Безопасность Апача: Шаг-за-Шагом) я описывал метод
защиты вебсервера Apache от несануционированого доступа из Интернет. Благодаря
описаному методу стало возможным значительно повысить уровень безопасности
сервера, но только в случае использования статических HTML страниц. Но как
можно повысить безопасность, когда необходима интерактивная работа с пользова-
телем, и данные надо хранить в БД ?
Эта статья рассказывает о повышении безопасности PHP, одного из самых популярных
скриптовых языков используемого для создания динамических вебстраниц. Во избежа-
ние повторения, в этой статье будет описана главным образом разница в настройке
Apache.
Операционная система
Так же как и в предыдущей статье, целевой ОС будет FreeBSD 4.7. Точно также
описываемый метод может быть с легкостью применен в других Unix-like системах.
Эта статья подразумевает что на сервере установлен MySQL и находится в директории
"/usr/local/mysql".
Функциональность
Вообще, функциональность будет не сильно отличатся от описаной в предыдущей
статье. Вот самые основные отличия:
* Веб сервер должен потдерживать язык PHP
* Компоненты PHP толжны "уметь" записывать и читать данные в лолкальный
MySQL
Требования безопасности
Тут мы имеем следущие изменения:
* PHP должен иметь расширеные механизмы защищенности
* PHP скрипты должны запускаться в chroot окружении
* Apache должен контролировать все запросы (POST и GET) которые содержат
HTML теги (для предотвращения аттак типа XSS) и апострофы (SQL-inj)
* Пользователю не должно отображаться никаких предупреждений и ошибок
PHP скриптов.
* По возможности хранить все входящие POST и GET запросы в текстовом
архзиве. Это позволит использовать системы обнаружения вторжения (HIDS)
например swatch.
Подготовка софта
Во-первых, мы должны скачать самые последние версии Apache, PHP и mod_security.
Модуль необходим чтобы обезопаситься от атак типа CSS и SQL-inj. Далее, скаченый
софт должен быть распакован и помещен в домашнюю директорию. Исходный код
модудя mod_security должен находиться в директории апача ("src/modules/extra"):
gzip -dc apache_1.3.27.tar.gz | tar xvf -
gzip -dc php-4.3.2.tar.gz | tar xvf -
gzip -dc mod_security_1.5.tar.gz | tar xvf -
cp mod_security_1.5/apache1/mod_security.c apache_1.3.27/src/modules/extra/
Если имеются какие-нибудь апдейты безопасности они тоже должны присутствовать.
Перед тем как приступить к компилированию, мы должны также решить, какой
метод установки PHP будет использоваться:
* Как статический модуль веб сервера
* Как динамический модуль веб сервера
* Как CGI приложение
Каждый из вышеуказанных методов имеет свои преимущества и недостатки. Компиля-
ция PHP как статического модуля, может значительно повысить быстродействие
сервера, но тогда для обнавления PHP нам придется пересобирать весь сервер.
Второй способ (как динамический модуль) лишен этого недостатка, но быстродей-
ствие уменьшиться примерно на 5%. К томуже понадобится модуль mod_so. Третий
метод (как CGI) используемый совместно с suEXEC механизмом апача - довольно
интересное решение. В случае не правильной установки, это может повлеч
серьезную угрозу безопасности. С точки зрения безопасности, наилучшим решением
будет компиляция как статического модуля. Именно по этому, в этой статье описан
такой метод.
Установка PHP
Установка Apache с PHP не многим отличается от установки апача без PHP описаной
в предыдущей статье. Вся разница в двух дополнительных модулях: mod_php и
mod_security.
Так же как и в предыдущей статье мы начнем с создания учетки и группы "apache".
Далее подготовим сервер Apache следущим образом:
cd apache_1.3.27
./configure
И скомпилируем PHP:
cd ../php-4.3.2
./configure --with-mysql=/usr/local/mysql --with-apache=../apache_1.3.27
--enable-safe-mode
make
su
make install
Потом перейдем в каталог с исходниками Apache и продолжим инсталяцию:
cd ../apache_1.3.27
./configure --prefix=/usr/local/apache --disable-module=all --server-uid=apache
--server-gid=apache --enable-module=access --enable-module=log_config
--enable-module=dir --enable-module=mime --enable-module=auth
--activate-module=src/modules/extra/mod_security
--enable-module=security --activate-module=src/modules/php4/libphp4.a
make
su
make install
chown -R root:sys /usr/local/apache
В преведенных параметрах команды ./configure подключены только обязательные модуля
чтобы выполнить требования безопасности. Выбор модулей нами обсуждался в предыду-
щей статье. Теперь, следующим шагом, вернемся в php директорию и скопируем
дефолтовый конфиг:
cd ../php-4.3.2
mkdir /usr/local/lib
chmod 755 /usr/local/lib
cp php.ini-recommended /usr/local/lib/php.ini
chown root:sys /usr/local/lib/php.ini
chmod 644 /usr/local/lib/php.ini
Для того чтобы вебсервер Apache корректно распознавал PHP-скрипты, в
/usr/local/apache/conf/httpd.conf надо добавить следущую строку:
AddType application/x-httpd-php .php
Тепернь можно протестировать полученную конфигурацию, а также убедиться что
PHP корректно работает с MySQL. Это можно сделать используя следующий скрипт (
замените "user_name" и "password" вашими значениями):
<html><body>
<?php
$link = mysql_connect("localhost", "user_name", "password")
or die;
print "Everything works OK!";
mysql_close($link);
?>
</body></html>
Страница сгенерированая этим скриптом должна корректно отображаться во всех
браузерах. Если все настроено правильно, скрипт должен подключиться к MySQL и
выдать сообщение об успешной операции. Если же по какой-то причине этого
не произошло, проаналезируйте логи апача и mysql для локализации проблеммы.
Настройка PHP
Ранее мы описывали настройку Apache, теперь настало время поговорить и о
настройке конфигурационных файлов PHP. Чтобы апачь корекктно распознавал
PHP-скрипты, мы добавим в конфиг апача следущие строки:
AddModule mod_php4.c
AddType application/x-httpd-php .php
AddType application/x-httpd-php .inc
AddType application/x-httpd-php .class
Они означают, что апач будет считать файлы с расширением .php, .inc, .class -
приложениями PHP и выполнять их как скрипты.
Также, для повышения безопасности, внесем следущие изменения в php.ini:
safe_mode=On При включении этой опции PHP скрипты будут иметь доступ
только к тем файлам, создатиель которых является также
и создателем самих сценариев. Это один из главных
механизмов обеспечения безопасности встроеных в PHP. Это
давольно-таки эфективная защита от несанкционированого
доступа к системным файлам.
safe_mode_gid = Off Когда safe_mode включен, и safe_mode_gid выключен, PHP скрипты
имеют доступ не только когда UID совпадает, но также и
группы создателей совпадают.
open_basedir = Когда safe_basedir включен, тогда PHP скрипты будут иметь
directory[:...] доступ только к файлам находящимся в указаной директории
safe_mode_exec_dir= Когда safe_mode включен, функции system(),exec() и подобные,
directory[:...] смогут запускать программы находящиеся только в указаной
директории.
expose_php = Off Выключив данный параметр, мы заставляем PHP не посылать
в заголовке информацию о себе.
register_globals=Off Когда этот параметр включен, все EGPCS (окружение, GET,
POST, Cookie и Session) переменные будут автоматически
преабразовываться в обычные переменные. Т.к. это может
сильно снизить безопасность скриптов, необходимо этот
параметр отключить.
display_errors = Off Когда этот параметр отключен, предупреждения и ошибки
PHP не будут выводиться на экран. Так как, подобные
сообщения могут дать информацию злоумышленнику, их
надо отключить.
log_errors = On Когда этот параметр включен, все предупреждения и сообщения
об ошибках, будут писаться в логфайл определенный в
параметре error_log.
error_log=filename Этот параметр определяет файл, вкоторый будет вестись лог
об ошибках и предупреждениях.
В дополнение, можно изменить расширения файлов *.php на например *.asp. Это
позволит ввести злоумышленника в заблуждение относительно технологий
используемых на сервере. Для этого надо добавить строку:
AddType application/x-httpd-php .asp
Блягодаря этому, пользователи не увидят расширения *.php в строке браузера
и не будут знать о том что на сервере применяется PHP.
Защита против SQL-inj и CSS аттак
В требованиях безопасности, мы определили что сервер должен вести учет всех
GET и POST запросов. Для этого мы воспользуемся модулем mod_security:
AddModule mod_security.c
Внесем следущие изменения в httpd.conf:
AddHandler application/x-httpd-php .php
SecAuditEngine On
SecAuditLog logs/audit_log
SecFilterScanPOST On
SecFilterEngine On
Эти команды включают ядро аудита, которое предназначено для ведения логов и
фильтрации запросов. Для защиты сервера от CSS атак, вставте перед
такие строки:
SecFilterDefaultAction "deny,log,status:500"
SecFilter "<(.|
)+>"
Первая строка определяет какую ошибку будет возвращать сервер когда поступит
запрос содержащий запрещенные символы. Во второй строке определен фильтр полиска
HTML тэгов в запросе.
Одна из типичных сигнатур атаки SQL-inj - это использование символа аппострофа
(') или двойных кавычек (") в GET или POST запросе.
Примичание: иногда запрет этих символов, может привести к неправильной работе
php скрипта. В этом случае можно использовать JavaScript который на стороне
клиента будет преобразовывать эти символы в потенциально безопасные.
Выводы
Добиться высокого уровня безопасности на сервере применяя server-side технологии
(ASP, PHP, JSP etc) на практике очень сложная задача. Интерактивность сервера
делает эту задачу практически невозможной. Вот почему скрипты должны использоваться
только там, где это действительно необходимо.
Описаный в данной статье метод, позволяет немного снизить риск проникновения в
систему, когда будут найдены новые уязвимости в используемом ПО.Конечно статья
не претендует на полноценное руководство по безопасности PHP, в ней изложены лишь
базовые принципы. Также нельзя забывать что безопасность сервера зависит не только
от защищенности Apache и PHP, но в большей степени от используемых скриптов.
© Artur Maj (2003-06-23)
10.07.2006 © перевод Cobalt