Установка и настройка Apache application firewall – mod_security

Как установить модуль mod_security на веб сервер Apache на примере Debian/Ubuntu

Mod security - это модуль Apache с открытым исходным кодом реализующий функцию межсетевого экрана для веб приложений Web Application Firewall (WAF). Он также доступен для Nginx и IIS. В состав дистрибутива входит набор правил Core Rule Set (CRS) для защиты от таких атак как: SQL инъекции, cross site scripting, Trojans, bad user agents, session hijacking и многих других уязвимостей. Поддерживается гибкий движок создания собственных правил. Для веб сервера Apache поставляется как дополнительный модуль, что упрощает установку и конфигурирование.
security_firewall

Для установки вам потребуется как минимум LAMP сервер.

1. Установка mod_security
2. Настройка mod_security
3. Проверка на SQL Injection
4. Настройка правил
5. Создание собственных правил mod_security
6. Отключение действия mod_security для определенных виртуальных хостов и директорий
7. Обновление правил mod_security
8. Web консоль mod_security "WAF-FLE"

Установка mod_security

Modsecurity доступен в стандартном репозитории Debian/Ubuntu:

Для начала неплохо обновить систему:

aptitude update
aptitude upgrade

Внимание! Следующая команда автоматически перезагрузит apache.

apt-get install libapache2-modsecurity

Проверка правильности установки mod_security.

apachectl -M | grep --color security

Вы должны увидеть модуль с именем security2_module (shared) это означает, что модуль установлен правильно.

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

cd /etc/modsecurity
cp modsecurity.conf-recommended modsecurity.conf

Перечитываем конфиг Apache

service apache2 reload

После этого появится log файл от mod_security в Apache log директории:

ls -l /var/log/apache2/modsec_audit.log
-rw-r----- 1 root root 0 Oct 19 08:08 /var/log/apache2/modsec_audit.log

Настройка mod_security

Из коробки modsecurity ничего не делает, так как для его работы требуются правила. По умолчанию в конфигурационном файле установлен параметр DetectionOnly, при этом события пишутся в лог, но ничего не блокируется. Что бы изменить поведение по умолчанию нужно отредактировать modsecurity.conf файл:

nano /etc/modsecurity/modsecurity.conf

Найдите строку:

SecRuleEngine DetectionOnly

и замените на:

SecRuleEngine On

Включайте этот параметр только после проверки и тестирования всех правил.

Еще одна дериктива SecResponseBodyAccess отвечает за помещение данных входных форм в буфер (т.е. данные будут прочитаны modsecurity). Это необходимо лишь в случае обнаружения утечек и защиты данных. Следовательно, при дефолтном значении параметра On увеличивается нагрузка и размер лог файла. В случае использования шаблона для защиты от SQL инъекций должен быть включен.

При необходимости его можно отключить:

Найдите строку:

SecResponseBodyAccess On

и замените на:

SecResponseBodyAccess Off

Теперь ограничим максимальный объем данных передаваемых веб приложению. Это может быть сделано с помощью двух команд:

SecRequestBodyLimit
SecRequestBodyNoFilesLimit

Параметр SecRequestBodyLimit указывает максимальный размер передаваемых данных (maximum POST data size) в байтах. Если размер данных передаваемых клиентом будет превышен, сервер выдаст ошибку: 413 Request Entity Too Large error. Если в веб приложении не реализован механизм загрузки файлов (file uploads), то параметр может быть существенно уменьшен.

В конфигурационном файле значение по умолчанию:

SecRequestBodyLimit 13107200

т.е. 12.5MB.

При задании этого параметра обратите внимание на соответствующие параметры в php.ini:

; Maximum size of POST data that PHP will accept.
; http://php.net/post-max-size
;post_max_size = 8M
post_max_size = 100M
; Maximum allowed size for uploaded files.
; http://php.net/upload-max-filesize
;upload_max_filesize = 2M
upload_max_filesize = 100M

Таким образом в нашем случае установим maximum POST data size в 100Мб (100x1024x1024 = 104857600 байта):

SecRequestBodyLimit 104857600

Похожая директива SecRequestBodyNoFilesLimit. Единственное отличие в том, что ограничивается размер данных POST за вычетом размера файлов (uploads) - значение должно быть "as low as practical."

По умолчанию значение установлено в 128KB:

SecRequestBodyNoFilesLimit 131072

Еще одна директива влияющая на производительность сервера: SecRequestBodyInMemoryLimit. Она указывает какая часть передаваемых данных "request body" (POSTed data) должна быть помещена в память (RAM), все остальное будет помещено на жесткий диск (аналогично swap файлу). Since droplets use SSDs, this is not much of an issue; however, this can be set a decent value if you have RAM to spare.

SecRequestBodyInMemoryLimit 131072

Значение по умолчанию равно 128KB.

Если используется кодировка UTF-8, то в файле modsecurity_crs_10_config.conf можно попробовать включить соответствующую опцию:

SecAction "phase:1,id:'981216',t:none,nolog,pass,setvar:tx.crs_validate_utf8_encoding=1"

Проверка на SQL Injection

