Vor einiger Zeit hab eich eine Beitrag verfasst wie man ownCloud mit Fail2Ban absichern kann nun möchte ich zeigen wie man das selbe mit WordPress macht.
WordPress Plugin
Da WordPress standardmässig fehlerhafte Logins immer mit einem 200 HTTP code (OK) bestätigt ist es sehr schwierig die Logins zu überwachen. Mit der folgenden Erweiterung wird es möglich das bei fehlerhaften Logins das aus dem code 200 ein code 403 HTTP code (Forbidden) in den Logs aufgeführt wird.
Im WordPress wp-content Ordner muss ein neuer Ordner mit dem Namen „mu-plugins“ für Must Use Plugins angelegt werden, darin muss eine neue Datei mit einem beliebigen Namen (bei uns wp-login.php) angelegt werden mit dem folgenden Inhalt.
<?php function my_login_failed_403() { status_header( 403 ); } add_action( 'wp_login_failed', 'my_login_failed_403' );
Erstellen der Filterdatei und Konfiguration in Fail2Ban
Erstellen der Datei /etc/fail2ban/filter.d/wordpress.conf mit folgenden Inhalt:
[Definition] failregex = <HOST>.*POST.*(wp-login\.php|xmlrpc\.php).* 403 ignoreregex =
Und in der Datei /etc/fail2ban/jail.conf folgendes hinzufügen:
[wordpress] enabled = true filter = wordpress logpath = /var/log/httpd/access_log maxretry = 3
Neue Regeln für Fail2Ban testen
Welches natürlich nur geht, wenn man sich mal falsch anmeldet, sonst kann nichts gefunden werden.
root@test:/# fail2ban-regex /var/log/apache2/access.log /etc/fail2ban/filter.d/wordpress.conf Running tests ============= Use failregex filter file : wordpress, basedir: /etc/fail2ban Use log file : /var/log/apache2/access.log Use encoding : UTF-8 Results ======= Failregex: 38 total |- #) [# of hits] regular expression | 1) [38].*POST.*(wp-login\.php|xmlrpc\.php).* 403 `- Ignoreregex: 0 total Date template hits: |- [# of hits] date format | [230241] Day(?P<_sep>[-/])MON(?P=_sep)ExYear[ :]?24hour:Minute:Second(?:\.Microseconds)?(?: Zone offset)? `- Lines: 230241 lines, 0 ignored, 38 matched, 230203 missed [processed in 239.60 sec]
Die Regeln funktionieren. Der Service/Daemon Fail2ban kann neu gestartet werden:
root@test:/# systemctl restart fail2ban
Logfile Pfad unter debian 8 ist nicht mehr /var/log/httpd/access_log sonden /var/log/apache2/access.log
mfg 😉
Nicht nur erst seit Debian 8 sondern auch schon früher, bei RHEL Systemen sind die immer unter /var/log/httpd/… zu finden.
Die Anleitung kann aber natürlich für die anderen Distributionen angepasst werden.
Ich fürchte, dieser Ansatz funktioniert nicht verlässlich. Die Annahme, dass ein fehlgeschlagener Login immer zu einem HTTP-Status-Code 200 führt, ist nicht zutreffend. Wenn ich z.B. dem POST noch ein Argument mitgebe, etwa: POST /wp-login.php?action=register führt das zu einem 302 Status-Code – obwohl der Login nicht erfolgreich war. Wir sehen derzeit Angriffe genau nach diesem Muster… fail2ban kriegt das dann mit der o.g. regex nicht mit und der Angreifer kann ungebremst Passworte erraten…
Besten Dank für den Hinweis, der Filter ist mittlerweile auch schon einige Jahre alt und auf der Seite von WordPress hat sich in der Zeit einiges getan.
Ich habe den Regex etwas angepasst und eine kleine Erweiterung für die WordPress Installation, leider noch nicht 100% getestet sollte aber so wieder funktionieren.