ModSecurity med regelsættet OWASP CRS slås til på ti minutter og fra tre dage senere — efter at artikler er holdt op med at blive gemt i administrationsgrænsefladen, filuploaden er brudt sammen, og kunden ikke kan afgive en ordre, fordi adressen tilfældigvis indeholdt en apostrof. Konklusionen »WAF'en er i vejen« ligger lige for, men den er forkert: næsten alle disse blokeringer løses med tre eller fire målrettede undtagelser, og hele sagen handler om at finde dem på den rigtige måde.
Slå ikke blokering til med det samme
Den første uge er ren observation. I /etc/modsecurity/modsecurity.conf:
SecRuleEngine DetectionOnly
I den tilstand noterer WAF'en alt, den ville have blokeret, men blokerer intet. En uge med virkelig trafik — inklusive dit eget arbejde i administrationsgrænsefladen, billedupload og en ordre — giver listen over faktiske falske udslag i stedet for hypotetiske. At skifte til On giver først mening, når den liste er gennemgået.
Sådan virker CRS: ikke én regel, men en sum
Nøglen til alt det følgende. CRS blokerer næsten aldrig en forespørgsel med én enkelt regel. Hver regel, der udløses, lægger anomalipoint til forespørgslen, og blokeringen sker, når summen overstiger tærsklen. Derfor ser du ikke én linje i logfilen, men flere, og den sidste er reglen med id 949110 — den, der summerer.
Praktisk konklusion: undtagelsen skal laves for reglen, der gav pointene, ikke for 949110. Slår du den summerende regel fra, slår du hele sættet fra, og WAF'en er kun tilbage som en linje i konfigurationen.
Næste følge er paranoiaeniveauet. Som standard er det ét, og det er det rigtige valg. Niveau 2 og 3 tilføjer regler, der med sikkerhed giver falske udslag på almindelige hjemmesider, og de bør først slås til, når niveau ét er fuldt indkørt.
Find den skyldige regel
Alt det nødvendige findes i revisionsloggen (/var/log/modsec_audit.log) og i webserverens fejllog. Vi søger på blokeringstidspunktet:
sudo grep -o 'id "[0-9]*"' /var/log/modsec_audit.log | sort | uniq -c | sort -rn | head
Det er en frekvensliste over udløste regler. Derefter ser vi på, hvad et bestemt id rent faktisk blev udløst af:
sudo grep -A5 'id "942100"' /var/log/modsec_audit.log | head -40
Tre ting er nødvendige: reglens id, parameterens navn (ARGS:content, ARGS:comment) og forespørgslens sti. Af dem bygges undtagelsen.
De sædvanlige mistænkte
Listen gentager sig fra hjemmeside til hjemmeside:
- 942100 — SQL-injektion. Udløses på tekstfelter med langt indhold: artikeltekst, produktbeskrivelse, kommentar. Apostroffer, parenteser og ord som
selectser mistænkelige ud for detektoren selv i almindelig tekst; - 941100 og 941xxx — XSS. Kommer sammen med en visuel editor: HTML-tags i feltet er hele dens arbejdsmåde;
- 920420 — ikke tilladt Content-Type. Ødelægger API'er og filupload: standardsættet af tilladte typer er smalt, og
application/jsonindgik ikke i ældre versioner; - 913100 — scanner efter User-Agent. Fanger legitime værktøjer sammen med scannerne: tilgængelighedsovervågning, curl i dine egne scripts;
- 200002, 200004 — fejl ved fortolkning af forespørgslens krop. Betyder som regel ikke et angreb, men en overskredet størrelsesgrænse, altså upload af en stor fil.
Tre måder at lave undtagelser på
I stigende grovhed. Alle skrives i en separat fil (for eksempel /etc/modsecurity/crs/REQUEST-900-EXCLUSION-RULES.conf) og ikke i CRS' egne filer: regelsættet opdateres, og dine ændringer forsvinder ved opdateringen.
Tag en parameter ud fra én regel. Den mest præcise mulighed, og den vi sigter mod:
SecRuleUpdateTargetById 942100 "!ARGS:content"
Slå reglen fra kun på én sti. Passer, når en bestemt side støjer — editoren, importen, anmeldelsesformularen:
SecRule REQUEST_URI "@beginsWith /admin/post" \
"id:1001,phase:1,pass,nolog,ctl:ruleRemoveById=942100"
Slå reglen helt fra. Sidste udvej og næsten altid et tegn på, at årsagen ikke er fundet:
SecRuleRemoveById 942100
Forskellen mellem den første og den tredje er betydelig. I det første tilfælde holder feltet »artikeltekst« op med at blive kontrolleret for SQL-injektioner af én regel; i det andet og tredje holder hele hjemmesiden op med at blive kontrolleret. Forskellen i arbejdsindsats er omkring fem minutter.
Efter ændringerne — konfigurationskontrol og blød genindlæsning:
sudo apachectl configtest && sudo systemctl reload apache2
sudo nginx -t && sudo systemctl reload nginx
Rækkefølgen der sparer en uge
- En uge i
DetectionOnlymed almindeligt arbejde på hjemmesiden, inklusive administrationsgrænsefladen og uploads. - Frekvenslisten over regler fra revisionsloggen. Gå oppefra og ned — de tre første giver halvfems procent af støjen.
- For hver af dem: find ud af, hvilken parameter og hvilken side det gælder. Lav undtagelsen per parameter, ikke per regel.
- Først nu
SecRuleEngine On. - Se på blokeringerne én gang om måneden: når hjemmesiden ændres, dukker der nye falske udslag op.
Det sidste punkt er det, alt normalt strander på: revisionsloggen er gigabyte af tekst, og ingen læser den i hånden. Pointen med et samlet panel er, at listen over udløste regler, blokerede forespørgsler og det aktive sæt ligger foran øjnene i stedet for at blive gravet frem med grep. Hvordan det ser ud, viser demonstrationssiden nedenfor.