Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #133, ЯНВАРЬ 2010 г.

Остаться на плаву. Обвески для Web-сервера, без которых не обойтись

Евгений Зобнин (j1m@synack.ru)


Сегодня Web-серверы играют важнейшую роль в интернет-инфраструктуре. На них держится все, начиная с сайта Марины Петровны с посещаемостью 3 человека в месяц и заканчивая высоконагруженными проектами YouTube и Twitter. От производительности и безопасности Web-серверов во многом зависит конкурентоспособность сервиса, но чтобы выжать из сервера все, недостаточно одной только тонкой настройки Apache и PHP.

eAccelerator

Исполнение PHP-скриптов очень сложная задача, создающая огромные нагрузки на Web-сервер. По сути, именно разбор скриптов зачастую является наиболее затратным процессом, происходящим на машине, где крутится сервис. При этом не все Web-дизайнеры и программисты знают, что процесс исполнения PHP-кода (как, впрочем, и кода на любом другом современном интерпретируемом языке) состоит из двух этапов: трансляция кода PHP в байткод виртуальной машины и непосредственное исполнение байткода.

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

eAccelerator (eaccelerator.net) - это PHP-ускоритель, основанный на коде проекта Turck MMCache (sourceforge.net/projects/turck-mmcache). Он не только кэширует PHP-код в виде байткода, но и производит его оптимизацию, позволяет хранить кэш на диске и обладает развитой системой настроек.

eAccelerator распространяется в виде PHP-модуля, но доступен в репозиториях далеко не всех дистрибутивов, поэтому мы установим его из исходных текстов. Для этого получим последнюю стабильную версию модуля:

$ cd ~/tmp
$ wget http://bart.eaccelerator.net/source/0.9.5.3/eaccelerator-0.9.5.3.tar.bz2
$ tar -xjf eaccelerator-0.9.5.3.tar.bz2
$ cd eaccelerator-0.9.5.3

Установим пакеты, необходимые для сборки ПО из исходников (gcc, binutils и т.д.):

$ sudo apt-get install build-essential

Также нам понадобится пакет php-devel (php5-devel), содержащий утилиту phpize:

$ sudo apt-get install php5-devel

Запускаем процесс сборки:

$ export PHP_PREFIX="/usr"
$ $PHP_PREFIX/bin/phpize
$ ./configure \
--enable-eaccelerator=shared \
--with-php-config=$PHP_PREFIX/bin/php-config
$ make
$ sudo make install

Далее узнаем местоположение файла php.ini (в разных дистрибутивах он находится в разных местах):

$ php -i | grep php.ini

И добавляем в него следующие строки:

$ sudo vi /etc/php5/apache2/php.ini

extension="eaccelerator.so"
// В дисковом кэше будут храниться данные сессий, контент и прекомпилированный код
eaccelerator.cache_dir="/tmp/eaccelerator"
// Включаем eAccelerator (данная опция может быть полезна, если нужно отключить кэширование для одного или нескольких виртуальных хостов, пример: "php_admin_value eaccelerator.enable 0" в соответствующей секции vhost конфига Web-сервера)
eaccelerator.enable="1"
// Включаем оптимизатор, который поможет ускорить выполнения кода
eaccelerator.optimizer="1"
// При каждом обращении проверяем время модификации скрипта, чтобы определить, нуждается ли он в перекомпиляции или нет
eaccelerator.check_mtime="1"
// Отключаем журналирование отладочной информации
eaccelerator.debug="0"
// С помощью этой директивы можно определить, какие PHP-файлы могут быть кэшированы (например, "*.php *.phtml"), задаем все:
eaccelerator.filter=""
// Количество памяти (shared memory), выделяемой для кэширования PHP-скриптов
eaccelerator.shm_size="16"
eaccelerator.shm_max="0"
eaccelerator.shm_ttl="0"
eaccelerator.shm_prune_period="0"
eaccelerator.shm_only="0"
// Устанавливаем максимальный уровень сжатия для контентного кэширования
eaccelerator.compress="1"
eaccelerator.compress_level="9"

Создаем каталог для файлов кэша:

$ mkdir /tmp/eaccelerator
$ chmod 0777 /tmp/eaccelerator

Перезапускаем apache:

$ sudo /etc/init.d/apache2 restart

Вот и все. Теперь можно выполнить замер производительности. Разработчики утверждают, что ее прирост может достигать 10-ти раз, однако по личному опыту могу сказать, что зачастую эта цифра становится еще выше.

