WordPress-Login schützen
Veröffentlicht am 1.2.2019
Passwortsicherheit
Jeder Benutzer sollte sein Passwort selbst ändern können, damit auf einen Passwortdiebstahl sofort reagiert werden kann.
WordPress überprüft die Sicherheit von neuen Passwörtern direkt bei Passwortwechsel.
Damit alle Benutzer tatsächlich sichere Passwörter verwenden, sollten ausschließlich Passwörter der höchsten Sicherheitsstufe akzeptiert werden.
Weniger sichere Passwörter sollten von WordPress automatisch abgelehnt werden.
Dies kann durch kleine Anpassungen oder durch fertige WordPress-Plugins realisiert werden.
Passwortdatenbankabgleich
Zusätzlich sollte überprüft werden, ob Passwörter bereits von einem Datenleck betroffen waren und in einer der einschlägigen Passwortsammlungen geführt werden.
„Neue Passwort-Leaks: Insgesamt 2,2 Milliarden Accounts betroffen” (Heise-Online)
Diese Empfehlung beruht auch auf der aktuellen NIST-Richtlinie (National Institute of Standards and Technology).
Es ist davon auszugehen, dass öffentlich bekannte Passwörter von Crackern bevorzugt getestet werden.
Aus diesem Grund sollten solche Passwörter nicht mehr verwendet werden.
Um dies zu überprüfen ist z.B. ein automatisierter Abgleich mit der Datenbank von Troy Hunt über die API möglich:
API von Troy Hunt (Anleitung)
Auch für diese Funktion können fertige WordPress-Plugins genutzt werden.
Als Alternative dazu ist ein lokaler Abgleich der Daten mit dem Python-Script bloom.py möglich:
Gestartet wird das Script wie folgt:
python bloom.py test -s pwned-passwords-2.0.bloom Passwort
Zwei-Faktor-Authentisierung (2FA)
In der Praxis werden häufig die selben Passwörter oder nur geringfügig abgewandelte Passwörter für unterschiedliche Accounts verwendet.
Mehrfach verwendete Passwörter können durch ein Datenleck eines anderen Dienstes unbemerkt zum Sicherheitsrisiko werden.
Aus diesem Grund sollte für den WordPress-Login eine Zwei-Faktor-Authentisierung (2FA) verpflichtend eingerichtet werden.
„Zwei-Faktor-Authentisierung für höhere Sicherheit” (BSI)
Auch hierfür stehen entsprechende Plugins bereit.
Serverseitige Absicherung
Ein guter Schutz des WordPress-Logins lässt sich durch eine (zusätzliche) serverseitige Passwortvergabe realisieren.
Dabei muss der Benutzer sich zunächst durch ein Passwort gegenüber dem Server authentifizieren, bevor der eigentliche Login-Bereich von WordPress erreicht werden kann.
Ziel ist ein Login-Schutz, der von WordPress-Sicherheitslücken unabhängig ist. Darüber hinaus können Fehlanmeldungen (und damit ggf. Brute-Force-Angriffe) ressourcenschonender verarbeitet werden.
Leider sind bei diesem Verfahren zwei Passworteingaben nötig. Darüber hinaus lassen sich die serverseitigen Zugänge nur von einem Administrator des Servers einrichten und können von den Benutzern nicht geändert werden (auch existiert keine „Passwort vergessen”-Funktion).
Aus diesem Grund eignet sich dieses Verfahren nur für kleine Websites (z.B. ohne Kundenbereich).
Auch ist das Verfahren eher für kleine Unternehmen geeignet, bei denen die Website nur von wenigen, immer gleichen Personen verwaltet wird.
Bei größeren Einheiten ist die Komforteinbuße durch das zusätzliche Passwort i.d.R. nicht zu vertreten.
Anleitung für einen zusätzlichen Passwortschutz per .htaccess für den Apache:
Passwortdatei generieren:
Zunächst werden die gewünschten Benutzerzugänge mit den zugehörigen Passwörtern definiert. Auf dieser Basis wird der Inhalt für die .htpasswd generiert. Dies kann online mit dem Passwortgenerator auf aspirine.org erledigt werden.
Einstellungen:
- bcrypt, Cost 11
- Wichtig Aus Benutzernamen und Passwort sollte nicht der Einsatzort der generierten .htpasswd abgeleitet werden können (die Domain sollte nicht enthalten sein)
.htpasswd erstellen
Nun wird eine Textdatei mit dem Namen .htpasswd erstellt und die generierten Inhalte werden eingefügt. Diese Datei wird dann im Hauptverzeichnis der WordPress-Installation abgelegt.
Dabei ist zu beachten, dass Apache berechtigt sein muss, diese Datei zu lesen.
.htaccess anpassen
Jetzt wird der folgende Code ganz am Ende der .htaccess eingefügt:
Einstellungen:
- /pfad/zur/datei/ muss natürlich an den „echten” Verzeichnispfad auf dem Server angepasst werden
<Files wp-login.php> AuthType Basic AuthName "Bitte anmelden" AuthUserFile /pfad/zur/datei/.htpasswd Require valid-user </Files> <FilesMatch "(\.htaccess|\.htpasswd)"> Require all denied </FilesMatch>
Zusätzlicher Schutz gegen Brute-Force- und Wörterbuchangriffe
Schutz per JavaScript
Zusätzlich zu den o.g. Maßnahmen kann ein JavaScript-Schutz hinzugefügt werden.
Dabei lässt sich ein Login nur erfolgreich durchführen, wenn JavaScript interpretiert wird. Dies kann beispielsweise durch das Setzen eines Hakens abgefragt werden.
Dieser Schutz kann gegen automatisierte Cracker schützen, die JavaScript nicht interpretieren.
Auch hierfür kann auf fertige Plugins zurückgegriffen werden.
Limitierung der Login-Versuche (Cool Down)
Häufig werden Plugins empfohlen, die IP-Adressen zeitweise sperren, von denen fehlgeschlagene Login-Versuche ausgegangen sind.
Dies kann jedoch nicht gegen professionelle Angriffe schützen, weil diese i.d.R. von sehr vielen IP-Adressen ausgehen. Dabei werden von jeder IP-Adresse nur 1–2 Login-Versuche gestartet.
XMLRPC-Schnittstelle deaktivieren
Über die XMLRPC-Schnittstelle (xmlrpc.php) ist ebenfalls eine Anmeldung am System möglich.
Besonders kritisch ist die Möglichkeit, pro Anfrage sehr viele Passwörter gleichzeitig anfragen zu können.
Das ermöglicht relativ effiziente Brute-Force-Angriffe auf diese Schnittstelle.
Aus diesem Grund ist es empfehlenswert, die Schnittstelle komplett zu deaktivieren.
Dabei sollte die Datei xmlrpc.php serverseitig vor Zugriffen von außen geschützt werden (Codebeispiel per .htaccess für den Apache):
<Files xmlrpc.php> order deny,allow deny from all </Files>
Durch einen Eintrag in der functions.php kann zusätzlich die XMLRPC-Schnittstelle in WordPress deaktiviert und der RSD-Link aus dem HTML-Header entfernt werden:
/* XMLRPC-Schnittstelle deaktivieren */ add_filter( 'xmlrpc_enabled', '__return_false' ); /* Link aus dem HTML-Header entfernen */ remove_action('wp_head', 'rsd_link');