Sicherheit über HSTS hinaus
In unserem vorangegangenen Beitrag haben wir das Fundament Ihrer Web-Sicherheit mit HSTS gelegt. Doch ein sicheres Haus braucht mehr als nur ein Fundament. Um Ihre Website gegen Cross-Site-Scripting (XSS), Clickjacking und Datenlecks abzusichern, gibt es eine Reihe weiterer HTTP-Header, die Sie direkt in der .htaccess hinzufügen können.
Im Folgenden gehen wir die wichtigsten Header durch, erklären ihre Funktion und – was oft vergessen wird – worauf Sie achten müssen, damit Ihre Seite nicht "kaputtgeht".
1. Cookies härten: HttpOnly, Secure & SameSite
Header always edit Set-Cookie (.*) "$1; HttpOnly; Secure; SameSite=Lax"Was das macht:
Dieser Befehl ist besonders clever. Er setzt keinen neuen Header, sondern bearbeitet (edit) alle Cookies, die Ihre Anwendung (z.B. WordPress, PHP) bereits setzen will. Er hängt drei wichtige Flags an:
- HttpOnly: Verhindert, dass JavaScript (und damit böswillige Skripte) auf das Cookie zugreifen können. Das ist der wichtigste Schutz gegen Session-Diebstahl via XSS.
- Secure: Zwingt den Browser, das Cookie nur über verschlüsselte HTTPS-Verbindungen zu senden.
- SameSite=Lax: Schützt gegen CSRF-Angriffe (Cross-Site Request Forgery), indem Cookies bei Cross-Origin-Requests nur unter bestimmten Bedingungen mitgesendet werden.
Laxist der empfohlene Kompromiss:Strictist maximaler Schutz, bricht aber Login-Flows über externe Links (z.B. aus E-Mails).Noneerfordert zwingend dasSecure-Flag und sollte nur für bewusste Cross-Origin-Szenarien genutzt werden.
2. Anti-Clickjacking: X-Frame-Options
Header always set X-Frame-Options "SAMEORIGIN"Was das macht:
Clickjacking ist eine Angriffstechnik, bei der Ihre Website unsichtbar in einem <iframe> auf einer Hacker-Seite geladen wird. Der Nutzer denkt, er klickt auf ein Katzenvideo, klickt aber eigentlich auf einen unsichtbaren "Kaufen"-Button auf Ihrer Seite.
Der Wert SAMEORIGIN erlaubt das Einbinden in Frames nur, wenn die einbindende Seite dieselbe Domain hat wie Ihre Seite.
Exkurs: Wirkt sich "SAMEORIGIN" auf Subdomains aus?
Dies ist eine der häufigsten Fragen und Stolperfallen. Die Antwort lautet: Ja, es blockiert Subdomains.
Für den Browser sind beispiel.de und shop.beispiel.de zwei völlig verschiedene "Origins". Wenn Sie auf der Hauptseite SAMEORIGIN setzen, kann diese nicht in einem iFrame auf der Shop-Subdomain angezeigt werden.
Die Lösung: Hier kommt die unten beschriebene Content-Security-Policy (CSP) ins Spiel, die ein explizites Whitelisting erlaubt.
3. Datenschutz & SEO: Referrer-Policy
Hier gibt es verschiedene Strategien, je nachdem, wie viel Datenschutz Sie wünschen:
Header setifempty Referrer-Policy "same-origin"
# ODER
Header set Referrer-Policy "no-referrer"Was das macht:
Dieser Header steuert, welche Informationen Browser weitergeben, wenn ein Nutzer auf einen Link klickt, der von Ihrer Seite wegführt.
- same-origin: Sendet Referrer-Daten nur intern. Bei Links zu externen Seiten (z.B. Google) wird nichts gesendet.
- no-referrer: Es werden niemals Referrer-Daten gesendet (Maximaler Datenschutz).
- strict-origin-when-cross-origin (Standard-Empfehlung): Sendet die volle URL intern, aber nur die Domain an externe sichere Seiten. Das ist der beste Kompromiss für SEO und Analytics.
4. Der veraltete "Bodyguard": X-XSS-Protection
Header set X-XSS-Protection "0"Was das macht:
Dieser Header war ursprünglich dazu gedacht, den eingebauten XSS-Filter älterer Browser zu aktivieren. Er ist heute obsolet und sollte auf 0 gesetzt oder ganz weggelassen werden.
- Chrome hat den Header seit Version 78 (2019) vollständig entfernt.
- Firefox hat ihn nie implementiert.
- In älteren Safari- und Edge-Versionen konnte der
mode=block-Modus neue Angriffsvektoren öffnen, da der Filter legitime Inhalte blockierte und dabei Seitenstruktur preisgab. - Das OWASP empfiehlt ausdrücklich, den Header zu deaktivieren (
0) oder wegzulassen.
Der einzig wirksame XSS-Schutz ist eine gut konfigurierte Content-Security-Policy (CSP) – siehe unten.
5. Flash & PDF Sicherheit: X-Permitted-Cross-Domain-Policies
Header set X-Permitted-Cross-Domain-Policies "none"Was das macht:
Riegelt das Tor für Adobe Flash und PDF-Reader ab. Es verhindert, dass externe Flash-Anwendungen Daten von Ihrer Domain laden dürfen.
6. MIME-Sniffing verhindern: X-Content-Type-Options
Header set X-Content-Type-Options "nosniff"Was das macht:
Zwingt den Browser, sich strikt an den Dateityp zu halten, den der Server meldet. Verhindert, dass eine vermeintliche Text-Datei plötzlich als ausführbares JavaScript interpretiert wird.
Der Endgegner: Content-Security-Policy (CSP)
Wenn X-Frame-Options die Tür abschließt, ist die Content-Security-Policy (CSP) das gesamte Sicherheitssystem des Hauses inklusive Bewegungsmeldern. Sie ist der mächtigste HTTP-Header, aber auch derjenige, der am meisten Konfigurationsaufwand erfordert.
Das Prinzip:
Standardmäßig lädt ein Browser alles, was auf Ihrer Seite steht. CSP ändert das Prinzip zu "Verbiete alles, außer..." (Whitelist). Sie definieren exakt, von welchen Quellen Bilder, Skripte oder Stylesheets geladen werden dürfen.
Die wichtigsten Parameter (Direktiven)
default-src: Die Fallback-Regel. Gilt für alles, was nicht spezifisch definiert wurde.script-src: Steuert, woher JavaScript geladen werden darf (z.B. Google Analytics, Ihr eigener Server).style-src: Steuert CSS-Dateien und Inline-Styles.img-src: Steuert Bildquellen.frame-ancestors: Steuert, wer Ihre Seite einbinden darf (der moderne Ersatz für X-Frame-Options).
Whitelisting: So geben Sie mehrere Domains frei
Die Syntax von CSP ist strikt. Ein häufiger Fehler ist die Verwendung von Kommas. In CSP werden Quellen durch Leerzeichen getrennt.
Beispiel: Komplexes Whitelisting
# 'self' = Eigene Domain
# https: = Erlaubt ALLES über HTTPS (Vorsicht!)
# data: = Erlaubt Base64-Bilder
Header set Content-Security-Policy "default-src 'self'; img-src 'self' https: data:; script-src 'self' https://apis.google.com;"Wichtig: unsafe-inline und unsafe-eval vermeiden
⚠️ Achtung: Die Schlüsselwörter 'unsafe-inline' und 'unsafe-eval' in script-src heben den XSS-Schutz der CSP praktisch vollständig auf, da sie beliebige Inline-Skripte bzw. eval()-Aufrufe erlauben – genau das Angriffsziel von XSS.
Kurzfristige Übergangslösung: Verwenden Sie 'unsafe-inline' nur vorübergehend, um bestehende Seiten nicht sofort zu brechen.
Langfristige Lösung: Ersetzen Sie Inline-Skripte durch externe Dateien und nutzen Sie Nonces oder Hashes:
# Nonce-basierter Ansatz (serverseitig pro Request neu generieren):
script-src 'self' 'nonce-ZUFALLSWERT_PRO_REQUEST'Praxis-Beispiel: CSP für Analytics & Co.
Viele Websites nutzen externe Tools wie Google Analytics oder Microsoft Clarity. Eine Standard-CSP würde diese Skripte sofort blockieren.
Im finalen Code-Block unten finden Sie dafür eine vorbereitete "Praxis-Konfiguration", die all diese Ressourcen sauber freigibt.
Feature-Management: Permissions-Policy im Detail
Dieser Header (der Nachfolger der Feature-Policy) erlaubt Ihnen eine granulare Kontrolle darüber, welche Browser-Funktionen Ihre Webseite nutzen darf. Das ist Datenschutz auf Hardware-Ebene.
Die Syntax verstehen: () vs (self)
Die Werte werden in Klammern gesetzt. Hier passieren die meisten Fehler:
feature=()
Deaktiviert das Feature komplett. Weder Ihre Seite noch eingebettete iFrames dürfen es nutzen.feature=(self)
Lokal erlaubt. Ihre eigene Domain (Origin) darf das Feature nutzen, aber externe iFrames dürfen es nicht.feature=(self "https://partner.de")
Whitelist. Ihre Domain und die explizit genannte Partner-Domain dürfen das Feature nutzen.
Die wichtigsten Parameter erklärt
- geolocation: Steuert GPS. Nutzen Sie
(self)für Filialfinder, oder()wenn Sie keinen Standort brauchen. - camera & microphone: Sollte standardmäßig auf
()stehen, um Webcam-Hacks zu verhindern. - payment: Steuert Apple Pay / Google Pay APIs. Für Shops
(self), für Blogs(). - autoplay:
(self)erlaubt eigene Videos, blockiert aber nervige Autoplay-Werbung in Frames. - fullscreen:
(self)erlaubt den Vollbildmodus nur für Ihre eigene Domain. Der Wert*würde ihn auch für alle eingebetteten Drittanbieter-iFrames freigeben und sollte vermieden werden.
Wichtig: Wann Sie diese Parameter NICHT setzen dürfen
Sicherheit ist immer eine Abwägung. Wenn Sie die Header blind kopieren, können Funktionen Ihrer Website ausfallen. Hier ist Ihre Checkliste:
1. Vorsicht bei X-Frame-Options: SAMEORIGIN
Das Problem: iFrames auf anderen Domains werden blockiert.
NICHT setzen, wenn:
- Sie Widgets oder Tools bereitstellen, die Kunden auf deren Websites einbinden sollen.
- Sie Inhalte über mehrere Domains hinweg (Cross-Domain) in Frames laden.
Lösung: Nutzen Sie die CSP Direktive frame-ancestors ....
2. Vorsicht bei Header edit Set-Cookie ... HttpOnly
Das Problem: JavaScript kann Cookies nicht mehr lesen.
NICHT setzen, wenn:
- Ihre Seite eine "Single Page App" (React/Vue) ist, die Auth-Token clientseitig liest.
- Tracking-Skripte zwingend Zugriff auf Session-Cookies brauchen.
Symptom: Login funktioniert nicht, Warenkorb leert sich.
3. Vorsicht bei Referrer-Policy: no-referrer
Das Problem: Herkunftsdaten werden komplett unterdrückt.
NICHT setzen, wenn:
- Sie Affiliate-Marketing nutzen (Provisionen gehen verloren).
- Partner ihre Traffic-Quellen analysieren müssen.
Lösung: Nutzen Sie strict-origin-when-cross-origin.
4. Vorsicht bei X-Content-Type-Options: nosniff
Das Problem: Browser verweigert Dateien mit falschem MIME-Type.
NICHT setzen, wenn:
- Ihr Server falsch konfiguriert ist (z.B. CSS als
text/plainsendet).
Symptom: Seite sieht unformatiert ("nackt") aus.
5. Vorsicht bei Strict-Transport-Security mit includeSubDomains und preload
Das Problem mit includeSubDomains: Dieser Zusatz erzwingt HTTPS auf allen Subdomains. Wer auch nur eine Subdomain ohne gültiges SSL-Zertifikat betreibt, sperrt sich damit für Besucher aus.
Das Problem mit preload: Wer dieses Flag setzt und seine Domain zur Browser-internen HSTS-Preload-Liste anmeldet (hstspreload.org), trifft eine praktisch irreversible Entscheidung. Eine Entfernung aus der Liste kann Monate bis Jahre dauern und wird nicht von allen Browsern zeitnah übernommen. Alle Subdomains müssen dauerhaft HTTPS unterstützen.
Empfehlung: Starten Sie zum Testen mit einem kurzen max-age (z.B. 604800 = 1 Woche) ohne preload. Fügen Sie preload erst hinzu, wenn Sie sich absolut sicher sind.
Das Finale: Die komplette .htaccess Vorlage
Hier ist der ultimative Code-Block. Er kombiniert HSTS, CSP, Permissions-Policy und die klassischen Header.
Wählen Sie bei der CSP (Punkt 3) die Variante, die zu Ihnen passt:
Die Standard-Variante ist sicherer für einfache Seiten. Die Praxis-Variante ist optimiert für Analytics, Ahrefs und Clarity.
Voraussetzungen: Die folgenden Apache-Module müssen aktiv sein: mod_headers, mod_rewrite und mod_ssl. Auf Shared Hosting ist das meist der Fall, lässt sich aber im Hosting-Panel prüfen.
# ----------------------------------------------------------------------
# | SICHERHEITSKONFIGURATION (SSL, HSTS, SECURITY HEADERS) |
# ----------------------------------------------------------------------
<IfModule mod_rewrite.c>
RewriteEngine On
# 1. SSL erzwingen (HTTP zu HTTPS)
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>
<IfModule mod_headers.c>
# 2. HSTS (HTTP Strict Transport Security)
# WARNUNG: 'includeSubDomains' erzwingt HTTPS auf ALLEN Subdomains.
# WARNUNG: 'preload' ist praktisch irreversibel (Entfernung dauert Monate bis Jahre).
# Starten Sie zum Testen mit 1 Woche (604800) ohne 'preload'!
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" "expr=%{HTTPS} == 'on'"
# 3. Content-Security-Policy (CSP)
# VARIANTE A: Der moderne Standard (AKTIV)
# Hinweis: 'unsafe-inline' und 'unsafe-eval' sind eine Übergangslösung.
# Sie schwächen den XSS-Schutz erheblich. Langfristig sollten Inline-Skripte
# durch externe Dateien und Nonce-basierte CSP ersetzt werden.
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: https:; font-src 'self' data: https:; frame-ancestors 'self';"
# VARIANTE B: Praxis-Konfiguration (Analytics, Ahrefs, Clarity)
# Entfernen Sie zum Aktivieren das '#' am Anfang der Zeile und setzen Sie ein '#' vor Variante A.
# Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.googletagmanager.com https://www.clarity.ms https://analytics.ahrefs.com; connect-src 'self' https://www.google-analytics.com https://*.clarity.ms https://c.bing.com https://analytics.ahrefs.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://www.google-analytics.com https://*.clarity.ms https://c.bing.com; font-src 'self' data:; frame-src 'self'; child-src 'self'; frame-ancestors 'self';"
# 4. Permissions-Policy (Feature Control)
# Deaktiviert sensible Hardware-APIs. 'fullscreen=(self)' erlaubt Vollbild
# nur für die eigene Domain – nicht für eingebettete Drittanbieter-iFrames.
Header always set Permissions-Policy "geolocation=(self), camera=(), microphone=(), payment=(self), usb=(), bluetooth=(), fullscreen=(self)"
# 5. Weitere Sicherheits-Header (Fallbacks)
# -- Clickjacking Schutz --
Header always set X-Frame-Options "SAMEORIGIN"
# -- MIME-Sniffing verhindern --
Header always set X-Content-Type-Options "nosniff"
# -- XSS-Protection: Deaktiviert (veraltet, kann in älteren Browsern neue
# Angriffsvektoren öffnen; echter XSS-Schutz erfolgt über die CSP oben) --
Header always set X-XSS-Protection "0"
# -- Referrer Policy --
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# -- Flash/PDF Policy --
Header always set X-Permitted-Cross-Domain-Policies "none"
# 6. Cookies absichern (HttpOnly, Secure, SameSite=Lax)
# SameSite=Lax schützt gegen CSRF. 'Strict' ist sicherer, bricht aber
# Login-Links aus E-Mails. 'None' nur für bewusste Cross-Origin-Szenarien.
Header always edit Set-Cookie (.*) "$1; HttpOnly; Secure; SameSite=Lax"
</IfModule>
# ----------------------------------------------------------------------
# | ENDE SICHERHEIT |
# ----------------------------------------------------------------------Profi-Tipp: Wenn Sie unsicher sind, ändern Sie im Code oben Content-Security-Policy zu Content-Security-Policy-Report-Only. Dann blockiert der Browser nichts, sondern meldet Fehler nur in der Konsole (F12).
Nächste Schritte: Nachdem Sie diesen Code eingefügt haben, leeren Sie Ihren Browser-Cache und testen Sie Ihre Seite ausführlich. Nutzen Sie Tools wie securityheaders.com , um zu prüfen, ob alle Lichter auf "Grün" stehen.
