Tastaturlayout Ausschnitt

Content Security Policy

…und weitere »Security Header«

WordPress-Logo Watermark

Bloggen mit WordPress

Es sollte sich inzwischen unter Website- und auch Blogbetreibern herumgesprochen haben, dass man sowohl dem Erreichen eines gewissen Sicherheitslevels der eigenen Website als auch der Sicherheit der Verkehrsdaten der Nutzer derselben einige Aufmerksamkeit schenken sollte.

Inhalt:

In diesem Sinne habe ich mich in den letzten Wochen, im Grunde seit Einführung von WordPress 5.9 Joséphine, verstärkt mit Fragen beschäftigt, wie man heutzutage seine Website gegen mögliche Übergriffe aus dem (bösen) WWW abhärten und sichern kann.

Header im Kopf – und auf dem Webserver

Ein zentraler Ort zur Einrichtung von Sicherheitsfunktionen auf Webseiten sind die sogenannten HTTP-Header, speziell HTTP-Security-Header, die Kopfelemente des Datenverkehrs zwischen Webbrowser und Webseite. Mittels HTTP-Headern kann eine Website z.B. dem Webbrowser des Seitenbesuchers quasi Handlungsanweisungen geben. Sie kann aber in der anderen Richtung auch bestimmte Zugriffsversuche auf ihre Inhalte abweisen oder gewähren.

Header-Anweisungen werden normalerweise auf dem ausliefernden Webserver abgelegt oder in einer zur Webseite gehörenden .htaccess-Datei (Andere Webserver als Apache, der den .htaccess-Mechanismus bietet, wie z.B. nginx, verwenden andere Konfigurationsdateien, vgl.dort). Alternativ lassen sich solche Anweisungen auch im Kopf (HTML-Header) der Webseite selbst formulieren. Das Blogsystem WordPress bietet in neueren Versionen die Möglichkeiten, HTML-Header in der Theme-spezifischen Funktionsdatei functions.php abzulegen.

Jetzt zur Sache, einleitend ein paar Links zu wesentlichen Quellen…

Grundlegend hierzu:

Security Header, im WordPress-Blog eingesetzt

WordPress selbst liefert im Installations-Grundzustand nichts mit, was Security-Header angeht. Der interessierte Blogger muss selbst Hand anlegen und entsprechende Richtlinien implementieren. Da WordPress selbst eine .htaccess-Datei im Hauptverzeichnis anlegt, bietet es sich an, diese zu nutzen, um eine Reihe von Security-Headern einzurichten. (Es sollten in dieser Datei noch weitere Maßnahmen zur Erhöhung der Sicherheit des Blogs vorgenommen werden, aber das ist heute nicht mein Thema)

Zwecks sauberer Implementation packt man die Header-Direktiven in einen Abfrageblock, den man vor den WordPress-eigenen Anweisungsblock setzt :

<IfModule mod_headers.c>
  ...
</IfModule>

#BEGIN WordPress
...
...

Richten wir einige Direktiven ein:

X-Frame-Options

Dieser Header bestimmt, ob eine Webseite in einem iframe einer anderen Seite aufgerufen werden darf. So sieht die Direktive aus:

<IfModule mod_headers.c>
  Header set X-Frame-Options "deny"
</IfModule>

#BEGIN WordPress
...
...

Neben dem Verbot »deny« stehen noch »sameorigin« und (nicht mehr empfohlen) »allow from uri« zur Verfügung.

Ich setze jeweils die unter normalen Website-Umständen empfohlene Variante in den Codeblock ein, hier also »deny«.

X-Content-Type-Options

Mit diesem Header legt man fest, dass der Webbrowser Skripte und Stylesheets nur dann lädt bzw. ausführt, wenn der Server den korrekten zugehörigen MIME-Type dafür vorgibt. Hiermit können z.B. XSS-Attacken verhindert werden, wo ein ‚feindlicher‘ Server ein Bild auszuliefern vorgibt, tatsächlich aber ein verkapptes Skript liefert. Darüberhinaus sucht der Webbrowser nicht nach ausführenden Programmen (oder Skript-Engines), die eine Datei mit unbekanntem MIME-Type ausführen könnten. Keine weiteren Optionen.

<IfModule mod_headers.c>
  Header set X-Frame-Options "deny"
  Header set X-Content-Type-Options "nosniff"
</IfModule>

#BEGIN WordPress
...
...

X-XSS-Protection

Dieser Security-Header sorgt dafür, dass ältere Webbrowser keine Seiten laden, auf denen bestimmte Formen von XSS-Attacken ausgeführt werden.

