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.

Joomla!-Protokollverzeichnis
Joomla!-Protokollverzeichnis

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":

Joomla!-Benutzerprotokollierung
Joomla!-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
    [Definition]
    failregex = ^.*INFO <HOST>.*joomlafailure.*(Benutzername|Username).*​
    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.
  • /etc/fail2ban/jail.d/joomla-login-errors.conf
    [joomla-login-errors]
    enabled = true
    filter = joomla-login-errors
    port   = http,https
    logpath = /var/www/*/tmp/error.php
              /var/www/*/htdocs/tmp/error.php
              /var/www/*/htdocs/logs/error.php
              /var/www/*/apps/*/error.php​
    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.

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