Zum Hauptinhalt springen

MIME-Sniffing & X-Content-Type-Options

Eine alte Browser-Funktion, die auf den ersten Blick nützlich klingt — aber ein gefährliches Einfallstor für XSS und Drive-by-Downloads ist.

Was ist MIME-Sniffing?

Wenn ein Browser eine Datei vom Server lädt, sagt der Server per Content-Type-Header, was es ist — text/html, image/png, application/javascript und so weiter. Was passiert aber, wenn der Server keinen Content-Type schickt oder einen offensichtlich falschen (z. B. eine .gif-Datei mit text/plain)?

Hier kam historisch MIME-Sniffing ins Spiel: Browser haben in die ersten paar Bytes der Datei geschaut und versucht, den Typ selbst zu erkennen. Sieht aus wie HTML? Dann als HTML rendern, egal was der Header sagt. Das war im frühen Web pragmatisch — viele Server haben Content-Types damals schlampig gesetzt — heute ist es eine Sicherheitslücke.

Das Sicherheitsproblem

Stellen wir uns vor: Auf deiner Webseite kann ein Nutzer Dateien hochladen — etwa Profilbilder. Der Angreifer lädt eine Datei hoch, die wie ein gültiges PNG aussieht, aber im Body HTML mit eingebettetem JavaScript enthält. Der Server gibt sie mit image/png aus — soweit, so unkritisch. Ein Browser ohne Sniffing würde das Bild laden, das Skript würde nie ausgeführt.

Aber: Hat der Browser Sniffing aktiv und entdeckt im Body HTML-Markup, rendert er die Datei plötzlich als HTML — das eingebettete JavaScript läuft im Kontext deiner Domain und kann auf Cookies, Session und alle Daten der eingeloggten Nutzer zugreifen. Aus einem gemütlichen Datei-Upload wird ein vollständiger XSS-Angriff.

Das gleiche Problem existiert auch andersherum: Eine harmlose Textdatei kann je nach Browser-Sniffing-Logik plötzlich als Skript ausgeführt werden, eine PDF-Datei als HTML usw. Klassiker auch: alte Adobe-Flash-basierte Sniffing-Bypässe.

Die Lösung: nosniff

Der Header X-Content-Type-Options: nosniff sagt dem Browser unmissverständlich:

"Vertraue ausschließlich dem Content-Type-Header. Mach kein Sniffing. Wenn ich sage, etwas ist image/png, dann lade es als Bild — und nichts anderes."

Mit nosniff wird der oben beschriebene Upload-Angriff wirkungslos: Der Browser sieht Content-Type: image/png und behandelt die Datei strikt als Bild. Auch wenn HTML drin ist — kein Rendern, kein Skript. Voraussetzung: Der Server schickt einen sinnvollen Content-Type. Bei einem fehlenden Header bleibt nosniff trotzdem konservativ und lädt die Datei nicht als ausführbar.

Werte

Der Header kennt nur einen einzigen sinnvollen Wert: nosniff. Alles andere wird ignoriert.

X-Content-Type-Options: nosniff

Konfigurationsbeispiele

nginx:

add_header X-Content-Type-Options "nosniff" always;

Apache:

Header always set X-Content-Type-Options "nosniff"

Express:

app.use(helmet.noSniff())

Cloudflare: Im Dashboard unter Rules → Transform Rules → Modify Response Header.

Voraussetzung: korrekte Content-Types

nosniff wirkt nur, wenn dein Server tatsächlich die richtigen Content-Types ausliefert. Ein Bild als text/plain lädt nicht mehr — nosniff blockiert es. Schlecht konfigurierte Servers können nach dem Aktivieren von nosniff plötzlich Funktionsprobleme bekommen.

Lösung: vor dem Aktivieren prüfen, dass alle gängigen Dateitypen korrekte MIME-Types bekommen — bei nginx wird das über /etc/nginx/mime.types geregelt, was meistens schon passt. Bei Apache wird in der Regel kein Eingriff benötigt.

Fazit

X-Content-Type-Options: nosniff ist einer der einfachsten Security-Header — keine Konfigurationsmöglichkeiten, kein Trade-off, einfach setzen. Für jede Webseite mit Datei-Uploads, User-Generated-Content oder API-Endpunkten Pflicht. Im Webscan Radar findest du den Header in der Liste der sechs überprüften Security-Header.

Selbst prüfen: HTTP-Header

HSTS, CSP, X-Frame-Options & Co. Gib eine Domain ein und sieh in Sekunden, wie es um deinen MIME-SNIFFING steht.

Auch im Lexikon