IonCube PHP Encoder

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

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

Для установки настоящей, стойкой защиты на PHP-скрипты принято применять протекторы, наиболее известные из которых называются Zend Optimizer и IonCube PHP Encoder. Первый - это платный проект разработчиков PHP, защитные техники которого однажды уже показали свою нестойкость (в результате доверие к продукту упало). Второй разрабатывается компанией IonCube, обладает в три раза меньшей ценой и использует гораздо более изощренные техники сокрытия оригинального кода. Ему и будет посвящена остальная часть раздела.

Основные характеристики IonCube PHP Encoder:

  • Трансляция PHP-скриптов в байткод (спецификации которого закрыты).
  • Шифрование других типов файлов (например XML, шаблоны Smarty, изображения).
  • Генерация лицензионных файлов для ограничения доступа к закодированным файлам (Pro/Cerberus Encoder).
  • Обфускация байткода после компиляции.
  • Возможность получать файлы форматов ASCII или Binary.
  • Использование цифровых сигнатур для защиты скриптов от модификации.
  • Защита от вызова закодированных файлов из неавторизованных файлов.
  • Совместимость с открытыми расширениями, такими как mmcache и eAccelerator.
  • Возможность создания триальных скриптов, которые перестают работать после истечения определенного срока (Pro/Cerberus Encoder).
  • Защита файлов от запуска на машинах с определенными IP/MAC-адресами и DNS-именами (Pro/Cerberus Encoder).
  • Интеграция с IonCube Package Foundry.
  • Возможность вставки текстовых аннотаций и других данных в закодированные файлы.
  • Чрезвычайно быстрое кодирование (благодаря чему возможно кодирование на лету).

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

Для восстановления кода, зашифрованного PHP Encoder, взломщику придется вслепую произвести дизассемблирование байткода виртуальной машины (естественно, ни документации, ни исходного кода ВМ никто ему не даст), затем расшифровать зашифрованные данные, разобрать и подчистить код от обфускации и только после этого попытаться восстановить исходный PHP-код. При этом даже если взломщик попытается просто изменить код (например, для отключения проверки на регистрацию), приложение перестанет функционировать из-за несовпадения контрольной суммы в цифровой подписи. Тогда придется менять и ее.

Не возьмусь говорить, что взломать PHP-скрипты, закодированные PHP Encoder, невозможно, но это как раз тот случай, когда затраты не окупают результатов.

IonCube PHP Encoder доступен в виде триальной версии, которую можно получить, следуя инструкциям, опубликованным на странице www.ioncube.com/encoder_eval_download.php. Для установки достаточно выполнить пять шагов:

1. Зарегистрироваться и скачать последнюю версию PHP Encoder.

2. Распаковать полученный архив и скопировать загрузчик в каталог PHP-модулей (он может быть другим):

$ cd ~/tmp
$ tar -xzf ioncube_encoder_evaluation.tar.gz
$ cd ioncube_encoder_evaluation
$ sudo cp loaders/ioncube_loader_lin_5.3.so /usr/lib/php5/20060613+lfs/

3. Добавить в секцию [PHP] файла php.ini строку:

zend_extension = /usr/lib/php/modules/ioncube_loader_lin_5.3.so

4. Перезапустить индейца:

$ sudo /etc/init.d/apache2 restart

5. Закодировать файлы с помощью команды ioncube_encoder5 (или просто ioncube_encoder в случае PHP4):

$ ~/tmp/incube_encoder5 --obfuscate all оригинал.php -o закодированный_скрипт.php

Больше информации об аргументах командной строки ioncube_encoder ты узнаешь из официального руководства пользователя.

Web Optimizer

Любой web-дизайнер, разработчик или системный администратор, хоть раз занимавшийся оптимизацией содержимого веб-сайта, знает, что этот процесс требует применения множества самых различных техник и кучу времени, которое приходится тратить на рутинные, однообразные действия. Большую часть этих действий, конечно, можно оптимизировать с помощью скриптов и шаблонов конфигурационных файлов, однако различные CMS и Web-сервера могут внести в подход различия, скрипты придется дорабатывать, а конфиги переписывать.

