Το 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

Μια σειρά που γλιτώνει μια εβδομάδα

  1. Μία εβδομάδα σε DetectionOnly με κανονική δουλειά στον ιστότοπο, τη διαχείριση και τις μεταφορτώσεις.
  2. Λίστα συχνότητας κανόνων από το αρχείο ελέγχου. Δουλέψτε από πάνω προς τα κάτω — οι πρώτοι τρεις τέσσερις ευθύνονται για το ενενήντα τοις εκατό του θορύβου.
  3. Για καθέναν: βρείτε ποια παράμετρος και σε ποια σελίδα. Κάντε την εξαίρεση ανά παράμετρο, όχι ανά κανόνα.
  4. Μόνο τώρα SecRuleEngine On.
  5. Μία φορά τον μήνα, ρίξτε μια ματιά στους αποκλεισμούς: ο ιστότοπος άλλαξε, άρα εμφανίστηκαν νέα ψευδώς θετικά.

Σε αυτό το τελευταίο σημείο συνήθως καταρρέει η υπόθεση: το αρχείο ελέγχου είναι γιγαμπάιτ κειμένου και κανείς δεν θα το διαβάσει με το χέρι. Το νόημα ενός συγκεντρωτικού πίνακα είναι να έχετε μπροστά σας τη λίστα των κανόνων που ενεργοποιήθηκαν, τα αποκλεισμένα αιτήματα και το ενεργό σύνολο κανόνων, αντί να τα βγάζετε με grep. Πώς μοιάζει αυτό το δείχνει η σελίδα επίδειξης παρακάτω.