WordPress mit Fail2Ban gegen Brute Force Angriffe schützen

WordPress bietet von Hause aus leider keinen Schutz gegen Brute Force Angriffe. Ich möchte gerne nach drei vergeblichen Login-Versuchen die IP-Adresse sperren, von der die Login-Versuche erfolgten.

Da bei mir sowieso Fail2Ban läuft, um SSH-Logins zu limitieren, bietet es sich geradezu an das auch für WordPress zu verwenden. Hierzu muss ich allerdings erstmal heraus finden wie ich denn einen erfolgreichen von einem misslungenen Login unterscheiden kann.

Schauen wir uns zunächst mal einen misslungenen Login im Apache-Log /var/log/apache2/access.log an:

217.89.77.180 - - [06/Jul/2018:08:53:43 +0200] "POST /wp-login.php HTTP/1.1" 200 6337 "https://www.gluecksgriff-taschen.de/wp-login.php?loggedout=true" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36"

Und nun einen erfolgreichen Login:

217.89.77.180 - - [06/Jul/2018:08:54:06 +0200] "POST /wp-login.php HTTP/1.1" 302 5278 "https://www.gluecksgriff-taschen.de/wp-login.php" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36"

Offensichtlich gibt ein erfolgreicher Login einen Redirect-Status 302 zurück, während bei einem misslungenem Login-Versuch ein Status 200 zurückgegeben wird. Das kann ich natürlich prima für eine entsprechende Fail2Ban-Regel nutzen.

Hierzu erstelle ich unter /etc/fail2ban/filter.d einen Datei namens wordpress.conf mit folgendem Inhalt.

[INCLUDES]
before = common.conf

[Definition]
failregex = <HOST>.*POST.*(wp-login\.php|xmlrpc\.php).* 200

Der unter failregex angegebene reguläre Ausdruck bedeutet die Zeile beginnt mit der IP-Adresse, danach kommt irgendwann das Wort „POST“, dann irgendwann „wp-login.php“ und dann irgendwann ein Leerzeichen gefolgt von der Zahl 200. Das passt genau auf die Logzeile mit dem fehlgeschlagenem Login, sollte also funktionieren.

Nun muss ich Fail2Ban nur noch mitteilen, dass er diese Definition auch verwenden soll. Dazu erstelle ich eine Datei /etc/fail2ban/jail.d/wordpress.conf mit folgendem Inhalt:

[wordpress]
enabled = true
port = http,https
filter = wordpress
logpath = /var/log/apache2/access.log
maxretry = 3
bantime = 3600

Hiermit wird die für die Login-Versuche verwendete IP für 1 Stunde gesperrt. Zum Testen von der eigenen IP-Adresse aus würde ich natürlich erstmal deutlich geringere Werte bei bantime setzen.

Nach einem Neustart des Service mittels

sudo service fail2ban restart

ist die Regel aktiv, wie man im Logfile /var/log/fail2ban.log kontrollieren kann.

