HSTS zwingt Browser, Ihre Website nur noch über HTTPS aufzurufen, und schließt damit die Lücke, die eine reine Weiterleitung offen lässt. Falsch eingeführt sperrt der Header aber genau die Besucher aus, die er schützen soll. Diese Anleitung zeigt den Stufenplan mit konkreten Werten für Apache und nginx.
Unser Plugin Security Check Report prüft nicht nur, ob der HSTS-Header existiert, sondern auch, ob seine max-age lang genug ist und ob er Subdomains abdeckt. Der Grund für diese Unterscheidung: Ein Header mit max-age von wenigen Minuten besteht jeden Existenz-Check und schützt trotzdem niemanden. Wie Sie von null auf einen wirksamen Wert kommen, ohne sich selbst auszusperren, steht auf dieser Seite.
Welches Problem HSTS löst: SSL-Stripping
Die meisten Websites leiten HTTP-Aufrufe per 301 auf HTTPS um. Das klingt sicher, hat aber eine Schwachstelle: Der allererste Request geht unverschlüsselt raus. Wer im Browser nur ihre-domain.de eintippt, startet mit http://, und erst die Antwort des Servers schickt ihn auf https://.
Genau dieses Fenster nutzt ein Angreifer im selben Netzwerk, etwa im offenen WLAN eines Cafés oder Hotels. Er klemmt sich zwischen Besucher und Server und fängt den unverschlüsselten Request ab. Statt die 301-Weiterleitung durchzureichen, hält er die Verbindung zum Besucher auf HTTP und spricht nur selbst per HTTPS mit dem Server. Der Besucher sieht die richtige Website, aber alles, was er eingibt, läuft im Klartext über den Angreifer: Login-Daten, Session-Cookies, Formularinhalte. Das Verfahren heißt SSL-Stripping und funktioniert, ohne dass ein Zertifikat gefälscht werden muss.
HSTS (HTTP Strict Transport Security, definiert in RFC 6797) schließt dieses Fenster. Der Server schickt mit jeder HTTPS-Antwort den Header Strict-Transport-Security. Ab da merkt sich der Browser für die angegebene Dauer: Diese Domain wird ausschließlich per HTTPS aufgerufen. Jeder spätere http://-Aufruf wird intern auf https:// umgeschrieben, bevor überhaupt ein Request das Gerät verlässt. Dem Angreifer fehlt damit der unverschlüsselte erste Request, an dem er ansetzen könnte. Nur der allererste Besuch überhaupt bleibt ungeschützt, dafür gibt es die Preload-Liste, dazu weiter unten.
Warum schrittweise: der Header ist ein Versprechen mit Laufzeit
Der Header hat drei Bestandteile:
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
- max-age: wie viele Sekunden sich der Browser die HTTPS-Pflicht merkt. 31536000 Sekunden sind ein Jahr.
- includeSubDomains: die Regel gilt zusätzlich für alle Subdomains, auch für solche, an die Sie gerade nicht denken.
- preload: signalisiert, dass die Domain in die fest in Browser eingebaute Preload-Liste aufgenommen werden darf.
Das Risiko steckt in der Laufzeit. Ein Browser, der den Header einmal gesehen hat, weigert sich für die gesamte max-age, die Site per HTTP zu laden. Läuft Ihr Zertifikat ab, bricht die HTTPS-Konfiguration nach einem Serverumzug, oder liefert eine Subdomain (bei includeSubDomains) kein HTTPS: Betroffene Besucher sehen eine Fehlerseite, die sie nicht wegklicken können. Bei HSTS-Fehlern bieten Browser bewusst keinen „Trotzdem fortfahren“-Link an. Sie können den Header dann zwar sofort vom Server nehmen, aber das erreicht nur Browser, die noch eine Antwort bekommen. Alle anderen bleiben ausgesperrt, bis ihre gespeicherte max-age abgelaufen ist.
Deshalb die Regel: mit kurzer Laufzeit beginnen, prüfen, dann erhöhen. Genau dieses stufenweise Vorgehen empfiehlt auch hstspreload.org, die offizielle Anlaufstelle für die Preload-Liste.
Der Stufenplan
Voraussetzungen, bevor Sie anfangen: Die gesamte Site ist über HTTPS erreichbar, mit gültigem Zertifikat und automatischer Verlängerung. HTTP leitet per 301 auf HTTPS um, auf denselben Hostnamen. Es gibt keine Inhalte mehr, die nur per HTTP funktionieren. Erst wenn das alles steht, ergibt HSTS Sinn.
- Stufe 1, max-age=300 (5 Minuten): Header setzen, Site im Alltag benutzen, Browserkonsole und Server-Logs auf Fehler prüfen. Geht etwas schief, sind Besucher nach 5 Minuten wieder frei. Mindestens einige Tage laufen lassen.
- Stufe 2, max-age=86400 (1 Tag): Wenn Stufe 1 unauffällig war, erhöhen. Jetzt zeigt sich, ob auch seltener besuchte Bereiche und externe Einbindungen sauber über HTTPS laufen. Eine bis zwei Wochen beobachten.
- Stufe 3, max-age=31536000 (1 Jahr): Der Zielwert. Kürzere Werte bestehen zwar einen Existenz-Check, aber der Header erfüllt seinen Zweck erst, wenn Browser ihn sich über Monate merken.
- includeSubDomains, erst nach Inventur: Diese Direktive erfasst jede Subdomain, auch interne wie intranet.ihre-domain.de oder vergessene wie alt.ihre-domain.de. Erstellen Sie vorher eine vollständige Liste aller Subdomains (DNS-Zone durchsehen, nicht raten) und prüfen Sie jede einzelne auf HTTPS. Eine Subdomain ohne HTTPS wird mit dieser Direktive unerreichbar. Danach die Direktive ergänzen und wieder bei einer kurzen max-age beginnen, denn die Zusage gilt jetzt für einen größeren Bereich.
- preload, nur mit Bedacht: Die Aufnahme in die Preload-Liste schützt auch den allerersten Besuch, verlangt aber max-age=31536000, includeSubDomains und die preload-Direktive dauerhaft. Wichtigster Punkt: Die Austragung aus der Liste dauert Monate, weil die Änderung erst mit Browser-Updates bei den Nutzern ankommt, und für andere Browser als Chrome gibt es dafür keine Garantie. hstspreload.org selbst stuft Preloading inzwischen als nicht mehr generell empfohlen ein, weil moderne Browser HTTP-Aufrufe zunehmend von sich aus auf HTTPS anheben. Setzen Sie preload nur, wenn Sie sicher sind, dass die gesamte Domain samt aller Subdomains langfristig bei HTTPS bleibt.
Apache: Header-Direktive im VirtualHost
Der Header gehört in den HTTPS-VirtualHost Ihrer Site (oder in die .htaccess, wenn Sie keinen Zugriff auf die Server-Konfiguration haben). Das Modul mod_headers muss aktiv sein:
# Stufe 1: kurze Laufzeit zum Testen
Header always set Strict-Transport-Security "max-age=300"
Nach den Teststufen der Zielwert:
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Das Schlüsselwort always sorgt dafür, dass der Header auch bei Fehlerseiten und Weiterleitungen gesetzt wird. Wichtig: Der Header darf nur in der HTTPS-Konfiguration stehen. Über HTTP gesendet ist er wirkungslos, Browser ignorieren ihn dort laut RFC 6797. Danach Konfiguration testen und neu laden:
apachectl configtest
systemctl reload apache2
nginx: add_header im HTTPS-server-Block
In den server-Block, der auf Port 443 lauscht (je nach Distribution unter /etc/nginx/sites-available/ oder /etc/nginx/conf.d/):
# Stufe 1: kurze Laufzeit zum Testen
add_header Strict-Transport-Security "max-age=300" always;
Nach den Teststufen:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Der Parameter always stellt sicher, dass der Header auch bei Antworten mit Fehlerstatus gesendet wird. Eine nginx-Eigenheit sollten Sie kennen: Sobald ein location-Block eigene add_header-Zeilen enthält, erbt er die add_header-Zeilen aus dem server-Block nicht mehr. Prüfen Sie deshalb mit dem curl-Test unten nicht nur die Startseite, sondern auch Unterseiten und statische Dateien. Danach wie üblich:
nginx -t
systemctl reload nginx
Auf Managed Hosting ohne Zugriff auf die Server-Konfiguration setzen viele Hoster den Header über das Kundenpanel oder auf Anfrage. Fragen Sie konkret nach dem Strict-Transport-Security-Header und nennen Sie den gewünschten max-age-Wert.
So testen Sie das Ergebnis
Ein einzelner curl-Aufruf zeigt, ob der Header ankommt:
curl -sI https://ihre-domain.de/ | grep -i strict
Erwartete Ausgabe, je nach Stufe:
strict-transport-security: max-age=31536000; includeSubDomains
Prüfen Sie zusätzlich drei Dinge:
- Die HTTP-Variante leitet per 301 um:
curl -sI http://ihre-domain.de/muss Status 301 und eine Location mit https:// zeigen. - Der Header erscheint auch auf Unterseiten und bei statischen Dateien, nicht nur auf der Startseite (siehe die nginx-Vererbungsfalle oben).
- Der Header wird nicht doppelt gesendet, etwa einmal vom Server und einmal von einem Security-Plugin. Zwei Header mit unterschiedlichen Werten sind ein Konfigurationsfehler.
Ob die Laufzeit lang genug ist und Subdomains abgedeckt sind, prüft auch unser kostenloses Plugin Security Check Report bei jedem Lauf mit, als eine von 60 Prüfungen im Bereich Netzwerk und Transport. Wie Sie neben HSTS auch die übrigen Security-Header konfigurieren, zeigt die Anleitung Security-Header in Apache und nginx setzen. Der Quelltext ist öffentlich auf GitHub einsehbar.
Häufige Fragen
Ich habe eine lange max-age gesetzt und HTTPS ist kaputt. Was jetzt?
Zuerst HTTPS reparieren, das ist der einzige Weg, der alle Besucher wieder hereinlässt. Den Header zu entfernen hilft nur Browsern, die den Server noch erreichen; alle anderen halten sich an die gespeicherte Laufzeit. Für den eigenen Rechner lässt sich der Eintrag löschen (in Chrome über chrome://net-internals/#hsts), für Ihre Besucher nicht. Genau deshalb beginnt der Stufenplan mit 5 Minuten.
Reicht die 301-Weiterleitung von HTTP auf HTTPS nicht aus?
Nein. Die Weiterleitung setzt erst an, nachdem der erste Request unverschlüsselt beim Server war, und genau diesen Request kann ein Angreifer im selben Netzwerk abfangen und die Verbindung auf HTTP festhalten. HSTS verlagert die Entscheidung in den Browser: Der Request verlässt das Gerät gar nicht erst unverschlüsselt. Die Weiterleitung bleibt trotzdem nötig, als Einstieg für Browser, die den Header noch nie gesehen haben.
Kann ich HSTS einfach in WordPress per Plugin setzen?
Technisch ja, viele Security-Plugins können den Header senden. Der Server ist trotzdem der bessere Ort: Er setzt den Header auch auf statische Dateien und auf Antworten, die WordPress nie erreichen, etwa direkt ausgelieferte Bilder oder Fehlerseiten des Webservers. Wenn Sie beide Wege kombinieren, achten Sie darauf, dass der Header nicht doppelt gesendet wird.
Muss meine Domain auf die Preload-Liste?
Für die meisten Sites: nein. Die Liste schützt nur den allerersten Besuch, den der normale Header noch nicht abdeckt, und moderne Browser heben HTTP-Aufrufe zunehmend ohnehin auf HTTPS an. Dem steht eine Verpflichtung gegenüber, die sich nur über Monate rückgängig machen lässt. Wer preload setzt, sollte die Anforderungen auf hstspreload.org gelesen haben und sicher sein, dass jede Subdomain dauerhaft HTTPS spricht.
Gilt der Header auch für Besucher, die schon einmal da waren, als er noch kürzer war?
Ja. Der Browser ersetzt den gespeicherten Wert bei jedem Besuch durch den aktuellen. Wer heute mit max-age=300 kommt und nächste Woche max-age=86400 sieht, übernimmt den neuen Wert. Deshalb funktioniert der Stufenplan: Jede Erhöhung verteilt sich mit den normalen Besuchen von selbst.
Weitere Härtungsmaßnahmen rund um WordPress finden Sie in unserer Übersicht WordPress-Sicherheit. Und wenn Sie wissen wollen, wo Ihre Site heute steht: Security Check Report installieren, einen Lauf starten, und die Prioritätenliste sagt Ihnen, was zuerst dran ist. Kostenlos, ohne Pro-Version, ohne Telemetrie.