# Security Header für Websites: Sicherheits-Header richtig setzen

> Security Header für Websites einrichten: CSP, HSTS, X-Content-Type-Options und mehr mit Beispielen für Nginx und Apache, plus Prüfung und typische Fehler.

Quelle: https://phpsos.de/ratgeber/sicherheits-header/  
Stand: 25.10.2026  
Anbieter: PHP SOS, PHP-Notfallhilfe und Server-Sicherheit. Soforthilfe per WhatsApp: https://wa.me/491736494914?text=Hallo%20PHP%20SOS%2C%20wir%20brauchen%20Hilfe%20mit%20unserem%20PHP-Server.%20Firma%3A%20%E2%80%A6%20Website%3A%20%E2%80%A6

**Kurz gesagt:** Security Header sind Anweisungen des Webservers an den Browser, die Besucher vor Angriffen wie Cross-Site-Scripting, Clickjacking und unverschlüsselten Verbindungen schützen. Die wichtigsten sind HSTS, Content-Security-Policy, X-Content-Type-Options, Schutz gegen fremde Rahmen, Referrer-Policy und Permissions-Policy. Sie sind eine sinnvolle Härtung, ersetzen aber keine Updates auf dem Server.

## Was Security Header leisten und was nicht

Bei jedem Seitenaufruf sendet der Webserver neben dem Inhalt auch Header mit. Einige davon steuern Sicherheitsfunktionen des Browsers. Damit lässt sich zum Beispiel festlegen, dass eine Seite nur über HTTPS geladen wird oder dass der Browser keine Skripte von fremden Domains ausführt.

Für Betreiber ist die Einordnung wichtig: Header schützen in erster Linie die Besucher, etwa vor dem Abgreifen von Sitzungen oder vor manipulierten Formularen. Sie schließen keine Lücken auf dem Server. Eine Schwachstelle in PHP, im CMS oder in einer Erweiterung bleibt bestehen, egal wie gut die Header gesetzt sind. Im Zusammenspiel mit sauberem Code begrenzen sie aber die Folgen vieler Fehler deutlich.

## Die wichtigsten Security Header im Überblick

| Header | Zweck | Empfehlung als Ausgangspunkt |
|---|---|---|
| Strict-Transport-Security (HSTS) | erzwingt HTTPS für künftige Aufrufe | `max-age=31536000; includeSubDomains` |
| Content-Security-Policy (CSP) | legt erlaubte Quellen für Skripte, Bilder, Rahmen fest | individuell, zuerst als Report-Only |
| X-Content-Type-Options | verhindert, dass der Browser Dateitypen errät | `nosniff` |
| X-Frame-Options bzw. CSP frame-ancestors | verhindert Einbettung in fremde Seiten (Clickjacking) | `SAMEORIGIN` bzw. `frame-ancestors 'self'` |
| Referrer-Policy | begrenzt, welche Adresse an andere Seiten übermittelt wird | `strict-origin-when-cross-origin` |
| Permissions-Policy | schaltet Browserfunktionen wie Kamera oder Standort ab | nur benötigte Funktionen erlauben |

HSTS sollten Sie erst setzen, wenn alle Subdomains zuverlässig über HTTPS erreichbar sind. Der Browser merkt sich die Anweisung für die angegebene Zeit; ein Fehler lässt sich dann nicht sofort zurücknehmen. Beginnen Sie gegebenenfalls mit einer kurzen Laufzeit und erhöhen Sie sie nach erfolgreichen Tests. Die zusätzliche Option `preload` trägt die Domain dauerhaft in Listen der Browserhersteller ein und sollte nur nach sorgfältiger Prüfung gesetzt werden.

Header sind außerdem nicht die einzige Stelle, an der der Browser Schutz bietet. Cookies sollten die Attribute `Secure`, `HttpOnly` und `SameSite` tragen, damit Sitzungen nicht über unverschlüsselte Verbindungen oder Skripte abgegriffen werden. Wie Sie das in PHP einstellen, beschreibt der Ratgeber zu Sessions.

## Security Header in Nginx setzen

In Nginx gehören die Header in den `server`-Block der jeweiligen Website. Der Zusatz `always` sorgt dafür, dass sie auch bei Fehlerseiten gesendet werden.

```nginx
server {
    # ...
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
    add_header Content-Security-Policy-Report-Only "default-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; form-action 'self'" always;

    server_tokens off;
}
```

