Wordfence to fail2ban
1. November 2019 um 18:50 Uhr von Atari-Frosch
Das WordPress-Plugin Wordfence ist ein weit verbreitetes Sicherheits-Plugin, um WordPress und auch dessen Clone ClassicPress vor unerwünschten Zugriffen zu schützen. Leider hat es einen Nachteil: Es kann Zugriffe nur auf Webserver-Ebene blockieren. Das heißt, auch intensive Einbruchsversuche, aggressives Crawling, oder sogar Versuche, angreifbare Plugins oder Themes etc. zu finden, hämmern trotzdem unter Umständen stunden- bis tagelang auf den Webserver ein. Und diese Angreifer können wirklich sehr aggressiv und ausdauernd sein.
Man könnte nun nach einer Mail von Wordfence, daß da mal wieder ein Host keine Ruhe gibt, diesen Host in die Firewall eintackern. Diese Einträge müßte man dann aber ständig nachhalten, denn irgendwann hören die Angriffe von einem bestimmten Host ja auch mal wieder auf, und die Firewall-Einträge möchte man ja eher knapp halten, damit die Überprüfung bei jedem Zugriff von außen nicht zu lange dauert.
Andererseits verrät einem Wordfence nicht unbedingt alles, was es so sieht; eine Mail, mit der mir Wordfence erzählt, daß da gerade ein Host wegen aggressivem Crawlings „geblockt“ wurde, sagt mir nicht, ob der Host gleich wieder aufgehört hat oder ob er noch stundenlang weitermacht. Diese Informationen findet man nur in der primären Datenbanktabelle von Wordfence; die weiteren Versuche werden dem Admin nicht mehr mitgeteilt. Wenn Wordfence aufgrund einer Information aus dem Wordfence Security Network einen Host abwehrt, bekommt man das gar nicht zu sehen; es steht nur in der Datenbank. Eine Mail an den Admin wird deswegen nicht versandt.
Meine Idee war nun, diese schlaue Datenbanktabelle und fail2ban zu verheiraten. Denn im Gegensatz zu Wordfence blockt fail2ban über die Firewall, also zum Beispiel iptables, und läßt diese Angreifer damit gar nicht mehr zum Webserver durch. Da ich aber nun kein PHP kann (und es auch einklich gar nicht lernen will) und erst recht kein Plugin schreiben kann, habe ich diese Idee in Python3 quasi von außen her umgesetzt. Das Ergebnis: wftof2b.py oder in der Langversion „Wordfence to fail2ban“.
Dabei kommt mir entgegen, daß Wordfence seine Tabellen in der Wordpress-Datenbank mit ablegt, was bedeutet, daß ich mir einfach nur die Zugangsdaten zu der Datenbank aus der Datei wp-config.php ziehen muß, um in die Datenbank hineingreifen zu können. Da ich nur lesend zugreife, kann dabei auch nichts kaputtgehen.
In einem Durchgang rufe ich dabei die Datenbanken aller eingetragenen Blogs bzw. Wordfence-Installationen nacheinander ab, schreibe die gewonnenen Daten in ein eigenes, akkumuliertes Log, sortiere das dann durch (damit die Zeitstempel in der richtigen Reihenfolge stehen), und dieses akkumulierte Log wird dann von einem fail2ban-Filter abgegriffen und auf bestimmte Eigenheiten hin untersucht. Dabei lasse ich derzeit den Abruf auf die Datenbank alle fünf Minuten laufen, damit Angriffswellen möglichst schnell gestoppt werden können. Wegen des notwendigen Zugriffs auf die wp-config.php können auf diese Weise natürlich nur die Datenbanken von Blogs abgegriffen werden, die auf demselben Host liegen.
Was ich dabei nicht verhindern kann, sind Angriffswellen auf die Logins. Das heißt, doch, kann ich natürlich schon, mache ich auch, aber fehlerhafte Login-Versuche werden zum einen üblicherweise von fail2ban aus dem Webserver-Log heraus erkannt und direkt geblockt. Andererseits kommen solche Angriffswellen allerdings oft von sehr vielen unterschiedlichen Hosts, so daß man sie auf diese Weise nicht sinnvoll stoppen kann. Wenn tausend Hosts binnen weniger Stunden nur jeweils einmal versuchen, in ein Blog einzubrechen – und ja, ich habe solche Angriffswellen mehrfach gesehen –, ist die Methode schlicht ungeeignet.
Was „Wordfence to fail2ban“ also primär abblockt, sind aggressive Crawler und die Angriffswellen auf Plugins. Gerade im Zusammenspiel mit apache als Webserver können diese Angriffe schon ziemlich Last produzieren. Aber auch einen nginx, wie er bei mir läuft. muß man damit nicht unnötig belasten, zumal auch der PHP-Interpreter dabei teilweise ordentlich zu tun bekommt.
Wer also WordPress oder ClassicPress mit Wordfence sowie fail2ban installiert und außerdem Python3 zur Verfügung hat, ist gerne eingeladen, das Script auszuprobieren. Wie gesagt, es kann nichts kaputtgehen. Eine Installationsanleitung ist dabei, und natürlich sollte man auch die README gelesen haben, bevor man das ganze aktiviert.
Als Lizenz habe ich erstmal die GPLv3 gewählt, ob das bei späteren Versionen so bleibt, weiß ich noch nicht. Mich stört dabei vor allem der Autor. – Eine „strengere“ Lizenz wird es aber nicht werden.