Server Security mit dem Apache-Modul ModEvasive
Alle Websites down - was nun?
Der mysqld hat sich wieder einmal verabschiedet - Fehler in der Konfiguration und Hardwaredefekte können nach einiger Zeit der Suche ausgeschlossen werden. Aber was ist passiert, dass sich alle auf dem Server gehosteten Websites verabschiedet haben, weil der mySQL-Server zusammengebrochen ist?
DDoS - Distributed-Denial-of-Service, was soviel bedeutet wie "verbreitete Dienstverweigerung", die sich einstellt, wenn eine Unmenge von Anfragen eine Überlastung des Servers hervorrufen. Die Motivation eines solchen Angriffs möchte ich nun nicht weiter verfolgen, Fakt ist, dass der Server in die Lage versetzt werden muss, solchen unerwünschten Angriffen stand zu halten. Auch wenn in unserem Fall der mySQL-Server die Flügel streckte, der Angriff kam über den Apache Webserver und dort ist auch die geeignete Stelle, um sich dieser Angriffe zu erwehren. Ein Blocken der unerwünschten Anfragen bereits im Webserver, sorgt dafür, dass sie gar nicht erst weitergeleitet werden, zu anderen Komponenten des "Datennetzes", wie beispielsweise dem MySQL-Server.
Server Security mit dem Apache Modul ModSecurity
Unser erster Versuch, den Server zu schützen, war das Apache Modul "ModSecurity". Dabei handelt es sich um eine WAF (Web-Application-Firewall) die einen Zugriffsschutz in Echtzeit gewährleistet. Dies geschieht über eine Vielzahl von Regeln, die jederzeit erweitert, oder auch gezielt entfernt werden können. Diese Regeln prüfen den HTTP-traffic und blocken zuverlässig unerwünschte Anfragen. Wir installierten die von Open Web Application Security Project frei zu Verfügung gestellten ModSecurity Core Rule Sets, abgekürzt auch oft unter "OWASP CRS" zu finden. Dort sind Regeln für die gängigsten Angriffs-/Bedrohungs-Kategorien enthalten, wie beispielsweise SQL injection, cross site scripting, file inclusion, php code injection, session fixation usw. - insgesamt mehrere Hundert wenn nicht Tausende von Regeln, jede mit einer eigenen ID und der Möglichkeit, die Regel in der Konfiguration zu entfernen, beispielsweise mit "SecRuleRemoveById 981173".
Nach der Installation von ModSecurity aber dann ein recht böses Erwachen:
- HTTP/2-Aufrufe können nicht mehr durchgeführt werden, diese müssen erst explizit in der ModSecurity-Konfiguration "erlaubt" werden
- bots und andere Seitenaufrufe, die keinen "accept header" beinhalten werden geblockt - die dafür zuständigen Regeln müssen identifiziert und explizit ausgenommen werden
- Drupal AJAX-Aufrufe werden geblockt, das ist besonders fatal, wenn Aktualisierungen, beispielsweise in Drupal-views, via AJAX vorgenommen werden: diese views werden von ModSecurity mit einem "access denied 403" beantwortet
Die Abhilfe ist, beispielsweise für den dritten Fall der AJAX-Aufrufe, das ModSecurity für den betroffenen Pfad abzuschalten durch folgenden Eintrag in der Konfiguration:
SecRule REQUEST_URI "/views/ajax" "phase:1,log,pass,id:99998,severity:1,msg:'Pass Drupal AJAX',ctl:ruleEngine=Off"
Allerdings: was passiert eigentlich, wenn wir weitere Drupal-Module im Einsatz haben, die ihre eigenen AJAX-Pfade definieren? Diese werden dann ebenfalls nicht funktionieren und dies ist das große Problem bei ModSecurity. Es wird von Fällen berichtet, bei denen ein blogpost unter Drupal nicht gespeichert werden konnte, weil im content body-Text verstreut die drei strings "update", "set" und "=" vorhanden waren - ModSecurity erkannte das als SQL injection und verhinderte das Speichern!
Wir begannen also, aus im Netz verfügbaren Artikeln und Hinweisen eine große Liste von "Ausnahmen" zusammen zu stellen, um damit unsere eigene ModSecurity Regel-Konfiguration zu erstellen. Wir erkannten dann allerdings relativ schnell, dass unter der Prämisse "choose your rules wisely", ein fulltime Job daraus wird, und jede Installation eines neuen Drupal Moduls ein Abenteuer, weil man nie sicher sein kann, dass auch wirklich alle Pfade, die das Modul definiert, funktionieren, bzw. eben von ModSecurity und einer seiner 1000 Regeln nicht geblockt wird. Dieser Umstand führte uns zu einer alternativen Möglichkeit des Apache-Schutzes: ModEvasive.
Die Lösung: ModEvasive mit der Konfiguration von HeliconTech
ModEvasive ist ein Apache-Modul, das "evasive action", also Ausweichmanöver einleitet, falls DoS- oder brute-force-Angriffe erkannt werden. Das Modul verfolgt dabei die eingehenden HTTP-Verbindungen und überprüft, wieviel Anfragen an eine Seite in einem konfigurierbaren Zeitrahmen gestellt wurden. Wenn die Anzahl gleichzeitiger Anfragen einen spezifizierten Schwellwert überschreiten, wird die Anfrage mit einem 403 geblockt und spart damit eine Menge Bandbreite und Server-Resourcen. Die Konsequenz für den Angreifer ist, dass die nächsten Sekunden (konfigurierbar) alle Anfragen von seiner IP in einem "403 forbidden" enden, und bei jedem neuen request die Sperrzeit wieder von vorne beginnt.
Übrigens: ein "normaler Surfer", der über einen Proxy oder ein NAT-Gateway zugreift, ist davon nicht betroffen, dass eventuell zeitgleich andere Surfer mit gleicher IP auf der Seite unterwegs sind - das Modul zählt immer "pro listener" und ein Apache hat davon immer mehrere gleichzeitig laufen.
Natürlich hat dieses Modul, das auf Applikationslevel agiert, auch seine Grenzen: wird der Angriff so massiv, dass er die komplette Bandbreite ausnutzt oder der Server hardwaretechnisch nicht mehr mitkommt, ist der Angriff doch noch erfolgreich - für solche Fälle müssen dann am Besten die entsprechenden IPs komplett geblockt werden, beispielsweise über die .htaccess.
Die Konfiguration von ModEvasive ist grundsätzlich relativ selbsterklärend, allerdings steckt hier der Teufel, wie so oft, im Detail: Im namentlich irreführenden Konfigurations-Parameter "DOSLogDir" wird ein Verzeichnis angegeben, in dem die geblockten IP-Adressen als Datei gespeichert werden - dies wird von ModEvasive benötigt, um den "lock-Mechanismus" bei konsekutiven Anfragen durchzuführen.
Nachdem also das Modul installiert und konfiguriert war, wurde das Ganze auf dem Produktivserver getestet - natürlich kam es auch dort zu Überraschungen, weil der Zugriff auf verschiedene Seiten geblockt wurde.
Nach Recherche stellte sich heraus, dass beispielsweise eine Seite sehr viele kleine Bilder enthält (ca. 130 Stück) und jedes Bild einen eigenen request darstellt - dadurch werden natürlich mindestens 130 requests auf die gleiche Seite von der gleichen IP durchgeführt, worauf ModEvasive, entsprechend seiner Konfiguration richtigerweise, einen Angriff feststellt und den request blockt. Ebenso erging es dem "bingbot", der wohl auch "zu aggressiv" die Seiten durchforstet.
Die Kunst besteht also nun darin, die Konfiguration von ModEvasive so auszurichten, dass "normale" Zugriffe noch nicht als Angriff gewertet werden, alles was darüber hinausgeht, aber sehr wohl geblockt wird. Nach vielen Tests und mehrfachen Analysen der logfiles, haben wir nun die ModEvasive-Konfiguration von HeliconTech übernommen und fahren damit seither sehr gut: mysqld verrichtet zuverlässig seinen Dienst.