Intrusion Detection For PHP Applications With PHPIDS

Original author: Falko Timme
  • Translation
Эта статья покажет как настроить PHPIDS. PHPIDS (PHP-Intrusion Detection System) — это легко используемая, хорошо структурированная, быстрая прослойка для анализа безопасности ваших приложений. IDS — не является прослойкой для анализа данных, введенных пользователем, он только распознает, когда пытаются атаковать ваш сайт. на основе набора проверенных и оттестированных правил каждой атаке сопоставлен рейтинг ее опасности. Это позволит легко сохранять статистику по атакам или отсылать уведомления для команды разработчиков.


Предисловие
Примеры для данной статьи делались на Debian Etch LAMP с Apache версии 2 и PHP5, IP — 192.168.0.100.
Пользователь и группа Apache — www-data. Путь к php.ini — /etc/php5/apache2/php.ini. В качестве document root для виртуального хоста использовался /var/www/web1/web

Установка PHPIDS
Из изображений безопасности я установил PHPIDS вне document root, поэтому я создал /var/www/web1/phpids:

Затем я установил PHPIDS (на момент установки последняя версия была 0.4.7).
cd /tmp
wget php-ids.org/files/phpids-0.4.7.tar.gz
tar xvfz phpids-0.4.7.tar.gz
cd phpids-0.4.7
mv lib/ /var/www/web1/phpids/
cd /var/www/web1/phpids/lib/IDS
chown -R www-data:www-data tmp/


Далее я переконфигурировал Config.ini:
cd Config/
vi Config.ini


Я использую конфигурацию по умолчанию, и все что надо сделать — это поменять пути
; PHPIDS Config.ini

; General configuration settings

; !!!DO NOT PLACE THIS FILE INSIDE THE WEB-ROOT IF DATABASE CONNECTION DATA WAS ADDED!!!

[General]

filter_type = xml
filter_path = /var/www/web1/phpids/lib/IDS/default_filter.xml
tmp_path = /var/www/web1/phpids/lib/IDS/tmp
scan_keys = false

exceptions[] = __utmz
exceptions[] = __utmc

; If you use the PHPIDS logger you can define specific configuration here

[Logging]

; file logging
path = /var/www/web1/phpids/lib/IDS/tmp/phpids_log.txt

; email logging

; note that enabling safemode you can prevent spam attempts,
; see documentation
recipients[] = test@test.com.invalid
subject = «PHPIDS detected an intrusion attempt!»
header = «From: info@php-ids.org»
safemode = true
allowed_rate = 15

; database logging

wrapper = «mysql:host=localhost;port=3306;dbname=phpids»
user = phpids_user
password = 123456
table = intrusions

; If you would like to use other methods than file caching you can configure them here

[Caching]

; caching: session|file|database|memcached|none
caching = file
expiration_time = 600

; file cache
path = /var/www/web1/phpids/lib/IDS/tmp/default_filter.cache

; database cache
wrapper = «mysql:host=localhost;port=3306;dbname=phpids»
user = phpids_user
password = 123456
table = cache

; memcached
;host = localhost
;port = 11211
;key_prefix = PHPIDS
;tmp_path = /var/www/web1/phpids/lib/IDS/tmp/memcache.timestamp


Использование PHPIDS

Сейчас мы создадим /var/www/web1/web/phpids.php, который будет использовать PHPIDS
set_include_path(
get_include_path()
. PATH_SEPARATOR
. '/var/www/web1/phpids/lib'
);

require_once 'IDS/Init.php';
$request = array(
'REQUEST' => $_REQUEST,
'GET' => $_GET,
'POST' => $_POST,
'COOKIE' => $_COOKIE
);
$init = IDS_Init::init('/var/www/web1/phpids/lib/IDS/Config/Config.ini');
$ids = new IDS_Monitor($request, $init);
$result = $ids->run();

if (!$result->isEmpty()) {
// Take a look at the result object
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);
}


После этого введите в своем браузере 192.168.0.100/phpids.php, и вы увидите пустую страницу.
Однако если вы добавите различные параметры, например 192.168.0.100/phpids.php?test=%22%3EXXX%3Cscript%3Ealert(1)%3C/script%3E, PHPIDS определит их и напечатает результат в браузер



Сейчас мы сделаем так, чтобы PHPIDS тиспользовался в каждом вашем скрипте. Конечно, вам не придется модифицировать каждый файл php в вашей системе. Мы скажем php, чтобы он запускал PHPIDS при каждом старте скрипта. Мы сделаем это используя auto_prepend_file параметр. Для этого сделаем модификацию в php.ini или .htaccess file
auto_prepend_file = /var/www/web1/web/phpids.php
или для .htaccess
php_value auto_prepend_file /var/www/web1/web/phpids.php

Перепустите ваш Apache (для случая с модификацией php.ini)

Создайте файл info.php с содержимым
phpinfo();

Напишите в браузере 192.168.0.100/info.php и вы увидите нормальный вывод команды phpinfo()
теперь добавьте параметры, например 192.168.0.100/info.php?test=%22%3EXXX%3Cscript%3Ealert(1)%3C/script%3E
и вы увидите



PHPIDS запишет эти данные в /var/www/web1/phpids/lib/IDS/tmp/phpids_log.txt
«192.168.0.200»,2008-06-04T17:36:08+02:00,54,«xss csrf id rfe lfi»,«REQUEST.test=%5C%22%3EXXX%3Cscript%3Ealert%281%29%3C%2Fscript%3E GET.test=%5C%22%3EXXX%3Cscript%3Ealert%281%29%3C%2Fscript%3E»,
"%2Finfo.php%3Ftest%3D%2522%253EXXX%253Cscript%253Ealert%281%29%253C%2Fscript%253E"


