ModSecurity с набора правила OWASP CRS се включва за десет минути и се изключва след три дни — след като статиите престанат да се записват в администрацията, качването на файлове се счупи и клиентът не може да направи поръчка, защото в адреса е имало апостроф. Изводът „WAF пречи на работата“ идва от само себе си, но е погрешен: почти всички тези блокировки се решават с три-четири точни изключения, а цялата работа е да се намерят правилно.
Не включвайте блокирането веднага
Първата седмица е само наблюдение. В /etc/modsecurity/modsecurity.conf:
SecRuleEngine DetectionOnly
В този режим WAF записва всичко, което би блокирал, но не блокира нищо. Седмица реален трафик — включително собствената ви работа в администрацията, качването на снимки и оформянето на поръчка — дава списъка с истинските фалшиви сигнали вместо хипотетични. Превключването на On има смисъл едва след като този списък е обработен.
Как работи CRS: не едно правило, а сума
Ключът към всичко по-нататък. CRS почти никога не блокира заявка с едно правило. Всяко задействало се правило добавя на заявката точки за аномалност, а блокирането настъпва, когато сумата превиши прага. Затова в журнала ще видите не един ред, а няколко, и последното ще е правилото с идентификатор 949110 — точно то прави равносметката.
Практически извод: изключението трябва да се направи за правилото, което е добавило точки, а не за 949110. Изключвайки обобщаващото правило, изключвате целия набор и WAF остава само като ред в конфигурацията.
Второто следствие е нивото на параноя. По подразбиране то е първо и това е правилният избор. Нива 2 и 3 добавят правила, които заведомо дават фалшиви сигнали на обикновени сайтове, и има смисъл да се включват едва когато първото ниво е напълно изчистено.
Да се намери виновното правило
Всичко нужно е в одитния журнал (/var/log/modsec_audit.log) и в журнала за грешки на уеб сървъра. Търсим по времето на блокирането:
sudo grep -o 'id "[0-9]*"' /var/log/modsec_audit.log | sort | uniq -c | sort -rn | head
Това е честотен списък на задействалите се правила. После по конкретния идентификатор гледаме на какво точно се е задействало:
sudo grep -A5 'id "942100"' /var/log/modsec_audit.log | head -40
Нужни са три неща: идентификаторът на правилото, името на параметъра (ARGS:content, ARGS:comment) и пътят на заявката. От тях се строи изключението.
Обичайните заподозрени
Списъкът се повтаря от сайт на сайт:
- 942100 — SQL инжекция. Задейства се на текстови полета с дълго съдържание: тяло на статия, описание на стока, коментар. Апострофите, скобите и думи като
selectизглеждат подозрително за детектора и в нормален текст; - 941100 и 941xxx — XSS. Идват заедно с визуалния редактор: HTML етикетите в полето са целият смисъл на работата му;
- 920420 — неразрешен Content-Type. Чупи API и качването на файлове: наборът от разрешени типове по подразбиране е тесен и
application/jsonв по-старите версии не влизаше в него; - 913100 — скенер по User-Agent. Улавя заедно със скенерите и законни инструменти: наблюдение на достъпността, curl във вашите собствени скриптове;
- 200002, 200004 — грешки при разбор на тялото на заявката. Обикновено означават не атака, а превишен лимит за размера на тялото, тоест качване на голям файл.
Три начина да се направи изключение
По нарастваща грубост. Всички се пишат в собствен файл (например /etc/modsecurity/crs/REQUEST-900-EXCLUSION-RULES.conf), а не във файловете на самия CRS: наборът правила се обновява и вашите промени при обновяване ще изчезнат.
Изваждане на един параметър изпод едно правило. Най-точният вариант, към който се стремим:
SecRuleUpdateTargetById 942100 "!ARGS:content"
Изключване на правилото само на един път. Става, когато „шуми“ конкретна страница — редакторът, вносът, формата за отзив:
SecRule REQUEST_URI "@beginsWith /admin/post" \
"id:1001,phase:1,pass,nolog,ctl:ruleRemoveById=942100"
Пълно изключване на правилото. Крайна мярка и почти винаги признак, че причината не е намерена:
SecRuleRemoveById 942100
Разликата между първото и третото е съществена. В първия случай полето „текст на статията“ престава да се проверява за SQL инжекции от едно правило; във втория и третия престава да се проверява целият сайт. Разликата в обема работа е около пет минути.
След промените — проверка на конфигурацията и меко презареждане:
sudo apachectl configtest && sudo systemctl reload apache2
sudo nginx -t && sudo systemctl reload nginx
Редът, който спестява седмица
- Седмица в
DetectionOnlyс обичайна работа на сайта, включително администрацията и качванията. - Честотният списък на правилата от одитния журнал. Обработвайте отгоре надолу — първите три-четири дават деветдесет процента от шума.
- За всяко: разберете кой параметър и на коя страница. Изключението правете по параметър, а не по правило.
- Едва сега
SecRuleEngine On. - Веднъж месечно поглеждайте блокировките: сайтът се е променил — появили са се нови фалшиви сигнали.
Последната точка е това, в което всичко обикновено се проваля: одитният журнал е гигабайти текст, ръчно никой няма да го чете. Смисълът на събрания панел е списъкът на задействалите се правила, блокираните заявки и активният набор да са пред очите, а не да се вадят с grep. Как изглежда това, показва демонстрационната страница по-долу.