Перед тем как настраивать правила modsecurity, создим PHP скрипт с уязвимостью к SQL инъекциям и проверим на нем работу modsecurity. Заметьте, что это простейший PHP login script без обработки сессии. Не забудьте поменять пароль MySQL для подключения к вашей базе (как создать БД смотрите ниже):

/var/www/login.php

<html>
<body>
<?php
    if(isset($_POST['login']))
    {
        $username = $_POST['username'];
        $password = $_POST['password'];
        $con = mysqli_connect('localhost','root','password','sample');
        $result = mysqli_query($con, "SELECT * FROM `users` WHERE username='$username' AND password='$password'");
        if(mysqli_num_rows($result) == 0)
            echo 'Invalid username or password';
        else
            echo '<h1>Logged in</h1><p>A Secret for you....</p>';
    }
    else
    {
?>
        <form action="" method="post">
            Username: <input type="text" name="username"/><br />
            Password: <input type="password" name="password"/><br />
            <input type="submit" name="login" value="Login"/>
        </form>
<?php
    }
?>
</body>
</html>

Скрипт выдает форму запроса логина и пароля. При вводе верных учетных данных отображается сообщение "A Secret for you."

Нам нужно создать тестовую базу данных MySQL и таблицы, затем вписать в нее логин и пароль.

mysql -u root -p

После ввода пароля рута получим доступ к консоли mysql>

create database sample;
connect sample;
create table users(username VARCHAR(100),password VARCHAR(100));
insert into users values('jesin','pwd');
insert into users values('alice','secret');
quit;

Откройте браузер и укажите путь к скрипту http://yourwebsite.com/login.php. Введите верные учетные данные.

Username: jesin
Password: pwd

Вы увидите сообщение об успешном входе. Теперь вернемся назад и введем заведомо неверные учетные данные - вы увидите сообщение Invalid username or password.

Теперь можно сказать, что скрипт работает верно. Следующим этапом будет попытка авторизоваться с помощью SQL инъекции, что бы обойти проверку логина и пароля. В поле username введите следующее:

' or true -- 

Обратите внимание на то, что после символов -- должен стоять пробел. Без него взлом не удастся. Поле password оставьте пустым и нажмите кнопку входа.

Раз и скрипт отображает сообщение как для аутентифицированного пользователя!

Попробуем теперь защититься от подобного рода атак - настроим соответствующие правила modsecurity.

Настройка правил

Существует готовый набор правил mod_security, так называемый CRS (Core Rule Set) и располагающийся в директории: /usr/share/modsecurity-crs/

root@droplet:~# ls -l /usr/share/modsecurity-crs/
итого 36
drwxr-xr-x 2 root root  4096 июля  29 12:42 base_rules
drwxr-xr-x 2 root root  4096 июля  29 12:42 experimental_rules
drwxr-xr-x 2 root root  4096 июля  29 12:42 lua
-rw-r--r-- 1 root root 12667 июня  17  2011 modsecurity_crs_10_config.conf
drwxr-xr-x 2 root root  4096 июля  29 12:42 optional_rules
drwxr-xr-x 3 root root  4096 июля  29 12:42 util

Документация лежит тут:

root@droplet1:~# ls -l /usr/share/doc/modsecurity-crs/
итого 24
-rw-r--r-- 1 root root  235 июня  16  2011 changelog.Debian.gz
-rw-r--r-- 1 root root 1702 марта 31  2011 copyright
drwxr-xr-x 3 root root 4096 июля  29 12:42 examples
-rw-r--r-- 1 root root  557 марта 31  2011 README.Debian
-rw-r--r-- 1 root root 6494 мая   26  2011 README.gz

Чтобы подгрузить эти правила достаточно скопировать их в директорию /etc/modsecurity и выполнить:
service apache2 reload

Путь указан по умолчанию в конфигурационном файле модуля /etc/apache2/mods-enabled/mod-security.conf. При желании его можно изменить или дополнить.

Активируем правило для защиты от SQL инъекций:

cd /usr/share/modsecurity-crs/base_rules
cp modsecurity_crs_41_sql_injection_attacks.conf /etc/modsecurity/
еще понадобится файл с данными
cp modsecurity_41_sql_injection_attacks.data /etc/modsecurity/
и файл базовой конфигурации
cd ..
cp modsecurity_crs_10_config.conf /etc/modsecurity/
перезагружаем apache:
service apache2 reload

Теперь откроем страницу созданную ранее и попробуем выполнить SQL инъекцию. Если вы включили директиву SecRuleEngine в положение On, то увидите ошибку 403 Forbidden. Если установлен параметр DetectionOnly, атака пройдет успешно, но попытка взлома будет зафиксирована в лог файле modsec_audit.log.

Создание собственных правил mod_security

Создадим правило, которое будет блокировать запрос содержаший определнные "spammy" слова вводимые в HTML форме. Для начала создадим PHP скрипт, который отображает слова введенные в текстовом поле.

/var/www/form.php

