Es gibt viele Möglichkeiten eine WordPress Website sicherer zu machen. Für manches davon würdet ihr vermutlich zusätzliche Plugins verwenden. Aber es gibt auch einfache Wege zur Erhöhung der Sicherheit, bei denen ihr nur ein paar Server-Einstellungen ändern müsst. Aber bevor ich ins Detail gehe möchte ich erst einmal zeigen, wie man den aktuellen Stand der Sicherheit eurer Seite herausfinden kann.
Mozilla Observatory
Ein hervorragendes Tool zum Testen der Sicherheit einer Website ist das Mozilla Observatory Tool. Dieses Tool scannt nicht nur die Header, die der Server sendet, es analysiert auch TLS und SSH Einstellungen und verwendet einige dritte Tools für einen guten Überblick. Ein Ergebnis eines solchen Scan, bevor Anpassungen gemacht werden, könnte wie folgt aussehen:
Weiter unten auf der Seite findet ihr ein Liste mit allen Tests. Hier könnt ihr erkennen, welche erfolgreich waren und welche fehlgeschlagen sind und zu diesem schlechten Ergebnis geführt haben. In dem Beispiel von oben sah die Tabelle wie folgt aus:
Test | Pass | Score | Reason |
---|---|---|---|
Content Security Policy | Pass | Score -25 | Content Security Policy (CSP) header not implemented |
Cookies | Pass | Score 0 | No cookies detected |
Cross-origin Resource Sharing | Pass | Score 0 | Content is not visible via cross-origin resource sharing (CORS) files or headers |
HTTP Public Key Pinning | Pass | Score 0 | HTTP Public Key Pinning (HPKP) header not implemented (optional) |
HTTP Strict Transport Security | Pass | Score 0 | HTTP Strict Transport Security (HSTS) header set to a minimum of six months (15768000) |
Redirection | Pass | Score 0 | Initial redirection is to HTTPS on same host, final destination is HTTPS |
Referrer Policy | Pass | Score 0 | Referrer-Policy header not implemented (optional) |
Subresource Integrity | Pass | Score -50 | Subresource Integrity (SRI) not implemented, and external scripts are loaded over HTTP or use protocol-relative URLs via src="//..." |
X-Content-Type-Options | Pass | Score -5 | X-Content-Type-Options header not implemented |
X-Frame-Options | Pass | Score -20 | X-Frame-Options (XFO) header not implemented |
X-XSS-Protection | Pass | Score -10 | X-XSS-Protection header not implemented |
Nicht alle Dinge können für eine WordPress Website komplett gelöst werden, aber wir können einige Dinge stark verbessern.
Server-Header für bessere Sicherheit setzen
In diesem Blogbeitrag werde ich versuchen für die Website mindestes eine „B“ Bewertung zu erreichen. Um dies zu ermöglich setzen wir ein paar Server-Header für höhere Sicherheit.
Apache
Bei einem Apache-Webserver, den sehr viele Shared-Hostings einsetzen, könnt ihr diese Header in der .htaccess
Datei im Hauptverzeichnis der WordPress-Installation setzen. Fügt hierzu einfach folgende Zeilen am Anfang oder Ende der Datei ein:
<IfModule mod_headers.c>
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-XSS-Protection "1; mode=block"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'"
</IfModule>
nginx
Wenn ihr einen nginx-Webserver verwendet müsst ihr diese Header in den Konfigurationsdateien setzen. Entweder in der globalen oder in denen der einzelnen Seiten. Fügt hierzu diese Zeilen hinzu:
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src * data: 'unsafe-eval' 'unsafe-inline'" always;
Ihr müsst nicht all diese Einstellungen verstehen. Die Content-Security-Policy
ist die Einstellung, bei der man leider nicht sie sicherste Option einstellen kann, da ansonsten WordPress nicht mehr funktionieren würde.
Das neue Ergebnis
Nach dem Hinzufügen dieser Änderungen werden hoffentlich alle Tests bestanden. So sah das Ergebnis der Beispielseite aus:
Ich hatte eine „B“ Bewertung erwartet. Leider konnte ich nur ein „D“ erreichen. Der „Subresource Integrity“ Test hatte noch immer eine Wertung von „-50“, also habe ich nach dem Grund dafür gesucht. Auf der Seite habe ich ein eingebundenes Newsletter-Formular gefunden, das eine „protokoll-relative URL“ verwendet hat. Zusätzlich fügte das „Google Analytics for WordPress by MonsterInsights“ Plugin den Script-Tag für den Google Tag Manager mit einer protokoll-relativen URL ein. Glücklicherweise gab es einen Filter, über den ich an den Pfad das HTTPS Protokoll mit Hilfe eines MU-Plugins voranstellen konnte.
Das Endergebnis
Nachdem ich auch diese Änderungen umgesetzt hatte und die Seite neu scannen ließ (hierzu muss man 5 Minuten warten, bevor man einen erneuten Scan anstoßen kann), bekam ich endlich das Ergebnis, das ich mir erhofft hatte:
Es ist sogar möglich eine „B+“ Bewertung zu erhalten, allerdings nur dann, wenn keine JavaScript-Dateien von externen Domains geladen werden. Ansonsten wird der „Subresource Integrity“ Test mit der Meldung „Subresource Integrity (SRI) not implemented, but all external scripts are loaded over HTTPS“ fehlschlagen.
Fazit
Zur Verbesserung der Sicherheit einer WordPress Seite ist nicht immer ein zusätzliches Plugin notwendig. Ein paar Zeilen Code in eurer Server-Konfiguration reichen auch aus. Da dies über die .htaccess
Datei auch auf Shared-Hostings möglich ist gibt es eigentlich keinen Grund, wieso ihr es nicht auch auf eurer Seite umsetzen solltet.
Nachtrag
Torsten hatte in einem Kommentar angemerkt, dass man beim Apache-Webserver prüfen sollte, ob das Headers-Modul aktiv ist, das habe ich noch entsprechend ergänzt. In seinem Blog hat er auch einen Beitrag mit vielen weiten Tipps, wie man einen Apache-Webserver per .htaccess
weiter absichern kann.
Cooles Tool – danke für den Link! 🙂
Ich empfehle allerdings dringend diese Snippets immer in If-Konstruktionen zu kapseln:
<IfModule mod_headers.c>
und entsprechend am Ende</IfModule>
(gilt nur für Apache – keine Ahnung wie das bei nginx ist). Falls der Server das nämlich nicht erlaubt gäbe es sonst einen Internal Server Error …Die Frame-Zeile macht übrigens das Embedding kaputt. Wenn man also einen Blog hat und sich selbst einbetten möchte oder erlauben möchte, dass andere Seiten von sich einbetten können, dann sollte man die /embed-URLs damit nicht ausstatten.
Siehe dazu auch meinen Artikel aus 2016: https://torstenlandsiedel.de/2016/03/06/mehr-sicherheit-fuer-wordpress-per-htaccess/