Eine Eigenheit von Nginx: Setzt ein `location`-Block eigene `add_header`-Anweisungen, werden die Header aus dem `server`-Block dort nicht übernommen. Prüfen Sie deshalb auch Unterseiten und statische Dateien. Weitere Härtung für diese Kombination beschreibt [Nginx mit PHP-FPM absichern](https://phpsos.de/server/nginx-php-fpm/).

## Security Header in Apache setzen

Unter Apache benötigen Sie das Modul `mod_headers`. Die Anweisungen gehören in den VirtualHost oder, wenn kein Zugriff darauf besteht, in die `.htaccess`.

```apache
<IfModule mod_headers.c>
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()"
    Header always set Content-Security-Policy-Report-Only "default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'self'"
</IfModule>

ServerTokens Prod
ServerSignature Off
```

`ServerTokens` und `ServerSignature` gehören in die Hauptkonfiguration. Sie verhindern, dass der Server seine genaue Version in Antworten und Fehlerseiten nennt. In der `php.ini` erreichen Sie dasselbe für PHP mit `expose_php = Off`.

## Content-Security-Policy schrittweise einführen

Die Content-Security-Policy ist der wirksamste, aber auch anspruchsvollste Header. Sie legt fest, aus welchen Quellen Skripte, Stylesheets, Bilder, Schriften und Rahmen geladen werden dürfen. Wird ein eingeschleustes Skript von einer fremden Domain nachgeladen, blockiert der Browser es.

Moderne Websites binden oft Analyse-Werkzeuge, Zahlungsanbieter, Kartendienste oder Videos ein. Eine zu strenge Richtlinie legt dann Funktionen lahm. Gehen Sie deshalb in Stufen vor:

- Zuerst mit `Content-Security-Policy-Report-Only` starten. Der Browser meldet Verstöße in der Entwicklerkonsole oder an eine Sammeladresse, blockiert aber nichts.
- Alle benötigten Quellen erfassen und gezielt freigeben, statt pauschale Platzhalter zu verwenden.
- Inline-Skripte schrittweise in Dateien auslagern oder mit Nonces versehen, damit auf `'unsafe-inline'` verzichtet werden kann.
- Erst nach einer Testphase ohne unerwartete Meldungen auf `Content-Security-Policy` umstellen.

> **Tipp:**
> Die CSP ergänzt sauberes Escaping im Code, ersetzt es aber nicht. Wie Sie Ausgaben in PHP richtig absichern, steht im Ratgeber [Cross-Site-Scripting in PHP verhindern](https://phpsos.de/ratgeber/xss-php/).

## Header prüfen und typische Fehler vermeiden

Nach jeder Änderung sollten Sie prüfen, ob die Header tatsächlich ankommen. Das geht ohne zusätzliche Werkzeuge mit `curl`:

```bash
# Konfiguration testen und neu laden
nginx -t && systemctl reload nginx

# Header der Startseite und einer statischen Datei anzeigen
curl -sI https://www.example.de/ | grep -iE 'strict|content-security|x-content|x-frame|referrer|permissions|server'
curl -sI https://www.example.de/favicon.ico | grep -iE 'strict|x-content'
```

Typische Fehler sind doppelt gesetzte Header, wenn Webserver und Anwendung dieselben Header senden, ein vorgeschaltetes CDN, das Header entfernt oder überschreibt, und Header, die nur auf der Startseite, aber nicht bei Weiterleitungen oder Fehlerseiten erscheinen. Prüfen Sie außerdem nach Updates des CMS oder von Sicherheits-Erweiterungen, ob sich die Header verändert haben.

Legen Sie deshalb eine Stelle fest, an der die Header gepflegt werden, am besten den Webserver oder den vorgeschalteten Dienst. Viele CMS-Erweiterungen bieten ebenfalls Einstellungen für Sicherheits-Header. Das ist bequem, führt aber leicht zu doppelten oder widersprüchlichen Angaben, wenn zusätzlich der Server Header setzt. Für einzelne Tests eignen sich auch die Entwicklerwerkzeuge des Browsers: Im Netzwerk-Reiter sehen Sie zu jeder Anfrage die Antwort-Header, und die Konsole zeigt Verstöße gegen die Content-Security-Policy an.

## Wie hilft PHP SOS konkret?

- Wir prüfen die aktuellen Header aller Ihrer Websites, auch hinter CDN und Proxy, und zeigen Lücken und Widersprüche auf.
- Wir setzen die Header zentral im Webserver im Rahmen der [Server-Härtung](https://phpsos.de/leistungen/server-haertung/) und testen Startseite, Unterseiten und Fehlerseiten.
- Wir führen die Content-Security-Policy im Report-Only-Modus ein, werten die Meldungen aus und schalten sie nach Abstimmung scharf.
- Wo Code-Änderungen nicht sofort möglich sind, ergänzen wir den Schutz durch [WAF-Regeln und virtuelles Patching](https://phpsos.de/leistungen/waf-virtuelles-patching/).


## Häufige Fragen

**Was sind Security Header?**  
Security Header sind Zusatzangaben in der Antwort des Webservers. Sie sagen dem Browser zum Beispiel, dass er die Seite nur über HTTPS laden, keine fremden Skripte ausführen oder die Seite nicht in fremden Rahmen anzeigen soll. Sie schützen vor allem die Besucher.

**Schützen Security Header vor PHP2Shell?**  
Nein. PHP2Shell ist eine Lücke in PHP auf dem Server, Header wirken im Browser des Besuchers. Gegen PHP2Shell hilft das Update auf eine behobene PHP-Version und der Neustart aller Worker. Header sind eine ergänzende Härtung für andere Angriffsarten.

**Kann eine Content-Security-Policy meine Website kaputtmachen?**  
Ja, eine zu strenge Richtlinie blockiert benötigte Skripte, Schriften oder eingebettete Inhalte. Deshalb führt man sie zuerst im Report-Only-Modus ein, wertet die Meldungen aus und schaltet erst dann auf Durchsetzung um.

**Ist X-XSS-Protection noch sinnvoll?**  
Nein. Aktuelle Browser werten diesen Header nicht mehr aus, und die Empfehlung lautet, ihn wegzulassen oder auf 0 zu setzen. Schutz vor Cross-Site-Scripting bieten sauberes Escaping im Code und eine Content-Security-Policy.

## Quellen

- [OWASP Cheat Sheet Series (HTTP Headers)](https://cheatsheetseries.owasp.org/)
- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
- [BSI: Empfehlungen für Webserver](https://www.bsi.bund.de/)