2018-11-21 16:38:33,198 fail2ban.server         [7289]: INFO    Changed logging target to /var/log/fail2ban.log for Fail2ban v0.9.6
2018-11-21 16:38:33,199 fail2ban.database       [7289]: INFO    Connected to fail2ban persistent database '/var/lib/fail2ban/fail2ban.sqlite3'
2018-11-21 16:38:33,210 fail2ban.jail           [7289]: INFO    Creating new jail 'dovecot'
2018-11-21 16:38:33,329 fail2ban.jail           [7289]: INFO    Jail 'dovecot' uses pyinotify {}
2018-11-21 16:38:33,349 fail2ban.jail           [7289]: INFO    Initiated 'pyinotify' backend
2018-11-21 16:38:33,351 fail2ban.filter         [7289]: INFO    Set findtime = 900
2018-11-21 16:38:33,351 fail2ban.actions        [7289]: INFO    Set banTime = 3600
2018-11-21 16:38:33,352 fail2ban.filter         [7289]: INFO    Set jail log file encoding to UTF-8
2018-11-21 16:38:33,353 fail2ban.filter         [7289]: INFO    Added logfile = /var/log/mail.log
2018-11-21 16:38:33,354 fail2ban.filter         [7289]: INFO    Set maxRetry = 4
2018-11-21 16:38:33,377 fail2ban.server         [7289]: INFO    Jail dovecot is not a JournalFilter instance
2018-11-21 16:38:33,391 fail2ban.jail           [7289]: INFO    Creating new jail 'wordpress'
2018-11-21 16:38:33,392 fail2ban.jail           [7289]: INFO    Jail 'wordpress' uses pyinotify {}
2018-11-21 16:38:33,397 fail2ban.jail           [7289]: INFO    Initiated 'pyinotify' backend
2018-11-21 16:38:33,398 fail2ban.filter         [7289]: INFO    Set findtime = 900
2018-11-21 16:38:33,398 fail2ban.actions        [7289]: INFO    Set banTime = 43200
2018-11-21 16:38:33,399 fail2ban.filter         [7289]: INFO    Set jail log file encoding to UTF-8
2018-11-21 16:38:33,400 fail2ban.filter         [7289]: INFO    Added logfile = /var/log/apache2/access.log
2018-11-21 16:38:33,401 fail2ban.filter         [7289]: INFO    Set maxRetry = 3
2018-11-21 16:38:33,409 fail2ban.jail           [7289]: INFO    Creating new jail 'ssh'
2018-11-21 16:38:33,409 fail2ban.jail           [7289]: INFO    Jail 'ssh' uses pyinotify {}
2018-11-21 16:38:33,416 fail2ban.jail           [7289]: INFO    Initiated 'pyinotify' backend
2018-11-21 16:38:33,417 fail2ban.filter         [7289]: INFO    Set findtime = 900
2018-11-21 16:38:33,417 fail2ban.actions        [7289]: INFO    Set banTime = 43200
2018-11-21 16:38:33,418 fail2ban.filter         [7289]: INFO    Set jail log file encoding to UTF-8
2018-11-21 16:38:33,419 fail2ban.filter         [7289]: INFO    Added logfile = /var/log/auth.log
2018-11-21 16:38:33,420 fail2ban.filter         [7289]: INFO    Set maxRetry = 3
2018-11-21 16:38:33,420 fail2ban.filter         [7289]: INFO    Set maxlines = 10
2018-11-21 16:38:33,507 fail2ban.server         [7289]: INFO    Jail ssh is not a JournalFilter instance
2018-11-21 16:38:33,518 fail2ban.jail           [7289]: INFO    Jail 'dovecot' started
2018-11-21 16:38:33,523 fail2ban.jail           [7289]: INFO    Jail 'wordpress' started
2018-11-21 16:38:33,528 fail2ban.jail           [7289]: INFO    Jail 'ssh' started
2018-11-21 16:38:33,734 fail2ban.actions        [7289]: NOTICE  [wordpress] Ban 193.201.224.225

Wer sich beim Austesten jetzt selbst ausgesperrt hat, hier steht wie man eine IP-Adresse bei Fail2Ban wieder vorzeitig entsperren kann.

1 Kommentar zu „WordPress mit Fail2Ban gegen Brute Force Angriffe schützen“

  1. Bei fehlgeschlagenen Logins wird leider nicht immer HTTP-Status Code 200 geliefert. Wenn ich dem POST noch ein Argument beifügt, z.B.
    POST /wp-login.php?action=register kommt immer ein 302 Status Code zurück – auch wenn der Login fehlschlägt. Daher greift diese fail2ban Regel dann nicht und ein Angreifer kann ungestört weiter Passwort erraten… Wir sehen gerade Angriffe nach diesem Muster.

Kommentarfunktion geschlossen.