Beliebte Content-Management-Systeme, wie Joomla!, werden rund um die Uhr angegriffen.
Ein gängiger Angriff ist das Ausprobieren von Benutzernamen und Passwörtern. Sind im Joomla! bekannte oder zu einfache Kombinationen aus Benutzername und Password vorhanden, kann man damit in das Joomla! einbrechen und dann möglicherweise Unfug, zum Beispiel Spam-Versand, anstellen.
Dieser Artikel zeigt eine Möglichkeit, die IP-Adressen, von denen aus zahlreiche solche Login-Versuche durchgeführt werden, automatisiert mit Fail2ban zu blockieren. Die Sperrung erfolgt in diesem Beispiel nach 5 fehlerhaften Logins im Zeitraum von 10 Minuten, ebenfalls 10 Minuten nach der Sperre wird diese wieder aufgehoben. So werden automatisierte Login-Versuche ausgebremst.
Der Artikel richtet sich an Server-Administratoren und Webhoster.
Wie findet der Login-Angriff statt?
Die Login-URLs für Joomla! (und andere CMS) sind prinzipiell immer gleich:
- Admin Login: www.meinejoomlaseite123.de/administrator
- Frontend-Login: www.meinejoomlaseite123.de/index.php?option=com_users&view=login
Selbst dann, wenn kein Menupunkt für einen Login erstellt wurde, kann man die Komponente "com_users" und den View "login" mit der eben gezeigten URL auf jeder Joomla!-Seite aufrufen.
Wie kann der Login-Angriff erkannt werden?
Apache-Log: ungeeignet
Normalerweise landen die Zugriffe im Apache-Log.
Ein Login sieht beispielsweise so aus:
2003:ee:63e2:c300:: joomlatest25052018.andrehotzler.de - [25/May/2018:23:44:22 +0200] "POST /administrator/index.php HTTP/1.1" 200 2358 "https://joomlatest25052018.andrehotzler.de/administrator/index.php" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36" 944 2922
Dieser Eintrag nützt uns wenig, da sich folgende Probleme zeigen:
- Die IP-Adresse ist in diesem Beispiel unvollständig, da sie aus Datenschutzgründen beim Webhoster anonymisiert wurde - ohne IP-Adresse können wir aber nichts sperren
- "POST /administrator/index.php" zeigt in diesem Beispiel einen Login.
Andere Aktionen im Backend erzeugen aber teils den selben Eintrag im Apache-Log.
Wir können also die "legale" Benutzung nicht von ungewollter Nutzung unterscheiden.
Benutzerprotokollierung: geeignet
Joomla legt standardmäßig ein weiteres Logfile namens "error.php" an. Es liegt im Protokollverzeichnis, welcher unter "System" konfiguriert werden kann.
Und so sehen Einträge in der "error.php" aus, nachdem fehlerhafte Logins durchgeführt wurden:
12136# cat error.php
#
#<?php die('Forbidden.'); ?>
#Date: 2018-05-25 22:10:19 UTC
#Software: Joomla Platform 13.1.0 Stable [ Curiosity ] 24-Apr-2013 00:00 GMT
#Fields: datetime priority clientip category message
2018-05-25T22:10:19+00:00 INFO 2003:ee:63e2:c300:a126:145c:1acb:47a5 joomlafailure Benutzername und Passwort falsch oder das Benutzerkonto existiert noch nicht!
2018-05-25T22:10:26+00:00 INFO 2003:ee:63e2:c300:a126:145c:1acb:47a5 joomlafailure Username and password do not match or you do not have an account yet.
Wie man gut sehen kann, werden u.a. die IP-Adresse und eine Fehlermeldung in der Sprache, die am Login angezeigt wird, protokolliert.
Erzeugt werden die Einträge durch das Plugin "Benutzerprotokollierung":
Wenn das Plugin ausgeschaltet ist, dann erfolgt auch keine Protokollierung. Bei eingeschalteten Plugin und der damit verbundenen Protokollierung der IP-Adresse müssen möglicherweise Datenschutz-Aspekte beachtet werden, hier kann ein Datenschutz-Fachmann sicher Auskunft geben.
Fail2ban-Regel für die Auswertung der "error.php"
Die hier beschriebenen Regeln beziehen sich auf Fail2ban 0.10 (mit Unterstützung für ipv6), getestet wurde mit Joomla! 3.8.8. Unter Debian/GNU Linux kann man in der stable/oldstable/testing-Version die Version aus "testing" nehmen. Auf anderen Systemen heißen die Ordner und Dateien möglicherweise anders und müssen an die eigene Umgebung angepasst werden.
Wie müssen in Fail2ban einen Filter und einen Jail anlegen. Dazu legen wir folgende Dateien an:
- /etc/fail2ban/filter.d/joomla-login-errors.conf
Beim Filter ist wichtig, dass man nur die Zeilen filtert, die sich auf den Benutzernamen beziehen und "joomlafailure" beinhalten. In der Regex-OR-Regel (in Klammern) muss man das Wort "Benutzername" in allen Sprachen eintragen, die die Seite unterstützt.[Definition] failregex = ^.*INFO <HOST>.*joomlafailure.*(Benutzername|Username).*
- /etc/fail2ban/jail.d/joomla-login-errors.conf
In diesem Jail müssen die passenden Pfade auf dem Webserver eingetragen werden. Das Beispiel hier deckt gängige Pfade auf Servern, die mit Liveconfig verwaltet werden ab.[joomla-login-errors] enabled = true filter = joomla-login-errors port = http,https maxretry = 6 findtime = 18000 bantime = 18000 logpath = /var/www/*/tmp/*error.php /var/www/*/htdocs/tmp/*error.php /var/www/*/htdocs/logs/*error.php /var/www/*/apps/logs/*error.php /var/www/*/htdocs/administrator/logs/*error.php /var/www/*/apps/*/administrator/logs/*error.php
Lade Dir die Datei hier: https://github.com/ahotzler/... herunter.
Ergebnis in Fail2Ban
Der folgende Auszug aus dem Fail2ban-Logfile (Loglevel=3) zeigt den Start von Fail2ban und das Bannen einer IP nach 5 Fehlversuchen. "banTime", "maxRetry" usw. sind in diesem Beispiel Standardwerte.
2018-05-26 00:21:29,814 fail2ban.server [302]: INFO Starting Fail2ban v0.10.2
2018-05-26 00:21:29,816 fail2ban.database [302]: INFO Connected to fail2ban persistent database '/var/lib/fail2ban/fail2ban.sqlite3'
2018-05-26 00:21:29,833 fail2ban.jail [302]: INFO Creating new jail 'joomla-login-errors'
2018-05-26 00:21:29,834 fail2ban.jail [302]: INFO Jail 'joomla-login-errors' uses poller {}
2018-05-26 00:21:29,834 fail2ban.jail [302]: INFO Initiated 'polling' backend
2018-05-26 00:21:29,851 fail2ban.filter [302]: INFO Added logfile: '/var/www/joomlatest/htdocs/logs/error.php' (pos = 0, hash = 9762053d4defb8be822cb0957983a6b8796976d6)
2018-05-26 00:21:29,866 fail2ban.filter [302]: INFO encoding: UTF-8
2018-05-26 00:21:29,866 fail2ban.filter [302]: INFO maxRetry: 5
2018-05-26 00:21:29,866 fail2ban.filter [302]: INFO findtime: 600
2018-05-26 00:21:29,866 fail2ban.actions [302]: INFO banTime: 600
2018-05-26 00:21:29,868 fail2ban.jail [302]: INFO Jail 'joomla-login-errors' started
2018-05-26 00:21:43,934 fail2ban.filter [302]: INFO [joomla-login-errors] Found 2003:ee:63e2:c300:a126:145c:1acb:47a5 - 2018-05-26 00:21:43
2018-05-26 00:21:47,147 fail2ban.filter [302]: INFO [joomla-login-errors] Found 2003:ee:63e2:c300:a126:145c:1acb:47a5 - 2018-05-26 00:21:46
2018-05-26 00:21:48,352 fail2ban.filter [302]: INFO [joomla-login-errors] Found 2003:ee:63e2:c300:a126:145c:1acb:47a5 - 2018-05-26 00:21:48
2018-05-26 00:21:49,556 fail2ban.filter [302]: INFO [joomla-login-errors] Found 2003:ee:63e2:c300:a126:145c:1acb:47a5 - 2018-05-26 00:21:49
2018-05-26 00:21:53,569 fail2ban.filter [302]: INFO [joomla-login-errors] Found 2003:ee:63e2:c300:a126:145c:1acb:47a5 - 2018-05-26 00:21:53
2018-05-26 00:21:53,907 fail2ban.actions [302]: NOTICE [joomla-login-errors] Ban 2003:ee:63e2:c300:a126:145c:1acb:47a5