X-Content-Type-Options is een HTTP-response-header met precies één geldige waarde: nosniff. Hij instrueert de browser om strikt het in de Content-Type-header opgegeven MIME-type te volgen en nooit zelf te proberen het content-type te raden. Dit voorkomt een categorie aanvallen die het MIME-type-sniffing-gedrag van browsers misbruiken.
Van alle beveiligingsheaders is X-Content-Type-Options de eenvoudigste om te begrijpen en te implementeren. Hij vergt één regel configuratie, heeft geen complexe directieven en er is in feite geen reden om hem niet te gebruiken. Toch versturen verrassend veel websites hem nog steeds niet.
Wat is MIME-type-sniffing en waarom doen browsers het
Om te begrijpen waarom deze header bestaat, helpt wat geschiedenis. In de begindagen van het web waren veel servers slecht geconfigureerd en verstuurden ze onjuiste Content-Type-headers. Een server kon een HTML-bestand serveren als text/plain, of een afbeelding als application/octet-stream. Hadden browsers het opgegeven type strikt gevolgd, dan zouden deze pagina's als ruwe tekst zijn weergegeven of een download hebben getriggerd in plaats van correct te worden getoond.
Om dit te omzeilen, begonnen browsers met het "snuffelen" aan de werkelijke inhoud van bestanden om het echte type te bepalen. De browser bekeek de eerste bytes van een response, controleerde op bekende handtekeningen (zoals <html>-tags, beeldheaders of JavaScript-patronen) en overschreef het door de server opgegeven type als de inhoud anders leek. Internet Explorer was hier bijzonder agressief in. Detecteerde IE iets dat eruitzag als HTML of JavaScript binnen een bestand dat als text/plain werd geserveerd, dan rendeerde of voerde hij het vrolijk uit.
Dit was een redelijke workaround voor slecht geconfigureerde servers, maar creëerde een serieus beveiligingslek.
Hoe MIME-sniffing aanvallen mogelijk maakt
Hier is een concreet aanvalsscenario gericht op een WordPress-site met file uploads:
Stel dat uw WordPress-site gebruikers profielafbeeldingen laat uploaden. Uw upload-handler controleert de bestandsextensie en staat alleen .jpg, .png en .gif toe. Een aanvaller maakt een bestand dat begint met geldige beeldheaders (de eerste bytes lijken op een correcte JPEG), maar dat na de beeldheader JavaScript-code bevat. Hij noemt het avatar.jpg en uploadt het.
Uw server slaat het bestand op en serveert het met Content-Type: image/jpeg. Tot zover lijkt alles in orde. Maar nu linkt de aanvaller naar dit bestand vanaf een pagina, bijvoorbeeld in een forumbericht of reactie, met een script-tag:
<script src="https://uwsite.com/uploads/avatar.jpg"></script>Zonder X-Content-Type-Options zou een browser die MIME-sniffing toepast naar het bestand kunnen kijken, opmerken dat het JavaScript-achtige inhoud bevat, en het ondanks het content-type image/jpeg als script uitvoeren. De JavaScript van de aanvaller draait nu in de context van uw site, met toegang tot cookies en sessiegegevens van uw bezoekers.
Met de header nosniff respecteert de browser het opgegeven type image/jpeg en weigert hij het bestand als JavaScript uit te voeren. De aanval mislukt.
MIME-sniffing en WordPress-media-uploads
WordPress kent een media-uploadsysteem dat veel bestandstypen verwerkt: afbeeldingen, PDF's, documenten, audio en video. Elk daarvan wordt geserveerd met een specifiek MIME-type. WordPress core valideert uploads al enigszins (controle van bestandstypen tegen een toegestane lijst en verificatie dat de inhoud bij de extensie past), maar deze controles zijn niet waterdicht.
Verschillende factoren maken WordPress hier bijzonder relevant:
- Meerdere uploadpunten: de mediabibliotheek, Gravity Forms, Contact Form 7, WooCommerce-productafbeeldingen, bbPress-forumbijlagen en vele andere plugins verwerken allemaal file uploads. Elk daarvan is een potentiële toegangspoort voor kwaadaardige bestanden.
- Door gebruikers gegenereerde inhoud: op sites met lidmaatschaps- of community-functies staat u mogelijk relatief onbetrouwbare gebruikers toe bestanden te uploaden. Hoe meer uploadbronnen, hoe belangrijker dat de browser bestanden exact behandelt zoals opgegeven.
- Plugin-uploadhandlers: niet alle plugins valideren uploads zo zorgvuldig als WordPress core. Een slecht geschreven plugin kan bestanden met niet-overeenkomende types accepteren en zo precies de omstandigheden creëren die MIME-sniffing-aanvallen misbruiken.
- Shared-hosting-omgevingen: in shared hosting kunnen bestanden van andere sites op dezelfde server mogelijk met onjuiste headers geserveerd worden. De directive
nosniffvoegt een verdedigingslaag toe ongeacht de kwaliteit van de server-configuratie.
De eenvoudigste beveiligingsheader om te implementeren
X-Content-Type-Options toevoegen kost één regel. Er zijn geen directieven om uit te kiezen, geen waarden om af te stemmen en geen risico om functionaliteit te breken. In tegenstelling tot CSP (dat inline scripts kan breken), HSTS (dat u kan buitensluiten als uw certificaat verloopt) of Referrer-Policy (dat analytics kan beïnvloeden) heeft X-Content-Type-Options praktisch geen nadeel.
Voor Apache (.htaccess of virtual-host-config):
Header always set X-Content-Type-Options "nosniff"Voor Nginx:
add_header X-Content-Type-Options "nosniff" always;Via PHP in WordPress:
add_action('send_headers', function() {
header('X-Content-Type-Options: nosniff');
});WordPress verstuurt zelf al sinds versie 4.8 X-Content-Type-Options: nosniff voor admin-pagina's en REST API-responses. De front-end-pagina's van de meeste WordPress-installaties bevatten deze header echter niet, tenzij u hem op serverniveau of via een beveiligingsplugin toevoegt.
Hoe moderne browsers met MIME-sniffing omgaan
Het browsergedrag is in de loop der jaren aanzienlijk verbeterd. Moderne versies van Chrome, Firefox, Safari en Edge zijn veel minder agressief met MIME-sniffing dan browsers uit het Internet Explorer-tijdperk. Chrome blokkeert bijvoorbeeld in veel situaties al scripts met een niet-script MIME-type, zelfs zonder de header nosniff.
Toch zijn er nog edge cases waarin sniffing voorkomt, en oudere browsers kunnen nog kwetsbaar zijn. De header nosniff geeft een duidelijke, definitieve instructie die alle dubbelzinnigheid wegneemt. Het is een best practice ongeacht welke browsers uw bezoekers gebruiken.
Interactie met andere beveiligingsheaders
X-Content-Type-Options werkt goed samen met andere beveiligingsheaders en er zijn geen conflicten om u zorgen over te maken:
- Gecombineerd met CSP biedt het verdediging in de diepte: CSP bepaalt welke bronnen zijn toegestaan, terwijl
nosniffervoor zorgt dat bestanden uit toegestane bronnen behandeld worden als hun opgegeven type. - Met HSTS zorgt u voor versleutelde verbindingen, en met
nosniffwaarborgt u daarbovenop de integriteit van de inhoud. - In tegenstelling tot andere headers heeft
nosniffgeen interactie met of overschrijving van andere headers. Hij is puur additief.
Wat InspectWP controleert
InspectWP controleert of uw WordPress-site de header X-Content-Type-Options: nosniff verstuurt. Omdat deze header slechts één geldige waarde heeft en geen configuratiecomplexiteit kent, is er werkelijk geen reden waarom hij zou ontbreken. Als uw site deze header mist, is dit een van de snelste beveiligingswinsten die u kunt boeken. Toevoegen kost minder dan een minuut en biedt zinvolle bescherming tegen MIME-type-verwarringsaanvallen, vooral op sites die file uploads verwerken.