Наверное, именно такие мысли посещали головы российских web-разработчиков из ООО «ВЕБО» незадолго до того, как они приступили к разработке автоматизированной системы оптимизации контента. В результате их работы появился Web Optimizer (code.google.com/p/web-optimizator) - набор PHP-скриптов, которые выполняют всю рутинную работу по оптимизации контента Web-сайта на лету.
Надо сказать, система получилась весьма функциональная, она уже умеет делать следующее:

  • Объединение внешнего и встроенного кода.
  • Минимизация файлов (удаление из кода комментариев, незначащих пробелов, символов табуляции, переносов строк с целью уменьшения объема файлов и ускорения их загрузки).
  • gzip-сжатие файлов.
  • Клиентское кэширование.
  • Серверное кэширование.
  • Поддержка множественных хостов.
  • Автоматическое создание CSS Sprites.
  • Автоматическое применение Data:URI.
  • Ненавязчивая загрузка JavaScript.

Перефразируя слова авторов, можно сказать, что пользователям Web Optimizer больше не придется натравливать компрессор на каждый имеющийся js-файл, удалять комментарии из HTML-файлов и вытягивать их в одну строку, настраивать кэширование и проделывать многие другие рутинные операции. Все это сделает полностью автоматизированная система, которая проста в установке и не требовательна к ресурсам.

Опять же, если верить словам разработчиков (подкрепленным внушительной таблицей с замерами производительности), то среднее увеличение скорости загрузки страниц, обработанных Web Optimizer, составляет примерно 250% (а в некоторых случаях и до 500%). "Сайты ускоряются в среднем в 2,5 раза (+21 в оценке YSlow, -34% в размере, -43% в количестве внешних объектов)".

Для установки Web Optimizer следует выполнить три простых шага:

1. Обзавестись Web-сервером с поддержкой PHP и SSH-доступом (FTP тоже подойдет).

2. Получить последнюю версию Web Optimizer:

$ wget http://web-optimizator.googlecode.com/files/web-optimizer.v0.6.6.zip

3. Распаковать архив в корневой каталог Web-сервера:

$ cd /var/www
$ sudo unzip /путь/к/web-optimizer.v0.6.6.zip

Чтобы Web Optimizer смог сохранять кэшированные версии обработанных им файлов, следует установить права на запись на файл web-optimizer/config.webo.php и каталог web-optimizer/cache для пользователя, под которым работает Web-сервер:

$ sudo chmod +w web-optimizer/config.webo.php
$ sudo chmod -R +w web-optimizer/cache
$ sudo chmod -R www-data:www-data web-optimizer/cache

Все, теперь открываем страницу http://сайт/web-optimizer/index.php в браузере и приступаем к настройке фреймворка. Самый простой путь - довериться системе, ввести логин и пароль администратора и нажать кнопку "Быстрая установка". Web Optimizer пройдется по цепочке расположенных на Web-сервере файлов и создаст их закэшированные сжатые версии. Также он произведет необходимую для последующей работы системы модификацию оригиналов или (если они недоступны для записи) выведет инструкцию об их изменении.
Нажав на оранжевую стрелку в правой стороне экрана, можно произвести так называемую "Обычную установку", которая включает в себя возможность ручного указания опций оптимизации.

PHP Intrusion Detection System (PHPIDS)

Многие из нас применяют системы обнаружения вторжений на своих серверах. Некоторым достаточно сетевых IDS, другие также устанавливают и локальные, однако мало кто применяет Web IDS, предназначенные для "отлова" попыток взлома Web-сайтов.
PHPIDS одна из представительниц таких систем. Это легкая в использовании, быстрая система обнаружения атак, которая умеет ловить разные виды XSS, SQL-инъекции, расщепления запроса (HTTP Response Splitting), проходы по каталогам (Directory traversing), RFE/LFI, DoS, LDAP-инъекции и многое другое. Причем это не просто слова, а реально работающая система, которая способна отбить охоту взлома у 99% злоумышленников. Для сомневающихся открыта специальная страничка, перейдя на которую, любой желающий может попробовать обмануть систему.

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

Установить систему очень просто:

1. Скачиваем последнюю версию PHPIDS с офсайта и распаковываем:

$ cd /tmp
$ wget http://php-ids.org/files/phpids-0.6.3.1.tar.bz2
$ tar -xjf phpids-0.6.3.1.tar.bz2
$ sudo mkdir /var/phpids
$ sudo mv lib /var/phpids
$ cd /var/phpids/lib/IDS
$ sudo chown -R www-data:www-data tmp

Обрати внимание, что мы намеренно установили PHPIDS рядом с корневым каталогом Web-сервера (а не в него). Так мы изолировали его каталоги от просмотра посторонними.