<IfModule mod_headers.c>
  Header set X-Frame-Options "deny"
  Header set X-Content-Type-Options "nosniff"
  Header set X-XSS-Protection "1; mode=block"
</IfModule>

#BEGIN WordPress
...
...

Referrer Policy

Die Referrer-Richtlinie bestimmt, ob und unter welchen Umständen die aufgerufene Webseite (Destination) Informationen über die aufrufende Webseite (Origin) erhält. Oft möchte man vielleicht gar nicht, dass die Zielseite erfährt, von wo aus man sie aufgerufen hat. Referrer Policy ist also im Grunde ein Datenschutz-Header.

<IfModule mod_headers.c>
  Header set X-Frame-Options "deny"
  Header set X-Content-Type-Options "nosniff"
  Header set X-XSS-Protection "1; mode=block"
  Header set Referrer-Policy "no-referrer" 
</IfModule>

#BEGIN WordPress
...
...

Mögliche Werte neben dem Verbergen des Referres sind »same-origin«, was Sinn macht, wenn innerhalb einer Domain Seitenaufrufe nachverfolgbar sein sollen. »strict-origin« bestimmt, dass lediglich der Domain-URI gesendet wird, nicht jedoch tieferliegende Pfade. »strict-origin-when-cross-origin« verbindet beide vorgenannten Direktiven: innerhalb derselben Domain wird der vollständige Referrer gesendet, zu Fremdseiten nur der Domain-URI.

HSTS: HTTP Strict Transport Security

Jetzt wird es etwas komplizierter. Es sollte sich langsam herumgesprochen haben, dass Webseiten nicht mehr unverschlüsselt und damit offen und unsicher über das einfache HTTP-Protokoll ausgeliefert werden sollten. Heute verwendet man Domain-spezifisch ausgestellte TLS/SSL-Zertifikate auf Webservern und liefert Seiten über das Transport-verschlüsselte HTTPS-Protokoll aus.

Damit dieser gesicherte Transport verbindlich erfolgt und auch die bei fehlerhaften bzw. fehlenden Zertifikaten ausgelieferte Fehlerseite im Webbrowser nicht umgangen werden kann, kann man diesen Security-Header setzen.

Der Parameter »max-age« ist obligatorisch, die Mindest-Laufzeit der Direktive beträgt 6 Monate, anzugeben in Sekunden (15768000). Empfohlen werden wohl 2 Jahre = 63072000 Sekunden.

<IfModule mod_headers.c>
  Header set X-Frame-Options "deny"
  Header set X-Content-Type-Options "nosniff"
  Header set X-XSS-Protection "1; mode=block"
  Header set Referrer-Policy "no-referrer"
  Header set Strict-Transport-Security: "max-age=63072000 
</IfModule>

#BEGIN WordPress
...
...

Darüberhinaus kann man eventuell vorhandene Subdomains einschließen:

Header set Strict-Transport-Security: "max-age=63072000; includeSubDomains; preload

»preload« bedeutet, dass die Webseite in die HSTS Preload List aufgenommen werden kann, wenn man sie dort anmeldet. Das führt zu…

As a result, web browsers will do HTTPS upgrades to the site without ever having to receive the initial HSTS header. This prevents downgrade attacks upon first use and is recommended for all high risk websites.

https://infosec.mozilla.org/guidelines/web_security.html#directives

»preload« muss zusammen mit »includeSubDomains« verwendet werden. Nun aber erst einmal eine…

Kurze Pause und eine grundlegende Anmerkung

Alle vorgenannten Sicherheitsrichtlinien habe ich inzwischen in meinem Blog bzw. auf meiner Domain im Einsatz, meine .htaccess ist entsprechend eingerichtet. Für jede Richtline habe ich zuvor ermittelt und überlegt, ob und mit welchen Parametern ich sie einsetzen kann.

Ich empfehle dringend, Direktive für Direktive schrittweise vorzugehen. Ist eine Direktive umständeweise nicht anwendbar oder macht man beim Formulieren in der .htaccess einen Syntaxfehler, wird die Website/das Blog (resp. der Webserver) sofort mit einem 500er-Fehler quittieren: Die Seite ist nicht mehr aufrufbar. Dann ist Ursachen- oder Fehlersuche angesagt.

Hat man alle Direktiven eingebaut und alles läuft ohne Fehlermeldungen (bei WordPress auch immer den Adminbereich testen!), dann kann man sich einmal zurücklehnen und freuen.

Noch einmal durchatmen… denn jetzt folgt der größte – und schwierigste – Brocken, nämlich die Herstellung einer funktionierenden Content Security Policy.

Seiten: 1 2