<html>
    <body>
        <?php
            if(isset($_POST['data']))
                echo $_POST['data'];
            else
            {
        ?>
                <form method="post" action="">
                        Enter something here:<textarea name="data"></textarea>
                        <input type="submit"/>
                </form>
        <?php
            }
        ?>
    </body>
</html>

Собственные правила могут быть добавлены в любой конфигурационный файл modsecurity. Создадим собственный новый файл:

nano /etc/modsecurity/modsecurity_custom_rules.conf

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

SecRule REQUEST_FILENAME "form.php" "id:'400001',chain,deny,log,msg:'Spam detected'"
SecRule REQUEST_METHOD "POST" chain
SecRule REQUEST_BODY "@rx (?i:(pills|insurance|rolex))"

Сохраним файл и перезагрузим Apache. Откроем в браузере http://yourwebsite.com/form.php и введем текст содержащий любое из перечисленных слов: pills, insurance, rolex.

Вы увидите либо 403 ошибку и соответствующую запись в логе, или только запись в логе в зависимости от настройки параметра SecRuleEngine.

Синтаксис правила SecRule:

SecRule VARIABLES OPERATOR [ACTIONS]

В данном примере использовано действие (action) chain для поиска соответствий в переменной (variables) REQUEST_FILENAME с файлом form.php, REQUEST_METHOD с POST и REQUEST_BODY с регулярным выражением (@rx) строки (pills|insurance|rolex). Символы ?i: означают регистронезависимое совпадение. Тут ACTION со значением deny и log с сообщением "Spam detected." Действие chain подразумевает логическое "И", т.е. одновременное совпадение всех трех условий.

Отключение действия mod_security для определенных виртуальных хостов и директорий

Иногда имеет смысл отключить mod_security для некоторых директорий или доменных имен. Например, phpmyadmin, так как modsecurity будет блокировать SQL запросы. Так же рекомендуется исключать админки управления сайтами, такими как WordPress.

Отключение modsecurity для целого VirtualHost:

Внутри раздела <VirtualHost>:

<IfModule security2_module>
    SecRuleEngine Off
</IfModule>


Для определенной директории:

<Directory "/var/www/wp-admin">
    <IfModule security2_module>
        SecRuleEngine Off
    </IfModule>
</Directory>

Например, отключим modsecurity для phpmyadmin:

nano /etc/phpmyadmin/apache.conf

Добавим директиву SecRuleEngine в раздел:

<directory /usr/share/phpmyadmin>
...
        <ifmodule security2_module>
                SecRuleEngine Off
        </ifmodule>
</directory>

Если вы не хотите полностью отключать modsecurity, используйте директиву SecRuleRemoveById, что бы отключить определенное правило или цепочку правил по его ID. В предыдущем примере ID правила: '400001'.

<LocationMatch "/wp-admin/update.php">
    <IfModule security2_module>
        SecRuleRemoveById 400001
    </IfModule>
</LocationMatch>


Создание белого списка IP адресов, на которые не распространяется действие modsecurity:

Создадим файл whitelist:

touch /etc/modsecurity/whitelist

и добавим в него IP адреса в столбик:

192.168.0.1
192.168.0.2

В файл modsecurity.conf, например сразу после директивы SecRuleEngine On добавим строки:

# Подключение файла whitelist с разрешенными IP
SecRule REMOTE_ADDR "@pmFromFile /etc/modsecurity/whitelist" phase:1,nolog,allow,ctl:ruleEngine=Off

и перезапустим Apache.

Обновление правил mod_security

После загрузки, распаковки и обновления правил рекомендуется обновить и modsecurity_crs_10_setup.conf

wget -O master.zip https://github.com/SpiderLabs/owasp-modsecurity-crs/archive/master.zip

Если возникает ошибка при перезапуске Apache:

Error parsing actions: Unknown action: ver
Action 'configtest' failed.
The Apache error log may have more information.
...fail!

это означает, что версия установленного mod_security устарела и новые правила не поддерживаются.

Набор правил OWASP rule set требует версию modsecurity >=2.7

Можно либо обновить версию mod_security, скачав дистрибутив отсюда http://sourceforge.net/projects/mod-security/files/, либо применить downgrade script расположенный в директории ../util/rule-management, который автоматически переписывает правила и делает их совместимыми с версией 2.6.
Для этого достаточно выполнить команду, находясь в директории с правилами, которые нужно даунгрэйдить.

perl /PATH_TO_OWASP_RULESET_TGZ/util/rule-management/remove-2.7-actions.pl -t 2.6 -f .

Web консоль mod_security "WAF-FLE"

Официальный сайт проекта: http://waf-fle.org/

WAF-FLE - это OpenSource ModSecurity Console, позволяющая просматривать события в журнале modsecurity используя графические сенсоры.

dashboard_waf-fle

Источники

Официальная документация modsecurity: https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual

Данная статья является свободным переводом статьи: https://www.digitalocean.com/community/tutorials/how-to-set-up-mod_security-with-apache-on-debian-ubuntu

Установка под Windows: http://www.osp.ru/win2000/2007/05/4320176/

Метки: . Закладка Постоянная ссылка.

Добавить комментарий

Ваш e-mail не будет опубликован.

*