В данной статье я не планирую рассказывать о том что такое WAF, давать ссылки на вику с расшифровкой аббревиатуры. Кто еще не знает или не слышал, гугл поможет Я не буду сравнивать их, говорить какие хорошие, а какие плохие, получится слишком субъективно. Да и сравнивать не планировал, тем более что WAF Barracuda и Imperva я в глаза не видел и руками не щупал чуть менее чем год как. Поговорим мы о самой подходящей WAF в наше кризисное время, о бесплатной... Mod Securyti И опять же, я не буду рассказывать о каких то базовых настройках, такой информации в интернете вагон и тележка следом, в том числе и на русском, на пример: HTML: http://apachedev.ru/2006/02/19/vvedenie-v-mod_security/ Я бы хотел расказать о работе с ним, о нюансах и трудностях с которыми столкнулся уже сейчас, багами, которые есть и сейчас... А дальше решать уже вам, готовы вы с чем то мириться и бесплатно получить не самый плохой WAF или все же платные с меньшим кол-ом проблем и теоретической возможностью зависти TAC в рамках лицензии и получить, если очень повезет то быстро, заплатку. 1. Общие сведения 1.1 Официальный сайт HTML: https://www.modsecurity.org/ На сайте вы можете увидеть информацию что есть и платная версия. На самом деле на платные и бесплатные делятся только наборы правил. Сам исходник, код продукта, открыт и бесплатный, текущая версия 2.9.0, у меня используется 2.7.7. Готовится к релизу вроде как версия 3.0 HTML: https://github.com/SpiderLabs/ModSecurity/releases Платный набор правил от бесплатного отличается тем, что в платном разработчиками являются сотрудники Trustwave SpiderLabs и тех.поддержка осуществляется на основе лицензии. Бесплатный набор правил разрабатывали члены сообщества OWASP. Текущая актуальная версия набора правил 2.2.9, готовится к релизу набор правил 3.0 под движок с тем же номером версии, часть правил потерпели изменения, появились новые операторы (я нашел два) . У меня сейчас микс набора правил из этих двух веток. HTML: https://github.com/SpiderLabs/owasp-modsecurity-crs Тех. поддержка осуществляется на основе комментариев в github и по принципу можем сейчас решить или на доработку в следующие версии Второе, основное отличие в том, что бесплатный набор содержит правила от основных типов атак, анализ правил натолкнул меня на мысль, что за основу взяты типы и методы атак описанные на страницах ресурса OWASP, что собственно логично. Платные же дополнены правилами закрывающими уязвимости в популярных коммерческих CMS, таких как: Microsoft SharePoint, WordPress, cPanel, osCommerce, Joomla, cPanel, Drupal, vBulletin. Плюс еще ряд плюшек. С полным списком сервисов за деньги можно ознакомиться тут: HTML: https://www.modsecurity.org/commercial-rules.html Дальше я когда буду говорить о правилах, как отдельных, так и их группах, буду иметь ввиду только правила из бесплатного набора. Большая часть политик, реализующих защиту от SQLi, XSS и т.п. строится на основе регулярных выражений, для обработки regexp используется PCRE библиотека, реализующая работу регулярных выражений в стиле Perl (с некоторыми отличиями). 1.2 Изначально modsec разрабатывался только для Аpache, на данный момент он является кросс-платформенными решением и может быть установлен как на Apache, так и на Nginx и IIS. 1.3 У Mod Security как и у любого WAF( по крайне мере те о которых я слышал, видел, щупал) есть три основных состояния/режима работы это: а)отключена обработка правилами запроса Code: SecRuleEngine Off б)включена в режиме обучения, режим предназначен для первичной подгонки правил Code: SecRuleEngine DetectionOnly в)ну и соответственно боевой режим, когда правила активны и их срабатывание могут вызывать блокировку запросов или ответов от сервера, попавших под условия блокировки(да, он умеет слушать и прогонять по правилам не только REQUEST, но и RESPONSE, прослушивание ответов от сервера с веб приложением нацелено в первую очередь на подавление выводов ошибок). При чем в рабочем режиме блокировка может происходить на основе одного из двух способов или методов, называйте кому как удобнее. Тут надо заметить что все правила имеют свой уровень критичности, в большинстве своем во всех правилах с наивысшим уровнем критичности (Critical), в качестве реакции/действия на срабатывание правила происходит запись информации в лог, считаются баллы и применяется блокировка запроса, отдавая в ответ пользователю 404 (по дефолту, можно сменить). Остальные правила с более низким уровнем критичности(но не все), пишут в лог и считают балы, блокировку они не вызывают. Это и есть первый метод/режим блокировки, по уровню критичности, он же используется по умолчанию при установке. Второй это на основе баллов, которые считают правила, но в случае включения этого режима, блокировка запроса прописанная в этом правиле не отрабатывает, в переменную загоняется информация о сработавшем правиле и считаются баллы. После прохождения всех правил, запрос обрабатывается результирующим правилом, которое суммирует и вычитает баллы, получает итоговое значение и сравнивает его с пороговым, если порог достигнут, запрос блокируется (собственно на это режиме я и остановился). На мой взгляд это более гибкое решение, уменьшает кол-во ложных блокировок. Тем более что пороговое значение можно менять, по умолчанию 15, стоимость правил по уровню критичности тоже можно менять Code: Critical - Anomaly Score of 5. Is the highest severity level possible without correlation. It is normally generated by the web attack rules (40 level files). Error - Anomaly Score of 4. Is generated mostly from outbound leakage rules (50 level files). Warning - Anomaly Score of 3. Is generated by malicious client rules (35 level files). Notice - Anomaly Score of 2. Is generated by the Protocol policy and anomaly files. Ну вот, с краткой информацией по системе и отличиях в наборах правил ознакомились, теперь переходим к основному повествованию, с чем столкнулся, что работает не так, а что не так как заявлено в документации. Осталось уже не много, раз дошли до этого места, поздно закрывать, дочитываем 2. Треш, угар и садомия... 2.1 Грабли раз, версия под nginx. Так как на frontend используется nginx, то и я пошел путем нормального русского мужика, я поставил на тест исходник под nginx. Хочу оговориться сразу, не все однозначно, могли сказаться на результате и мои криворуки, и что это было начало моего общения с modsec. Опять же сейчас в релизе уже 2.9.0 версия, а у меня, напомню 2.7.7 стоит. Установка прошла нормально, завернул первый ресурс на WAF, и все, развлекаемся, POST обрабатывается криво, постоянно сыпятся ошибки с PCRE Limit (лимит на рекурсию), не все по не понятным причинам попадает в логи. Выкручивание этих самых лимитов до заоблачных значений, как рекомендуют на ресурсах напрямую не относящихся к modsec не помогает. И тут во мне проснулся старый опытный еврей, и где он до этого момента шлялся? Я полез смотреть сообщения по багам для modsec под разные платформы для текущей версии. И в итоге теперь modsec уютно живет на Apache Через забавную схему USER->Nginx->Apache->WAF->Apache->Nginx->backend. Так что, уважаемый читатель, включай старого мудрого еврея, читай вначале все-таки мануалы, ну или как в моем случае, листайте комментарии и смотрите на баги уже заявленные другими 3. Политики 3.1. Подключение правил для ресурса в modsec. На многих ресурсах рекомендуют делать так: PHP: Include "/какой-то путь до директории с modsec/modsec/base_rules/*.conf" Поверьте, это не самый правильный и надежный способ, modsec не выстраивает очередность исполнения правил по уникальному ID каждого правила, он подключит в том порядке, как файлы отсортированы в директории. Если вы хотите порядка и точно знать в каком порядке выполняются проверки, делайте так: PHP: Include "/какой-то путь до директории с modsec/modsec/base_rules/modsecurity_crs_20_protocol_violations.conf"Include "/какой-то путь до директории с modsec/modsec/base_rules/modsecurity_crs_21_protocol_anomalies.conf"Include "/какой-то путь до директории с modsec/modsec/base_rules/modsecurity_crs_23_request_limits.conf"Include "/какой-то путь до директории с modsec/modsec/base_rules/modsecurity_crs_30_http_policy.conf".... И include результирующего правила, подсчитывающего баллы, должно быть всегда в самом низу конфигурационного файла,после всех правил, как из набора, так и созданных вами. И еще один совет, касательно правил, не наступайте на мои грабли, не правьте эталонные правила. Используйте достаточное кол-во директив позволяющие вносить изменения в данное правило. Так же не отключайте шаблонное правило комментированием его. Используйте опять же директиву SecRuleRemoveById. Это сохранит ваше время и нервы при обновлении наборов правил, или при включении в защиту еще одного веб ресурса. Да, уточнение, все эти директивы, в конфигурационном файле должны идти строго ниже include того правила, в которое вы вносите изменение или отключаете его. В против ном случае не сработает, a modsec при проверке корректности синтаксиса, при внесении изменения на это не обращает внимание и говорит все ОК, изменение принято. 3.2 Самая большая и крупная проблема у modsec это не английские буквы, т.е. все те символы и буквы, которые при URL или hexadecimal кодировании принимают вид \xXX\xXX (на пример буква 'я'-\хd1\х8f). Mod Securyti игнорирует старший байт \xd1, который ему пытается сказать что я буква не английского алфавита, следующий байт за мной \x8f это тоже моя часть, он рассматривает это как два символа\буквы. На безопасность это не влияет, но создает ложные срабатывания, если у вас, на пример в строке поиска не пытаются загнать пол страницы Войны и Мира, то больших хлопот не доставит, просто используйте метод блокировки на основе балльной системы. Так как со стороны разработчиков пока еще нет решения. HTML: https://github.com/SpiderLabs/ModSecurity/issues/708 3.3 Во многих регулярных выражениях политик встречается вот такое \W, что означает "Буквенный или цифровой символ или знак подчёркивания". И не смотря на то что про PCRE библиотеку написано, что она осуществляет мультиязычную поддержку, не рассчитывайте что он русские буквы тоже будет считать буквенным символом, это не так. Полный эквивалент этой записи выглядит так [^A-Za-z0-9_]. Замените на него и дополните буквами русского алфавита, но не забывайте про пункт 3.1 при этом . 3.4 Помните в пункте 3.1 я упоминал директиву SecRuleRemoveByID? Эта директива отключается использование правила с указанным ID для всех запросов в данном ресурсе. Но modsec предполагает что данную директиву еще можно использовать и внутри вашего кастомного правила. В правило встраивается вот такая строчка ctl:ruleRemoveByID, и когда ваше правило отработает, запрос не должен попасть в правило, на проверку, с указанным ID. Оно, это правило, отключается для этого запроса. Так вот, в моем ядре не работает. Если надо срочно, а в вашей версии сборки вы еще не проверяли, работает или нет. Лучше используйте команды позволяющие пропустить определенное кол-во правил следующих за вашим. Ну и соответственно, в этом случае, ваше правило лучше располагать над правилом которое надо проигнорировать. 3.5 В ветке директории экспериментальные правила, есть два набора рулов: PHP: modsecurity_crs_11_dos_protection.confmodsecurity_crs_11_slow_dos_protection.conf Не советую включать, в ветке 3.0 изменили их или нет по отношению к текущему релизу не смотрел, но в текущем релизе, что на моем рабочем ядре 2.7.7, что на текущем 2.9 вызывают большую задержку в обработке правил и огромное кол-во блокировок запросов. 3.6 В пункте 1.3 я рассказал о директиве SecRuleEngine, и что при директиве Off останавливается обработка правил. Да, это так, но именно правил из базового набора и ваших, если такие есть. И если вы для ресурса целиком или для отдельного Location вашего ресурса, применили SecRuleEngine Off. Имейте ввиду, что WAF все равно обрабатывает запрос и если, к примеру, длинна URL или общий размер запроса, превышают установленные значения в файле : PHP: modsecurity_crs_10_setup.conf WAF выдаст Reject такому запросу. 3.7 JSON, поддержка, точнее корректный парсинг его появился только в ядре 2.9 (насколько корректно не проверял), но разработчики клятвенно заверяют что все хорошо, но при одном маленьком условии, в header должно быть: HTML: Content-Type: application/json Иначе, куча false positive 3.8 И еще одно, обращение к разработчикам еще не создавал, по этому вопросу, но обязательно создам, с предложение о доработке в следующих версиях и введении списка по кукам. которые должны проверяться правилами. На данный момент проверяются все куки в запросе, кроме тех, для которых явно указано в самом правиле - не проверять. На тех ресурсах, что сейчас в защите, я первое время, пока собирал и анализировал логи в режиме DetectionOnly, видел набор большого кол-во баллов. Что могло означать возможные блокировки, при включении режима защиты. Срабатывали правила для кук, которые прилетали с запросами от пользователя, но не относились к нашему ресурсу. Это куки от различных SEO тулбаров, adware и т.п. Сейчас я, в основной группе правил, которые давали false positive, внес изменения, и теперь они проверяют только те куки, которые обрабатываются нашими серверами, а значит и внедрение в которые различного рода injection, пусть даже и теоретически, могут вызвать проблемы при работе приложения.