ModSecurity met de OWASP CRS-regelset wordt in tien minuten aangezet en drie dagen later weer uit — nadat artikelen niet meer opslaan in het beheer, het uploaden van bestanden stukgaat en een klant geen bestelling kan plaatsen omdat er een apostrof in zijn adres stond. De conclusie «de WAF zit het werk in de weg» dringt zich op, en ze is onjuist: bijna al die blokkades worden verholpen met drie of vier nauwkeurige uitzonderingen, en alles draait erom die correct te vinden.
Zet het blokkeren niet meteen aan
De eerste week is alleen waarnemen. In /etc/modsecurity/modsecurity.conf:
SecRuleEngine DetectionOnly
In die modus noteert de WAF alles wat hij zou hebben geblokkeerd en blokkeert hij niets. Een week echt verkeer — inclusief uw eigen werk in het beheer, het uploaden van afbeeldingen en een bestelling — levert de lijst met werkelijke valse meldingen op in plaats van hypothetische. Overgaan op On heeft pas zin als die lijst is afgehandeld.
Hoe CRS werkt: geen regel, maar een som
Dit is de sleutel tot al het volgende. CRS blokkeert een verzoek vrijwel nooit met één enkele regel. Elke regel die afgaat voegt anomaliepunten toe, en de blokkade valt wanneer de som een drempel overschrijdt. Daarom ziet u in het logboek niet één regel maar meerdere, en de laatste is de regel met aanduiding 949110 — degene die de optelsom maakt.
Praktisch gevolg: de uitzondering hoort bij de regel die de punten toekende, niet bij 949110. Zet u de optellende regel uit, dan zet u de hele set uit, en van de WAF blijft alleen een regel in een configuratiebestand over.
Het tweede gevolg is het paranoia-niveau. Dat staat standaard op één, en dat is de juiste keuze. Niveau 2 en 3 voegen regels toe die op gewone sites naar hun aard vals alarm geven; die aanzetten heeft pas zin wanneer niveau één volledig is afgeregeld.
De schuldige regel vinden
Alles wat nodig is staat in het auditlogboek (/var/log/modsec_audit.log) en in het foutlogboek van de webserver. Zoek op het tijdstip van de blokkade:
sudo grep -o 'id "[0-9]*"' /var/log/modsec_audit.log | sort | uniq -c | sort -rn | head
Dat is een frequentielijst van de afgegane regels. Kijk daarna bij een concrete aanduiding waarop hij precies afging:
sudo grep -A5 'id "942100"' /var/log/modsec_audit.log | head -40
Er zijn drie dingen nodig: de regelaanduiding, de parameternaam (ARGS:content, ARGS:comment) en het pad van het verzoek. Daaruit wordt de uitzondering opgebouwd.
De gebruikelijke verdachten
De lijst herhaalt zich van site tot site:
- 942100 — SQL-injectie. Gaat af bij tekstvelden met lange inhoud: de body van een artikel, een productbeschrijving, een reactie. Aanhalingstekens, haakjes en woorden als
selectogen ook in gewone tekst verdacht voor de detector; - 941100 en de familie 941xxx — XSS. Ze komen mee met de visuele editor: HTML-tags in een veld zijn precies de zin van zijn werk;
- 920420 — niet-toegestaan Content-Type. Breekt API's en bestandsuploads: de standaardset toegestane typen is smal, en in oudere versies zat
application/jsoner niet bij; - 913100 — scanner op basis van de User-Agent. Vangt naast scanners ook legitieme hulpmiddelen: beschikbaarheidsbewaking, curl in uw eigen scripts;
- 200002, 200004 — fouten bij het ontleden van de verzoekinhoud. Ze duiden meestal niet op een aanval maar op een overschreden groottelimiet, oftewel het uploaden van een groot bestand.
Drie manieren om een uitzondering te maken
In oplopende grofheid. Ze horen alle in een eigen bestand (bijvoorbeeld /etc/modsecurity/crs/REQUEST-900-EXCLUSION-RULES.conf) en niet in de CRS-bestanden zelf: de regelset wordt bijgewerkt en uw wijzigingen zouden ermee verdwijnen.
Eén parameter uit één regel halen. De nauwkeurigste variant, en degene om naar te streven:
SecRuleUpdateTargetById 942100 "!ARGS:content"
Een regel alleen op één pad uitzetten. Passend wanneer een concrete pagina lawaai maakt — een editor, een import, een beoordelingsformulier:
SecRule REQUEST_URI "@beginsWith /admin/post" \
"id:1001,phase:1,pass,nolog,ctl:ruleRemoveById=942100"
De regel volledig uitzetten. Laatste redmiddel en vrijwel altijd een teken dat de oorzaak niet is gevonden:
SecRuleRemoveById 942100
Het verschil tussen de eerste en de derde is aanzienlijk. In het eerste geval wordt één veld — de tekst van het artikel — door één regel niet meer op SQL-injectie gecontroleerd; in het tweede en derde wordt de hele site niet meer gecontroleerd. Het verschil in moeite bedraagt zo'n vijf minuten.
Controleer na de wijzigingen de configuratie en herlaad rustig:
sudo apachectl configtest && sudo systemctl reload apache2
sudo nginx -t && sudo systemctl reload nginx
Een volgorde die een week bespaart
- Een week in
DetectionOnlymet normaal werk op de site, beheer en uploads inbegrepen. - Frequentielijst van regels uit het auditlogboek. Van boven naar beneden afwerken — de eerste drie of vier vormen negentig procent van het lawaai.
- Bij elke: uitzoeken welke parameter op welke pagina. De uitzondering maakt u per parameter, niet per regel.
- Pas nu
SecRuleEngine On. - Eens per maand even in de blokkades kijken: de site is veranderd, dus er zijn nieuwe valse meldingen bijgekomen.
Op dat laatste punt loopt het meestal stuk: het auditlogboek is gigabytes tekst die niemand met de hand leest. De zin van een paneel is de lijst met afgegane regels, de geblokkeerde verzoeken en de actieve set voor ogen te hebben in plaats van ze met grep op te diepen. Hoe dat eruitziet, toont de demopagina hieronder.