Возьми индейца под защитуСергей «grinder» Яремчук
Хакер, номер #106, стр. 154
(grinder@ua.fm)
Обеспечиваем безопасность инфраструктуры веб-сервера
По последним данным британской компании Netcraft, самым популярным веб-сервером в интернете является Apache - его доля на рынке за последние 3 года постепенно увеличивалась и сегодня составляет 67%. Успех Apache объясняется стабильностью его работы, наличием хорошей репутации в плане безопасности и простотой в администрировании. Но нельзя забывать, что обычно Apache используется не один, а в связке LAMP – Linux, Apache, MySQL и PHP/Perl. Поэтому сегодня мы выясним, как можно повысить безопасность LAMP с помощью ModSecurity, Suhosin, модуля mod_chroot и встроенных средств индейца.
Настраиваем Apache
Несмотря на репутацию компонентов LAMP, сегодня только и слышно о PHP include, SQL injection, Cross site scripting (XSS) и других атаках, направленных на веб-сервисы. Согласно статистике Web Application Security Consortium (
www.webappsec.org/projects/whid/statistics.shtml), именно они занимают первые места по количеству зафиксированных инцидентов. Среди основных причин такой негативной тенденции называют широкую доступность инструментов, необходимых для проведения атаки, и недостаточное внимание со стороны разработчиков сайтов к вопросам безопасности. Условно можно выделить 2 фактора, снижающих безопасность: ошибки в администрировании и ошибки в программировании веб-ресурса. С ними и будем разбираться. Советы и рекомендации даны применительно к Ubuntu/Debian. Подправив расположение файлов, их можно использовать и в любом другом дистрибутиве.
По умолчанию веб-сервер не скрывает название операционной системы, свою версию и информацию о некоторых установленных модулях. Все это злоумышленник может использовать при подготовке атаки. Чтобы сделать индейца менее болтливым, в конфигурационный файл apache2.conf (в некоторых дистрибутивах httpd.conf) необходимо добавить следующие строки:
ServerSignature Off
ServerTokens Prod
Директива ServerSignature отвечает за вывод информации внизу страницы, например страницы ошибки 404 или листинга файлов каталога. Что именно выводится, определяет ServerTokens, значение которой по умолчанию Full. При установке в Prod[uctOnly] будет выведено название сервера Apache без номера версии, без информации о модулях и версии операционной системы. Как вариант - можно сразу залезть в исходники (файл httpd.h в Apache 1.3 и ap_release.h в 2.x) и перед компиляцией подправить информацию по своему усмотрению.
В некоторых статьях рекомендуют запускать веб-сервер под отдельной учетной записью, приводя в качестве примера nobody. Запуск нескольких различных серверов под этим пользователем делает его не менее могущественным, чем root, поэтому для запуска любого сервера следует использовать отдельную учетную запись. Например, в Ubuntu и некоторых дистрибутивах это www-data:
$ sudo grep User /etc/apache2/apache2.conf
User www-data
Создаем пользователя, от имени которого будет запускаться и работать веб-сервер:
$ sudo adduser --no-create-home --disabled-password \
--disabled-login www-data
Затем в конфигурационном файле указываем:
User www-data
Group www-data
Теперь устанавливаем необходимые права:
$ sudo chown -R root:root /etc/apache2
$ sudo /etc/apache2 -type d | xargs chmod 755
$ sudo /etc/apache2 -type f | xargs chmod 644
Аналогичные команды выполняем для каталогов /var/log/apache2 (здесь хранятся журналы) и /var/www (соответствует DocumentRoot в Ubuntu). Нет никаких препятствий для того, чтобы убрать и право на чтение конфигурационных файлов Apache:
$ sudo chmod -R go-r /etc/apache2
По умолчанию индеец загружает довольно большое количество модулей. Чтобы просмотреть те, что скомпилированы вместе с Apache, используй apache2ctl –l или apache2 -l. К сожалению, лишнее из полученного списка убирается только путем полной пересборки индейца. Все динамически загружаемые модули (Dynamic Shared Object) можно просмотреть, введя:
$ sudo grep –R LoadModule /etc/apache2/*
Внимательно изучаем полученный список и в конфиге комментируем то, что не нужно. Вот список модулей, которые можно безболезненно отключить, естественно, убедившись, что они действительно нами не используются: mod_imap, mod_autoindex, mod_include, mod_info, mod_userdir, mod_status.
Apache поддерживает два типа аутентификации: basic и digest (обеспечивается модулем mod_auth_digest). В первом случае пароль передается в открытом виде. При использовании этого типа аутентификации у злоумышленника есть возможность перехватить логин и пароль и получить доступ ко всей «охраняемой» области. В digest передается Response, который представляет собой контрольную (обычно MD5) сумму от комбинации логина, пароля, запрашиваемого URL, метода HTTP и строки nonce, генерируемой сервером при ответе. Строка nonce позволяет сделать эту строку поистине уникальной. Для включения digest-аутентификации используем:
AuthType Digest
Одной из особенностей Apache является использование типового доступа, когда многие параметры либо устанавливаются по умолчанию, либо наследуются от родительского каталога. Чтобы избежать неприятностей, следует принудительно ограничить выполнение CGI-скриптов, SSI (Server Side Includes) включений, индексирования каталога и следование символическим ссылкам. Для этого в описании ресурса необходимо деактивировать следующие директивы:
Options All -Indexes -Includes –ExecCGI -FollowSymLinks
Либо отключить все сразу:
Options None
Чтобы злоумышленник не смог прочитать временные или конфигурационные файлы, используй следующую конструкцию:
<Files "(^\.ht|~$|\.bak$|\.BAK$)">
Order Allow,Deny
Deny from all
</Files>
Во избежание доступа к файлам, расположенным вне корневого каталога веб-сервера, нужно сначала принудительно ограничить доступ, а затем явно разрешить его только для требуемых каталогов. При нормальном раскладе подключившийся пользователь не сможет выйти за DocumentRoot, но для страховки стоит указать:
<Directory />
Order Deny,Allow
Deny from all
Options None
AllowOverride None
</Directory>
<Directory /var/www>
Order Allow,Deny
Allow from all
</Directory>
При необходимости значения директив AllowOverride и Options переопределяются в конкретном каталоге.
Другим способом не выпустить пользователя за DocumentRoot является использование chroot, речь о котором пойдет далее.
Не всегда веб-сервер или отдельный ресурс должны быть видны из сети. Например, используется прокси, либо это внутренний сервер компании. Если нет возможности закрыть доступ брандмауэром или использовать отдельный интерфейс, тогда доступ к ресурсу следует ограничить на основании IP-адреса или диапазона IP-адресов:
Order Deny,Allow
Deny from all
Allow from 192.168.0.0/24
Несмотря на то что директива Satisfy имеет всего два параметра - All и Any, она предоставляет возможность более гибко контролировать доступ к ресурсу. Например, нам нужно, чтобы доступ к приватной папочке могли получить только зарегистрированные пользователи и только с указанных адресов. Как это сделать? Очень просто:
Order Deny,Allow
Deny from all
Require valid-user
Allow from 192.168.0.0/24
Satisfy All
А для того чтобы пользователи внутренней сети могли вообще не регистрироваться, ставим вместо All Any.
Если изменить значения некоторых параметров, можно смягчить эффект DoS-атаки. Например, Timeout определяет, в течение какого времени сервер будет ожидать ответа клиента. В более ранних версиях Apache значение этой директивы равнялось 1200 секундам, затем оно было уменьшено до 300 сек. Мы можем спокойно его урезать, например, до 60 сек (это отразится только на пользователях с плохим соединением):
Timeout 60
По умолчанию размер клиентского запроса неограничен. Это обстоятельство также может быть использовано для организации DoS-атаки. Администратор в силах принудительно указать размер запроса в пределах от 0 (неограничен) до 2 147 483 647 байт (2 Гб) как для всего сервера, так и для отдельных ресурсов. Например, чтобы ограничить размер запроса 100 килобайтами, пишем:
LimitRequestBody 102400
Если клиент загружает на сервер некоторые данные (например, содержимое заполненных форм), то этот параметр следует скорректировать.
Для противодействия атакам «Отказ в обслуживании» существует целый ряд директив: LimitRequestFields, LimitRequestFieldSize и LimitRequestLine, MaxRequestsPerChild, MaxClients и некоторые другие. При необходимости, возможно, их значения стоит пересмотреть, выставив оптимальные для конкретных условий. Как вариант - для борьбы с DoS-атаками можно применять специальный модуль mod_evasive (
www.zdziarski.com/projects/mod_evasive).
Устанавливаем ModSecurity
Значительно повысить защищенность веб-ресурса можно с помощью ModSecurity. Этот проект, созданный Иваном Ристиком в 2003 году, позволяет защищать веб-приложения как от известных, так и от еще неизвестных атак. ModSecurity работает в виде модуля веб-сервера Apache, либо в автономном режиме. Его использование прозрачно, установка и удаление не требуют изменения настройки сервисов и сетевой топологии. Кроме того, при обнаружении уязвимого места теперь нет необходимости править исходные коды, создавая новые ошибки, - достаточно добавить правило, запрещающее вредоносную комбинацию.
В репозитарии некоторых дистрибутивов уже включен нужный пакет, следует поискать что-то вроде mod-security. В Debian достаточно добавить в /etc/apt/sources.list новый репозитарий:
deb http://etc.inittab.org/~agi/debian/libapache-mod-security2/ etch/
И затем можно инсталлировать:
# apt-get update
# apt-get install libapache2-mod-security2
Установить ModSecurity из исходных текстов тоже просто. Для сборки необходимы заголовочные файлы Apache, поэтому забираем исходные тексты веб-сервера из репозитария или с сайта проекта:
$ sudo apt-get apache2-src libxml2-dev
Если используются исходные тексты, взятые с сайта проекта, то перед компиляцией mod_security следует сконфигурировать веб-сервер командой ./configure с нужными параметрами (для работы модуля понадобится '--enable-unique-id'), а затем выполнить следующие действия:
$ wget –c www.modsecurity.org/download/modsecurity-apache_2.1.1.tar.gz
$ tar xzvf modsecurity-apache_2.1.1.tar.gz
$ cd modsecurity-apache_2.1.1/apache
2
Теперь редактируем Makefile:
$ mcedit Makefile
# Меняем apxs на apxs2 (APache eXtenSion tool)
APXS = apxs2
# Каталог с исходными текстами Apache
top_dir = /home/grinder/source/httpd-2.2.4
Компилируем модуль, останавливаем Apache, устанавливаем модуль:
$ make
$ sudo /etc/init.d/apache2 stop
$ sudo make install
В конфигурационный файл веб-сервера добавляем две строчки:
LoadFile /usr/lib/libxml2.so
LoadModule security2_module /usr/lib/modules/mod_security2.so
Для удобства все настройки mod_security лучше вынести в отдельный файл, взяв за пример готовый шаблон и подключив его в apache2.conf директивой:
Include /etc/apache2/mod_security.conf
Копируем шаблон и правим:
$ sudo cp modsecurity-apache_2.1.1/modsecurity.conf-minimal /etc/apache2/mod_security.conf
$ sudo mcedit /etc/apache2/mod_security.conf
<IfModule mod_security2.c>
SecRuleEngine On
...
SecFilterDefaultAction "deny,log,status:430"
</IfModule>
Активируем модуль mod_unique_id:
$ sudo a2enmod unique_id
Теперь можно запускать Apache:
$ sudo /etc/init.d/apache2 start
Если все работает нормально, можно добавлять правила. Команда разработчиков уделяет большое внимание усовершенствованию кода mod_security, оставляя создание правил на откуп пользователю, поэтому оригинальный конфигурационный файл имеет всего несколько рулесетов, находящихся в подкаталоге rules. На сайте проекта лежит отдельный архив modsecurity-core-rules. Для подключения входящих в его состав правил достаточно скопировать все conf-файлы в каталог /etc/apache2 и в секции mod_security2.c указать:
Include rules/*.conf
Include rules/blocking/*.conf
Подключать все сразу не стоит. Некоторые правила требуют редактирования под конкретные условия, лучше разбираться постепенно.
Защищаем PHP с помощью Suhosin
Задача проекта Suhosin (
www.hardened-php.net/suhosin) - защита серверов и пользователей от целого ряда известных проблем в приложениях и ядре PHP, так как safe_mode помогает далеко не всегда. Сам Suhosin состоит из двух независимых частей, которые могут использоваться как раздельно, так и совместно. Первая часть – небольшой патч к ядру, осуществляющий низкоуровневую защиту структур данных от переполнения буфера, уязвимости форматной строки и ошибок в реализации функции realpath, присущей некоторым платформам, а также от других потенциальных уязвимостей ядра PHP. Вторая часть реализована в виде расширения, которое фактически и осуществляет всю основную защиту, при необходимости его очень просто доустановить в уже рабочую систему без полной пересборки PHP. С полным списком возможностей можно познакомиться на сайте проекта
www.hardened-php.net/suhosin/a_feature_list.html.
В случае нарушения установленных правил возможна блокировка переменных, отсылка определенного HTTP-кода ответа, перенаправление браузера пользователя, выполнение другого PHP-скрипта. Все события заносятся в журналы, для чего может использоваться syslog, свой модуль или внешний скрипт. Последние версии расширения Suhosin совместимы практически со всеми версиями PHP.
Установка Suhosin включает в себя 2 этапа: наложение патча на PHP с последующей его пересборкой и компиляция модуля расширения. Хотя возможна и сборка со встроенным расширением. Чтобы не было проблем с зависимостями, в Ubuntu перед началом установки рекомендую дать команду
sudo apt-get build-dep php5.
Скачиваем PHP, затем патч suhosin под используемую версию PHP и модуль расширения. Все это распаковываем, накладываем патч и компилируем:
$ tar xvjf php-5.2.3.tar.bz2
$ gunzip suhosin-patch-5.2.3-0.9.6.2.patch.gz
$ cd php-5.2.3
$ patch -p 1 -i ../suhosin-patch-5.1.6-0.9.5.patch
$ ./configure [--enable-so и другие параметры при необходимости]
$ make
$ make test
$ sudo make install
Теперь собираем модуль расширения:
$ tar xzvf suhosin-0.9.20.tgz
$ cd suhosin-0.9.20
$ phpize
$ ./configure --prefix=/usr/lib/php5/20060613+lfs/
$ make
$ make test
$ sudo make install
Проверить сборку можно, введя команду:
$ php –v
PHP 5.2.3 with Suhosin-Patch 0.9.6.2 (cli) (built: Jul 26 2007 11:35:13)
Все настройки Suhosin производятся в файле php.ini. Патч поддерживает только опции регистрации, поэтому первой записью обязательно подключаем модуль suhosin.so (он должен быть виден переменной LD_RUN_PATH):
extension=suhosin.so
После установки Suhosin будет работать с настройками по умолчанию, которые достаточны, но, возможно, не оптимальны для твоей конфигурации.
Строим chroot
Для построения chroot-окружения нам понадобится модуль mod_chroot (core.segfault.pl/~hobbit/mod_chroot). В репозитарии Ubuntu он присутствует:
$ sudo apt-get install libapache2-mod-chroot
Параллельно будет установлен пакет mod-chroot-common, содержащий документацию (/usr/share/doc/mod-chroot-common). Для самостоятельной сборки mod_chroot достаточно распаковать свежескачанный архив и ввести команду apxs2 -cia mod_chroot.c. Далее следует указать, что рабочий каталог теперь является корневым, то есть в apache2.conf прописываем:
<IfModule mod_chroot.c>
LoadFile /lib/libgcc_s.so.1
PidFile /var/run/httpd.pid
ChrootDir /var/www
DocumentRoot /
</IfModule
>
Значение DocumentRoot изменяем с «/var/www» на «/» и все ссылки на ресурсы даем относительно корня. В apache2.conf не забываем подключить модуль:
LoadModule chroot_module /usr/lib/apache2/modules/mod_chroot.so
Либо в Ubuntu правильнее:
$ sudo a2enmod mod_chroot
При использовании Apache2 понадобится создать каталог для PID-файла.
$ sudo mkdir -p /var/www/var/run
$ sudo chown -R root:root /var/www/var/run
$ sudo ln -s /var/www/var/run/httpd.pid /var/run/httpd.pid
Перезапускаем индейца и проверяем работу.
Это далеко не все, что можно сделать для защиты LAMP. Также следует учесть, что приведенные советы не могут гарантировать абсолютной безопасности (такого просто не бывает в природе) хотя несколько уменьшить риск они позволяют. Кроме того, в некоторых средах часть параметров может вызывать проблемы или влиять на производительность. Поэтому к их использованию следует подходить осторожно, вводя изменения постепенно и тщательно тестируя результат. Универсальный совет по-прежнему один: следует изучать документацию и включать только то, что нужно.c