X-Content-Type-Options ist ein HTTP-Response-Header mit genau einem gültigen Wert: nosniff. Er weist den Browser an, den im Content-Type-Header deklarierten MIME-Typ strikt zu befolgen und niemals zu versuchen, den Inhaltstyp eigenständig zu erraten. Das verhindert eine Kategorie von Angriffen, die das MIME-Type-Sniffing-Verhalten von Browsern ausnutzen.
Von allen Sicherheitsheadern ist X-Content-Type-Options der einfachste zum Verstehen und Implementieren. Er braucht eine Zeile Konfiguration, hat keine komplexen Direktiven, und es gibt praktisch keinen Grund, ihn nicht zu verwenden. Trotzdem senden überraschend viele Websites ihn immer noch nicht.
Was ist MIME-Type-Sniffing und warum Browser es machen
Um zu verstehen, warum dieser Header existiert, braucht man etwas Geschichte. In den frühen Tagen des Webs waren viele Server schlecht konfiguriert und sendeten falsche Content-Type-Header. Ein Server konnte eine HTML-Datei als text/plain ausliefern oder ein Bild als application/octet-stream. Hätten Browser den deklarierten Typ strikt befolgt, wären diese Seiten als Rohtext gerendert oder als Download ausgelöst worden, anstatt korrekt angezeigt zu werden.
Um das zu umgehen, begannen Browser damit, den tatsächlichen Inhalt von Dateien zu „sniffen", um den echten Typ zu bestimmen. Der Browser schaute sich die ersten Bytes einer Antwort an, prüfte auf bekannte Signaturen (wie <html>-Tags, Bild-Header oder JavaScript-Muster) und überschrieb den deklarierten Typ des Servers, wenn der Inhalt anders aussah. Internet Explorer war dabei besonders aggressiv. Wenn IE etwas erkannte, das wie HTML oder JavaScript aussah, in einer als text/plain ausgelieferten Datei, renderte oder führte er es bereitwillig aus.
Das war ein vernünftiger Workaround für schlecht konfigurierte Server, schuf aber eine ernsthafte Sicherheitslücke.
Wie MIME-Sniffing Angriffe ermöglicht
Hier ist ein konkretes Angriffsszenario, das auf eine WordPress-Seite mit Datei-Uploads abzielt:
Angenommen, deine WordPress-Seite erlaubt Nutzern, Profilbilder hochzuladen. Dein Upload-Handler prüft die Dateierweiterung und erlaubt nur .jpg, .png und .gif. Ein Angreifer erstellt eine Datei, die mit gültigen Bild-Headern beginnt (die ersten Bytes sehen wie ein korrektes JPEG aus), aber nach dem Bild-Header eingebetteten JavaScript-Code enthält. Er nennt sie avatar.jpg und lädt sie hoch.
Dein Server speichert die Datei und liefert sie mit Content-Type: image/jpeg aus. Bis hierhin sieht alles korrekt aus. Jetzt verlinkt der Angreifer diese Datei von einer Seite aus, vielleicht in einem Forenbeitrag oder Kommentar, mit einem Script-Tag:
<script src="https://yoursite.com/uploads/avatar.jpg"></script>
Ohne X-Content-Type-Options könnte ein Browser, der MIME-Sniffing durchführt, die Datei betrachten, feststellen, dass sie JavaScript-ähnlichen Inhalt enthält, und sie als Skript ausführen, trotz des image/jpeg-Content-Types. Das JavaScript des Angreifers läuft jetzt im Kontext deiner Seite, mit Zugriff auf die Cookies und Sitzungsdaten deiner Besucher.
Mit dem nosniff-Header respektiert der Browser den deklarierten image/jpeg-Typ und weigert sich, die Datei als JavaScript auszuführen. Der Angriff schlägt fehl.
MIME-Sniffing und WordPress-Medien-Uploads
WordPress hat ein Medien-Upload-System, das viele Dateien verarbeitet: Bilder, PDFs, Dokumente, Audio, Video. Jede davon wird mit einem bestimmten MIME-Typ ausgeliefert. Der WordPress-Core führt bereits einige Validierungen bei Uploads durch (Prüfung der Dateitypen gegen eine erlaubte Liste, Verifizierung, dass der Dateiinhalt zur Erweiterung passt), aber diese Prüfungen sind nicht narrensicher.
Mehrere Faktoren machen WordPress hier besonders relevant:
- Mehrere Upload-Punkte: Die Mediathek, Gravity Forms, Contact Form 7, WooCommerce-Produktbilder, bbPress-Foren-Anhänge und viele andere Plugins verarbeiten alle Datei-Uploads. Jeder ist ein potenzieller Eintrittspunkt für bösartige Dateien.
- Nutzergenerierte Inhalte: Auf Seiten mit Mitgliedschafts- oder Community-Funktionen erlaubst du möglicherweise relativ unvertrauenswürdigen Nutzern, Dateien hochzuladen. Je mehr Upload-Quellen du hast, desto wichtiger ist es, dass der Browser Dateien genau wie deklariert behandelt.
- Plugin-Upload-Handler: Nicht alle Plugins validieren Uploads so sorgfältig wie der WordPress-Core. Ein schlecht geschriebenes Plugin könnte Dateien mit nicht übereinstimmenden Typen akzeptieren und genau die Bedingungen schaffen, die MIME-Sniffing-Angriffe ausnutzen.
- Shared-Hosting-Umgebungen: Auf Shared Hosting könnten Dateien von anderen Seiten auf demselben Server potenziell mit falschen Headern ausgeliefert werden. Die
nosniff-Direktive fügt eine Verteidigungsschicht hinzu, unabhängig von der Qualität der serverseitigen Konfiguration.
Der einfachste Sicherheitsheader zum Implementieren
Das Hinzufügen von X-Content-Type-Options erfordert eine Zeile. Es gibt keine Direktiven, zwischen denen man wählen müsste, keine Werte zum Feintunen und kein Risiko, Funktionalität zu beschädigen. Anders als CSP (das Inline-Skripte brechen kann), HSTS (das dich aussperren kann, wenn dein Zertifikat abläuft) oder Referrer-Policy (das Analytics beeinflussen kann), hat X-Content-Type-Options effektiv null Nachteile.
Für Apache (.htaccess oder Virtual-Host-Konfiguration):
Header always set X-Content-Type-Options "nosniff"
Für Nginx:
add_header X-Content-Type-Options "nosniff" always;
Per PHP in WordPress:
add_action('send_headers', function() {
header('X-Content-Type-Options: nosniff');
});
WordPress selbst sendet X-Content-Type-Options: nosniff bereits für Admin-Seiten und REST-API-Antworten seit Version 4.8. Die Frontend-Seiten der meisten WordPress-Installationen enthalten diesen Header jedoch nicht, es sei denn, du fügst ihn auf Server-Ebene oder über ein Sicherheitsplugin hinzu.
Wie moderne Browser MIME-Sniffing handhaben
Das Browser-Verhalten hat sich im Laufe der Jahre erheblich verbessert. Moderne Versionen von Chrome, Firefox, Safari und Edge sind weit weniger aggressiv beim MIME-Sniffing als Browser aus der Internet-Explorer-Ära. Chrome blockiert beispielsweise bereits Skripte mit einem Nicht-Skript-MIME-Typ in vielen Situationen, auch ohne den nosniff-Header.
Es gibt jedoch weiterhin Randfälle, in denen Sniffing stattfindet, und ältere Browser können nach wie vor anfällig sein. Der nosniff-Header liefert eine klare, eindeutige Anweisung, die jede Mehrdeutigkeit beseitigt. Er ist eine Best Practice, unabhängig davon, welche Browser deine Besucher verwenden.
Zusammenspiel mit anderen Sicherheitsheadern
X-Content-Type-Options funktioniert gut neben anderen Sicherheitsheadern, und es gibt keine Konflikte, um die man sich sorgen müsste:
- In Kombination mit CSP bietet er Verteidigung in der Tiefe: CSP kontrolliert, welche Quellen erlaubt sind, während
nosniffsicherstellt, dass Dateien aus erlaubten Quellen als ihr deklarierter Typ behandelt werden. - Mit HSTS stellst du verschlüsselte Verbindungen sicher, und mit
nosniffsicherst du zusätzlich die Inhaltsintegrität. - Anders als andere Header interagiert
nosniffnicht mit anderen Headern und überschreibt sie nicht. Er ist rein additiv.
Was InspectWP prüft
InspectWP prüft, ob deine WordPress-Seite den X-Content-Type-Options: nosniff-Header sendet. Da dieser Header nur einen gültigen Wert hat und keine Konfigurationskomplexität besitzt, gibt es wirklich keinen Grund für seine Abwesenheit. Wenn deiner Seite dieser Header fehlt, ist er einer der schnellsten Sicherheitsgewinne, die du erzielen kannst. Das Hinzufügen dauert weniger als eine Minute und bietet sinnvollen Schutz gegen MIME-Type-Confusion-Angriffe, besonders auf Seiten, die Datei-Uploads verarbeiten.