Как настроить mod_security с помощью Apache в Debian/Ubuntu
Прелюдия
Mod security — это бесплатный брандмауэр веб-приложений (WAF), который работает с Apache, Nginx и IIS. Он поддерживает гибкий механизм правил для выполнения простых и сложных операций и поставляется с основным набором правил (CRS), в котором есть правила для SQL-инъекций, межсайтовых сценариев, троянов, плохих пользовательских агентов, перехвата сеансов и множества других эксплойтов. Для Apache это дополнительный модуль, упрощающий установку и настройку.
Для выполнения этого руководства вам понадобится LAMP, установленный на вашем сервере.
Установка mod_security
Modsecurity доступен в репозитории Debian/Ubuntu:
apt-get install libapache2-modsecurity
Убедитесь, что модуль mod_security был загружен.
apachectl -M | grep --color security
Вы должны увидеть модуль с именем security2_module (shared)
, который указывает, что модуль был загружен.
Установка Modsecurity включает рекомендуемый файл конфигурации, который необходимо переименовать:
mv /etc/modsecurity/modsecurity.conf{-recommended,}
Перезагрузить Апач
service apache2 reload
Вы найдете новый файл журнала для mod_security в каталоге журнала Apache:
root@droplet:~# 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). Это необходимо только в том случае, если требуется обнаружение утечки данных и защита. Таким образом, если оставить его Включенным, ресурсы дроплетов будут израсходованы, а также увеличится размер файла журнала.
Найдите это
SecResponseBodyAccess On
и измените его на:
SecResponseBodyAccess Off
Теперь мы ограничим максимальное количество данных, которые можно отправить в ваше веб-приложение. Две директивы настраивают их:
SecRequestBodyLimit
SecRequestBodyNoFilesLimit
Директива SecRequestBodyLimit
указывает максимальный размер данных POST. Если клиент отправляет что-то большее, сервер ответит ошибкой 413 Request Entity Too Large. Если в вашем веб-приложении нет загрузки файлов, это значение можно значительно уменьшить.
Значение, указанное в файле конфигурации, равно
SecRequestBodyLimit 13107200
что составляет 12,5 МБ.
Подобной директиве является SecRequestBodyNoFilesLimit
. Единственное отличие состоит в том, что эта директива ограничивает размер данных POST за вычетом загружаемых файлов — это значение должно быть «как можно меньше».
Значение в файле конфигурации
SecRequestBodyNoFilesLimit 131072
что составляет 128 КБ.
Наряду с этими директивами есть еще одна, влияющая на производительность сервера: SecRequestBodyInMemoryLimit
. Эта директива говорит сама за себя; он указывает, сколько данных «тела запроса» (данные POST) должны храниться в памяти (ОЗУ), все остальное будет помещено на жесткий диск (точно так же, как подкачка). Поскольку капли используют SSD, это не так уж много. проблема; тем не менее, это может быть установлено приличное значение, если у вас есть свободная оперативная память.
SecRequestBodyInMemoryLimit 131072
Это значение (128 КБ), указанное в файле конфигурации.
Тестирование SQL-инъекций
Прежде чем приступить к настройке правил, мы создадим PHP-скрипт, который уязвим для SQL-инъекций, и попробуем его. Обратите внимание, что это всего лишь базовый PHP-скрипт входа в систему без обработки сеанса. Обязательно измените пароль 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>
Этот скрипт отобразит форму входа. При вводе правильных учетных данных появится сообщение «Секрет для вас».
Нам нужны учетные данные в базе данных. Создайте базу данных 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
Вы увидите сообщение об успешном входе в систему. Теперь вернитесь и введите неправильную пару учетных данных - вы увидите сообщение Неверное имя пользователя или пароль.
Мы можем подтвердить, что скрипт работает правильно. Следующая задача — попробовать свои силы с SQL-инъекцией, чтобы обойти страницу входа. Введите следующее в поле имени пользователя:
' or true --
Обратите внимание, что после должен быть пробел —
эта инъекция не будет работать без этого пробела. Оставьте поле пароля пустым и нажмите кнопку входа.
Вуаля! Сценарий показывает сообщение, предназначенное для аутентифицированных пользователей.
Настройка правил
Чтобы облегчить вам жизнь, существует множество правил, которые уже установлены вместе с mod_security. Они называются CRS (основной набор правил) и расположены в
root@droplet:~# ls -l /usr/share/modsecurity-crs/
total 40
drwxr-xr-x 2 root root 4096 Oct 20 09:45 activated_rules
drwxr-xr-x 2 root root 4096 Oct 20 09:45 base_rules
drwxr-xr-x 2 root root 4096 Oct 20 09:45 experimental_rules
drwxr-xr-x 2 root root 4096 Oct 20 09:45 lua
-rw-r--r-- 1 root root 13544 Jul 2 2012 modsecurity_crs_10_setup.conf
drwxr-xr-x 2 root root 4096 Oct 20 09:45 optional_rules
drwxr-xr-x 3 root root 4096 Oct 20 09:45 util
Документация доступна по адресу
root@droplet1:~# ls -l /usr/share/doc/modsecurity-crs/
total 40
-rw-r--r-- 1 root root 469 Jul 2 2012 changelog.Debian.gz
-rw-r--r-- 1 root root 12387 Jun 18 2012 changelog.gz
-rw-r--r-- 1 root root 1297 Jul 2 2012 copyright
drwxr-xr-x 3 root root 4096 Oct 20 09:45 examples
-rw-r--r-- 1 root root 1138 Mar 16 2012 README.Debian
-rw-r--r-- 1 root root 6495 Mar 16 2012 README.gz
Чтобы загрузить эти правила, нам нужно указать Apache просмотреть эти каталоги. Отредактируйте файл modsecurity.conf
.
nano /etc/apache2/mods-enabled/modsecurity.conf
Добавьте следующие директивы внутрь
:
Include "/usr/share/modsecurity-crs/*.conf"
Include "/usr/share/modsecurity-crs/activated_rules/*.conf"
Каталог activated_rules
аналогичен каталогу Apache mods-enabled
. Правила доступны в каталогах:
/usr/share/modsecurity-crs/base_rules
/usr/share/modsecurity-crs/optional_rules
/usr/share/modsecurity-crs/experimental_rules
Симлинки должны быть созданы внутри каталога activated_rules
для их активации. Давайте активируем правила SQL-инъекций.
cd /usr/share/modsecurity-crs/activated_rules/
ln -s /usr/share/modsecurity-crs/base_rules/modsecurity_crs_41_sql_injection_attacks.conf .
Чтобы правила вступили в силу, необходимо перезагрузить Apache.
service apache2 reload
Теперь откройте страницу входа, которую мы создали ранее, и попробуйте использовать запрос SQL-инъекции в поле имени пользователя. Если вы изменили директиву SecRuleEngine
на On, вы увидите ошибку 403 Forbidden. Если оставить параметр DetectionOnly, внедрение будет успешным, но попытка будет зарегистрирована в файле modsec_audit.log
.
Написание собственных правил mod_security
В этом разделе мы создадим цепочку правил, которая блокирует запрос, если определенные «спамные» слова вводятся в 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
в браузере и введите текст, содержащий любое из этих слов: таблетки, страхование, ролекс.
Вы увидите либо страницу 403 и запись в журнале, либо только запись в журнале, основанную на настройке SecRuleEngine
. Синтаксис для SecRule:
SecRule VARIABLES OPERATOR [ACTIONS]
Здесь мы использовали цепочку действий для сопоставления переменных REQUEST_FILENAME с form.php, REQUEST_METHOD с POST и REQUEST_BODY с регулярным выражением (@rx) string (pills|insurance|rolex) . ?i: соответствует регистру. При успешном совпадении всех этих трех правил ДЕЙСТВИЕ заключается в отклонении и регистрации с сообщением \Обнаружен спам. Действие chain имитирует логическое И для соответствия всем трем правилам.
Исключение хостов и каталогов
Иногда имеет смысл исключить конкретный каталог или доменное имя, если оно работает с таким приложением, как phpMyAdmin, в качестве modsecurity и будет блокировать SQL-запросы. Также лучше исключить серверные части администрирования приложений CMS, таких как WordPress.
Чтобы отключить modsecurity для полного виртуального хоста, поместите следующее
<IfModule security2_module>
SecRuleEngine Off
</IfModule>
внутри раздела
.
Для определенного каталога:
<Directory "/var/www/wp-admin">
<IfModule security2_module>
SecRuleEngine Off
</IfModule>
</Directory>
Если вы не хотите полностью отключать modsecurity, используйте директиву SecRuleRemoveById
, чтобы удалить определенное правило или цепочку правил, указав его идентификатор.
<LocationMatch "/wp-admin/update.php">
<IfModule security2_module>
SecRuleRemoveById 981173
</IfModule>
</LocationMatch>
Дальнейшее чтение
Официальная документация по модбезопасности https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual