Sicherheitsheader für Ihre Website: was sie sind und worum Sie bitten sollten
Sechs HTTP-Header, die dem Browser sagen, wie er die Menschen auf Ihrer Website schützt. Was jeder davon tut, wie Sie Ihre prüfen, und ein fertiger Auftrag für Ihren Entwickler.
Wenn jemand Ihre Website öffnet, schickt der Server seinem Browser die Seite selbst und dazu ein paar Zeilen Anweisungen, die der Besucher nie sieht. Das sind HTTP-Header. Einige davon sagen dem Browser, wie er die Menschen auf Ihrer Website schützen soll, zum Beispiel nur über eine verschlüsselte Verbindung zu verbinden oder keine Skripte von unbekannten Adressen auszuführen.
Header kosten nichts, und Sie richten sie einmal ein. Trotzdem fehlen sie auf vielen Websites, weil die Standardeinrichtung des Servers sie oft weglässt. Hat Ihnen eine Sicherheitsprüfung gemeldet, dass Ihrer Website „Sicherheitsheader fehlen“, erklärt dieser Beitrag, was das bedeutet, und gibt Ihnen einen fertigen Text, den Sie an Ihren Entwickler schicken können.
So sehen Sie, was Ihre Website sendet
Am schnellsten geht es in Ihrem eigenen Browser. Öffnen Sie Ihre Website in Chrome, Edge oder Firefox und drücken Sie F12 (auf dem Mac Cmd+Option+I). Es öffnet sich ein Bereich mit Entwicklertools. Wählen Sie den Tab Netzwerk und laden Sie die Seite neu. Ganz oben in der Liste steht ein Eintrag mit der Adresse Ihrer Website. Klicken Sie darauf und suchen Sie den Abschnitt Antwortheader.
Den Rest des Bereichs können Sie ignorieren. Sie suchen nur nach den Namen, die unten beschrieben sind.
Der zweite Weg ist ein kostenloses Prüftool für Header, etwa unser Security Headers Check (auf Englisch) oder das HTTP Observatory, das Mozilla auf seiner Website MDN betreibt. Sie geben Ihre Adresse ein und bekommen eine Liste der Header mit einer Note. Verstehen Sie die Note als Hinweis, nicht als Urteil.
Strict-Transport-Security: immer HTTPS
Dieser Header, kurz HSTS, sagt dem Browser: Verbinde dich für einen festgelegten Zeitraum nur über HTTPS mit dieser Domain. Das schützt Besucher zum Beispiel im öffentlichen WLAN, wo jemand versuchen könnte, die erste unverschlüsselte Verbindung abzufangen.
Strict-Transport-Security: max-age=31536000; includeSubDomains
max-age ist eine Zeit in Sekunden, hier ein Jahr. Und hier liegt der Haken: Sobald der Browser sich diesen Header gemerkt hat, kann ein Besucher bei einem Zertifikatsproblem nicht mehr über die Warnung hinwegklicken. includeSubDomains erfasst jede Subdomain. Hat also shop.ihredomain.de oder ein vergessenes test.ihredomain.de kein funktionierendes HTTPS, lassen sie sich nicht mehr öffnen.
Deshalb beginnen Sie mit einem kurzen Zeitraum, etwa einem Tag, und verlängern ihn, wenn alles funktioniert. Fügen Sie preload nicht ohne gründliche Überlegung hinzu, denn das lässt sich nur sehr schwer rückgängig machen.
Content-Security-Policy: eine Liste vertrauenswürdiger Quellen
Das ist der mächtigste der Header und der einzige, der Ihre Website wirklich kaputtmachen kann. CSP ist eine Liste der Orte, von denen Ihre Seiten Skripte, Stile, Bilder und Schriften laden dürfen. Gelingt es einem Angreifer, ein schädliches Skript einzuschleusen, etwa über ein anfälliges Formular, weigert sich der Browser, Code von einer Adresse auszuführen, die nicht auf der Liste steht.
Das Problem: Eine typische Website eines kleinen Unternehmens hängt an vielen externen Diensten. Google Analytics oder der Tag Manager, das Facebook-Pixel, ein Chatfenster, eine Karte, Webfonts, YouTube-Videos, ein Zahlungsanbieter. Fehlt einer davon auf der Liste, funktioniert dieser Teil der Website nicht mehr. Der Chat verschwindet, oder Kunden können nicht bezahlen.
Deshalb sollte CSP in einem Testmodus beginnen, unter dem Namen Content-Security-Policy-Report-Only. In diesem Modus blockiert der Browser nichts und meldet nur, was er blockiert hätte. Ihr Entwickler sammelt diese Meldungen über ein bis zwei Wochen normalen Betriebs, vervollständigt die Liste und schaltet den Header erst dann in den durchsetzenden Modus. So kann das aussehen:
Content-Security-Policy-Report-Only: default-src 'self'; script-src 'self' https://www.googletagmanager.com; img-src 'self' data: https:
Das ist nur ein Beispiel. Die echte Liste hängt davon ab, was Ihre Website nutzt. Auf Websites mit vielen Plugins kann eine vollständige CSP schwer einzurichten sein. Auch dann ist eine teilweise Richtlinie besser als keine.
Vier kürzere Header
X-Content-Type-Options: nosniff sagt dem Browser, dass er dem vom Server angegebenen Dateityp vertrauen soll, statt zu raten. Ohne diesen Header könnte eine als Text oder Bild hochgeladene Datei in manchen Situationen als Skript behandelt werden. Er macht selten etwas kaputt, solange der Server die Dateitypen korrekt angibt.
X-Frame-Options: SAMEORIGIN verhindert, dass andere Websites Ihre in einem Rahmen anzeigen. Das schützt vor Clickjacking: Jemand lädt Ihre Seite unsichtbar unter seiner eigenen und bringt den Besucher dazu, auf etwas zu klicken, das er nicht sieht, etwa einen Bestellknopf. Das neuere Gegenstück ist frame-ancestors 'self' in der CSP, und Sie können beides setzen. Soll Ihre Website anderswo in einem Rahmen erscheinen, zum Beispiel ein Buchungskalender auf der Website eines Partners, muss Ihr Entwickler die Adresse dieses Partners in frame-ancestors aufnehmen.
Referrer-Policy: strict-origin-when-cross-origin bedeutet: Klickt jemand auf Ihrer Website einen Link zu einer anderen, erfährt diese nur, von welcher Domain er kam, nicht von welcher Seite. Das ist wichtig, wenn Ihre Seitenadressen etwas Privates enthalten, etwa eine Bestellnummer. Moderne Browser verhalten sich standardmäßig bereits so, den Header ausdrücklich zu setzen kostet aber nichts.
Permissions-Policy: camera=(), microphone=(), geolocation=() erklärt, dass Ihre Website weder Kamera noch Mikrofon noch Standort nutzt. Dann kann auch ein eingeschleustes Skript den Besucher nicht um Zugriff darauf bitten. Hat Ihre Website eine Filialsuche in der Nähe oder Videoberatungen, lässt Ihr Entwickler die benötigte Funktion eingeschaltet.
Ein fertiger Auftrag für Ihren Entwickler
Sie können den folgenden Text kopieren und mit Ihrer eigenen Adresse so verschicken.
Bitte richten Sie für ihredomain.de Sicherheitsheader ein,
auf jeder Seite, auch im Backend und im Shop:
Strict-Transport-Security: max-age=86400; includeSubDomains
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Content-Security-Policy-Report-Only: eine Richtlinie passend
zu den Skripten und Diensten, die wir tatsächlich nutzen
Bitte prüfen Sie vor dem Aktivieren von includeSubDomains,
dass jede Subdomain über HTTPS funktioniert. Wenn innerhalb
einer Woche nichts kaputtgeht, erhöhen Sie max-age bitte
auf 31536000.
CSP zuerst ein bis zwei Wochen im Modus Report-Only.
Schicken Sie mir dann bitte die Liste der gemeldeten
Verstöße, und wir legen gemeinsam fest, wann wir auf
den durchsetzenden Modus umstellen.
Bitte teilen Sie mir auch mit, wo die Header gesetzt wurden
(Serverkonfiguration, .htaccess, Cloudflare oder ein Plugin).
Die letzte Bitte ist wichtig. Header lassen sich an mehreren Stellen gleichzeitig setzen, und zwei verschiedene Einstellungen für denselben Header sorgen leicht für Verwirrung, wenn sich das nächste Mal etwas ändert. Sobald sie aktiv sind, prüfen Sie die Header erneut und klicken Sie sich durch die wichtigsten Teile: das Kontaktformular, den Warenkorb, die Zahlung, den Chat, die Karte und die Anmeldung im Backend.
Was Header nicht beheben
Header sind eine zweite Verteidigungslinie. Sie beheben kein veraltetes Plugin und kein schwaches Passwort. Sie begrenzen den Schaden, wenn etwas anderes versagt.
Jagen Sie auch nicht um jeden Preis der Bestnote in einem Prüftool hinterher. Eine Website mit fünf einfachen Headern und funktionierenden Zahlungen steht viel besser da als eine mit perfekter CSP, auf der Kunden keine Bestellung mehr aufgeben können.
Noch etwas: Rät Ihnen ein Tool, einen Header X-XSS-Protection hinzuzufügen, behandeln Sie das nicht als dringend. Die meisten modernen Browser ignorieren ihn, und die aktuelle Empfehlung lautet, ihn wegzulassen oder auf 0 zu setzen.