2. Открываем конфигурационный файл Config/Config.ini.php и вносим в него необходимые изменения. На данном этапе достаточно модифицировать всего одну опцию:

base_path = /var/phpids/lib/IDS

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

3. Создаем файл phpids.php в корневом каталоге Web-сервера и записываем в него следующее:

$ sudo vi /var/www/phpids.php

set_include_path(
get_include_path()
. PATH_SEPARATOR
. '/var/phpids/lib'
);

if (!session_id()) {
session_start();
}

require_once 'IDS/Init.php';

try {

/*
* Что будем сканировать?
*/
$request = array(
'REQUEST' => $_REQUEST,
'GET' => $_GET,
'POST' => $_POST,
'COOKIE' => $_COOKIE
);

$init = IDS_Init::init(dirname(__FILE__) . '/var/phpids/lib/IDS/Config/Config.ini.php');

/*
* Инициализируем PHPIDS и читаем результаты проверки
*/
$ids = new IDS_Monitor($request, $init);
$result = $ids->run();

/*
* Если обнаружена атака - заносим результат в логи и завершаем работу
*/
if (!$result->isEmpty()) {
echo $result;

require_once 'IDS/Log/File.php';
require_once 'IDS/Log/Composite.php';

$compositeLog = new IDS_Log_Composite();
$compositeLog->addLogger(IDS_Log_File::getInstance($init));
$compositeLog->execute($result);

die('Attack detected');
}
}

4. Чтобы PHPIDS проверял все наши PHP-скрипты, добавим файл phpids.php к каждому из них. Для этого откроем php.ini и внесем в него следующую строку:

auto_prepend_file /var/www/phpids.php

То же самое можно сделать при помощи .htaccess:

php_value auto_prepend_file /var/www/phpids.php

5. Перезапускаем апач:

$ sudo /etc/init.d/apache2 restart

Это все. Теперь можешь протестировать PHPIDS, набрав в адресной строке браузера что-нибудь вроде "http://сайт/phpids.php?test=%22%3EXXX%3Cscript%3Ealert(1)%3C/script%3E".

Интересные Apache-модули

Этот раздел посвящен сторонним Apache-модулям, которые ты можешь скачать из Интернета и подключить к своему Web-серверу. Среди них есть как известные и повсеместно используемые модули, так и необычные проекты.

  • mod_connection_limit (code.google.com/p/mod-connection-limit/) - ограничение на одновременное количество подключений к Web-серверу.
  • mod_vhost_limit (apache.ivn.cl) - индивидуальный контроль пропускной способности и количества подключений для каждого виртуального хоста.
  • mod_ipenv (mod-ipenv.sourceforge.net) - установка и снятие переменных окружения на основе IP-адресов и DNS-имен клиентов.
  • mod_access_dnsbl (www.apacheconsultancy.com/modules/mod_access_dnsbl/) - контроль доступа, основанный на черных и белых списках DNSBL.
  • mod_cluster (jboss.org/mod_cluster/) - динамический балансировщик нагрузки. Требует mod_proxy.
  • mod_qos - реализация QoS (mod-qos.sourceforge.net), возможность использования разных приоритетов обработки в зависимости от типа запроса.
  • mod_captcha (sourceforge.net/projects/mod-captcha/) - реализация капчи в виде Apache-модуля. Для своей работы требует библиотеки GD 2.x и Berkeley DB 4.5.
  • mod_swf2html (ilovedaemon.net/hanai/apache/mod_swf2html/) - конвертирует swf-файлы в HTML для того, чтобы они могли быть проиндексированы поисковыми машинами.
  • mod_txt (apache.webthing.com/mod_txt/) - показывает текстовые файлы, добавляя к ним хидер и футер (так же, как это сделано при отображении каталогов).
  • mod_validator (apache.webthing.com/mod_validator/) - валидатор HTML, XML и SGML.
  • mod_bash (www.autistici.org/bakunin/mod_bash/) - интерпретатор bash, встроенный в Apache.

Что еще?

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

INFO

Обфускация — приведение исходного текста или исполняемого кода программы к виду, сохраняющему ее функциональность, но затрудняющему анализ, понимание алгоритмов работы и модификацию при декомпиляции. Другими словами, запутывание кода.

PhpSecInfo (phpsec.org/projects/phpsecinfo/) добавляет функцию phpsecinfo(), предоставляющую информацию о безопасности PHP-окружения и советы по ее улучшению.

Содержание