ModSecurity se sadou pravidel OWASP CRS se zapíná za deset minut a vypíná za tři dny — poté, co se přestanou ukládat články v administraci, rozbije se nahrávání souborů a zákazník nemůže dokončit objednávku, protože v adrese byl apostrof. Závěr „WAF překáží v práci“ se nabízí sám, ale je nesprávný: téměř všechny tyto blokace se řeší třemi až čtyřmi cílenými výjimkami a celá věc je v tom najít je správně.

Nezapínejte blokování hned

První týden jen pozorování. V /etc/modsecurity/modsecurity.conf:

SecRuleEngine DetectionOnly

V tomto režimu WAF zapisuje vše, co by zablokoval, ale neblokuje nic. Týden skutečného provozu — včetně vaší vlastní práce v administraci, nahrávání obrázků a dokončení objednávky — dá seznam skutečných falešných poplachů místo hypotetických. Přepnout na On má smysl teprve poté, co je tento seznam probrán.

Jak CRS funguje: ne jedno pravidlo, ale součet

Klíč k pochopení všeho dalšího. CRS téměř nikdy neblokuje požadavek jediným pravidlem. Každé spuštěné pravidlo přidá požadavku body anomálie a k blokaci dojde, když součet překročí práh. Proto v logu neuvidíte jeden řádek, ale několik, a poslední bude pravidlo s identifikátorem 949110 — to, které sčítá.

Praktický závěr: výjimku je třeba udělat pro pravidlo, které body přidalo, ne pro 949110. Vypnutím sčítacího pravidla vypnete celou sadu a WAF zůstane jen jako řádek v konfiguraci.

Druhý důsledek je úroveň paranoie. Ve výchozím stavu je první a je to správná volba. Úrovně 2 a 3 přidávají pravidla, která na běžných webech zaručeně vyvolávají falešné poplachy, a zapínat je má smysl teprve tehdy, když je první úroveň zcela vyladěná.

Najít viníka

Vše potřebné je v auditním logu (/var/log/modsec_audit.log) a v chybovém logu webového serveru. Hledáme podle času blokace:

sudo grep -o 'id "[0-9]*"' /var/log/modsec_audit.log | sort | uniq -c | sort -rn | head

To je četnostní seznam spuštěných pravidel. Dále se u konkrétního identifikátoru podíváme, na čem přesně se spustilo:

sudo grep -A5 'id "942100"' /var/log/modsec_audit.log | head -40

Potřebujete tři věci: identifikátor pravidla, název parametru (ARGS:content, ARGS:comment) a cestu požadavku. Z nich se výjimka staví.

Obvyklí podezřelí

Seznam se opakuje od webu k webu:

  • 942100 — SQL injection. Spouští se na textových polích s dlouhým obsahem: tělo článku, popis zboží, komentář. Apostrofy, závorky a slova jako select vypadají detektoru podezřele i v normálním textu;
  • 941100 a 941xxx — XSS. Přicházejí spolu s vizuálním editorem: HTML značky v poli jsou celý smysl jeho práce;
  • 920420 — nepovolený Content-Type. Rozbíjí API a nahrávání souborů: výchozí sada povolených typů je úzká a application/json do ní ve starších verzích nepatřil;
  • 913100 — skener podle User-Agent. Chytá spolu se skenery i legitimní nástroje: monitoring dostupnosti, curl ve vašich vlastních skriptech;
  • 200002, 200004 — chyby při parsování těla požadavku. Obvykle neznamenají útok, ale překročený limit velikosti těla, tedy nahrávání velkého souboru.

Tři způsoby, jak udělat výjimku

Vzestupně podle hrubosti. Všechny se píší do vlastního souboru (například /etc/modsecurity/crs/REQUEST-900-EXCLUSION-RULES.conf), ne do souborů samotné CRS: sada pravidel se aktualizuje a vaše úpravy při aktualizaci zmizí.

Vyjmout jeden parametr z působnosti jednoho pravidla. Nejpřesnější varianta, o niž usilujeme:

SecRuleUpdateTargetById 942100 "!ARGS:content"

Vypnout pravidlo jen na jedné cestě. Hodí se, když „hlučí“ konkrétní stránka — editor, import, formulář recenze:

SecRule REQUEST_URI "@beginsWith /admin/post" \
    "id:1001,phase:1,pass,nolog,ctl:ruleRemoveById=942100"

Vypnout pravidlo úplně. Krajní opatření a téměř vždy známka toho, že příčina nebyla nalezena:

SecRuleRemoveById 942100

Rozdíl mezi prvním a třetím je podstatný. V prvním případě přestane být pole „text článku“ kontrolováno na SQL injection jedním pravidlem; ve druhém a třetím přestane být kontrolován celý web. Rozdíl v objemu práce je asi pět minut.

Po úpravách kontrola konfigurace a měkký restart:

sudo apachectl configtest && sudo systemctl reload apache2
sudo nginx -t && sudo systemctl reload nginx

Pořadí, které ušetří týden

  1. Týden v režimu DetectionOnly s běžnou prací na webu včetně administrace a nahrávání.
  2. Četnostní seznam pravidel z auditního logu. Probírat shora dolů — první tři až čtyři dají devadesát procent šumu.
  3. U každého: zjistit, který parametr a na které stránce. Výjimku dělat podle parametru, ne podle pravidla.
  4. Teprve teď SecRuleEngine On.
  5. Jednou za měsíc nahlédnout do blokací: web se změnil — objevily se nové falešné poplachy.

Poslední bod je to, o co se vše obvykle rozbije: auditní log jsou gigabajty textu, ručně ho nikdo číst nebude. Smysl shromážděného panelu je v tom, aby seznam spuštěných pravidel, zablokovaných požadavků a aktivní sady byl před očima, a ne aby se dobýval grepem. Jak to vypadá, ukazuje ukázková stránka níže.