Теперь, просмотрев записи. вы увидите, что хакер пытался что-то сделать с вашим приложением.

Для добавления другого уровня безопасности для вашего приложения вы можете остановить скрипт, если PHPIDS обнаружил атаку:
мы можем добавить что-то похожее на это
die('

Go away!

');
в секцию if (!$result->isEmpty()) {} в файле /var/www/web1/web/phpids.php script
set_include_path(
get_include_path()
. PATH_SEPARATOR
. '/var/www/web1/phpids/lib'
);

require_once 'IDS/Init.php';
$request = array(
'REQUEST' => $_REQUEST,
'GET' => $_GET,
'POST' => $_POST,
'COOKIE' => $_COOKIE
);
$init = IDS_Init::init('/var/www/web1/phpids/lib/IDS/Config/Config.ini');
$ids = new IDS_Monitor($request, $init);
$result = $ids->run();

if (!$result->isEmpty()) {
// Take a look at the result object
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('

Go away!

');
}


Если нет атаки скрипт продолжит выполнение, иначе хакер увидит это


коментарий переводчика
Указанные выше примеры можно использовать и на боевых системах. Однако для этого потребуется некое преобразование
$init = IDS_Init::init('/var/www/web1/phpids/lib/IDS/Config/Config.ini');

так как каждый раз незачем загружать файл настроек из файла, а заменить его написанным заранее классом
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 20

    0
    Картинки битые.
      0
      у меня все показывает, но все равно проверю
      –1
      Интересное решение. Но поможет не всегда и не всем.
        0
        Как по-мне, лучше фильтровать данные по мере их поступления. И фильтровать по правилам, которые нужны именно Вам.
          0
          где вы увидели фильтрацию?
            0
            А как по-Вашему называется предотвращение xss и прочих в get-запросах?
              0
              ну если фильтрацией назвать тупой die, то да
              если под фильтрацией подразумевать, фильтрацию переменных(приведение типов, выкидывание тэгов и т.д., то нет)
          0
          имхо подобные PHPIDS системы - это костыли. Система сама должна обеспечивать свою безопасность. А такие штуки прикручивать можно было неколько лет назад, когда ещё не настолько хорошо были освещены различные методы атак на веб-приложения. К тому же централизованная фильтрация очень неудобна.
            0
            Вы не внимательно прочитали статью.
            1) В начале описано, что это никакая не фильтрация
            2) Зачем изобретать собственный велосипед, если можно взять чужую библиотеку и модифицировать для себя (не надо только далее писать, что порой легче написать свое, чем пользоваться чужим)
              0
              вы злоупотребляете выражением "изобретать велосипед"
              если разработчик системы не в состоянии ВАЛИДИРОВАТЬ данные, которые приходят в его приложение, то никакие заглушки не помогут
              правило очень простое — знаем какие данные ждем, принимаем и проверяем
              удачи
                0
                мой опыт работы показывает, что все предусмотреть не возможно
                :-)
                  0
                  в статье описана "защита" от инъекций
                  защита от инъекций — валидирование данных
                  вы всегда знаете какие данные к вам ДОЛЖНЫ прийти
                  что значит невозможно предусмотреть?
                  как-то не вяжется это с опытом работы :)
                    0
                    Язвительное замечание. "Все предусмотреть не возможно" - относится к глобальному, а не к данной статье. При долговременной работе приложения безусловно вы переберете практически все варианты использования. Помню курсе на третьем было у нас какое-то приложение, которое по всем описанным на UML сценариям (или не на UML) пыталось построить множество сценариев использования.
                    По поводу Вашего ответа, до определенного момента времени (выхода расширения filter) многие не понимали какой именно должна быть фильтрация, как и в какой последовательности применять strip_tags,htmlentities,set_type...а чем моя статья не помощь для них, а залезть внутрь посмотреть хотя бы правила. Один известный мне проект, достаточно долго работал, там было огромно количество пользователей, казалось бы все оттестировано, и в один прекрасный день он столкнулся с xss.
                      0
                      поднял вам карму за вредость
              0
              А эта штука не может ложно сработать?
                0
                Вопрос о производительности сего. Не будет ли по производительней mod_security или snort+snortsam перед веб сервером?
                  0
                  Да, я как-то тоже не сторонник такого рода систем, да и насчет "все предусмотреть невозможно" - тоже имхо неправильная позиция, можно предусмотреть, если специально этим озадачиться, иже введя например доп.абстракцию, одна лишняя функция/метод, в которую отдельно передаются запрос и параметры оного (с последующей обработкой оных) - уже избавляет от проблем с sql-инъекциями, также можно централизовать обработку данных, пришедших с форм, из адресной строки и т.п., да и вообще проверка наличия того "что нельзя" всегда будет уступать проверке на соответствие тому "что можно".
                    0
                    Вышла новая версия PHPIDS 0.5
                    http://php-ids.org/2008/06/07/phpids-05-has-landed/
                    Раз развивается проект значит кому то нужно, имхо если бы все производители использовали эту идс, то было бы меньше багов.
                      0
                      Подключил в один из своих проектов, благодаря статье.
                      Было большой ошибкой с моей стороны ставить die();
                      Целый час вдвоём пытались понять почему падает отправка формы.
                      Довольно быстро поняли, что это из-за отправляемой кавычки.
                      Но то поле могло содержать кавычку и ничего страшного бы не произошло.
                      Рыли в сторону падения sql-запроса.
                      Когда через час я догадался глянуть почту...

                      В-общем, не ставьте die(). =)
                        0
                        Ок, насколько тяжелее становится запросы? какова вероятность вылета какой нибудь ошибки, если клиент добавит какой нибудь подозрительный линк не ведая про то что он подозрительный, сколько хостеров готовы поменять php.ini?

                        Only users with full accounts can post comments. Log in, please.