MIME sniffing in Internet Explorer enables cross-site scripting attacks
by Henry Sudhof
Uploading images is a standard requirement in any Web 2.0 application, but some features of Internet Explorer need to be carefully handled, otherwise a gap can open up and facilitate cross-site scripting attacks on site visitors.
At the heart of the problem is the variety of ways in which a file's type can be determined. A jpg filename extension, for example, indicates an image in JPEG format. The web server may also define Content-Type (image/jpg in this case) in the HTTP header, but as a rule it determines the type of file being uploaded from its file name extension. Finally, most web browsers also check the first few bytes of a file (its "signature") for known byte sequences, such as PNG, PK, JPEG JFIF and so on.
Internet Explorer 4 introduced a fourth method, known as MIME sniffing, or mime type detection. So no version of IE now automatically assumes that a file taken from the web has the same content type as that stated by the server in the HTTP header. Nor does it trust the file name extension, or signature, on their own. Instead, Internet Explorer also examines the first 256 bytes of the file to determine its type. The snag is that it does this, only if the user calls up the URL directly, to download the file. No problems arise when locally stored files, or images that the browser links to via image tags (IMG) in HTML pages, are opened with Internet Explorer.
MIME sniffing was originally meant to guard against incorrect indications of content type by servers. These could be exploited by attackers to circumvent protective functions in Internet Explorer that were meant to prevent the browser automatically executing downloaded files, such as hta files. MIME sniffing also makes the browser tolerant of accidental errors in Content-Type statements. If, for example, the server announces text/plain, but then supplies an HTML file, Internet Explorer will handle it as HTML.
With the common GIF, JPEG and PNG formats, the browser ignores the result of MIME sniffing, as long as the filename extension, Content-Type and signature, all indicate the same type. Only if the results are inconsistent will Internet Explorer handle the file as the type identified by MIME sniffing.
security_logo_en.png, Content-Type: image/png, Signature: PNG
In the second example, we have changed the file extension to JPG. The server has noted this and changed the content-type to image/jpeg. But the signature check on the file says the file is PNG. Because the content-type (image/jpeg) clashes with the signature (PNG), the browser takes a closer look and renders the file as HTML.
security_logo_en.jpg, Content-Type: image/jpeg, Signature: PNG
In the third example, the file extension is BMP, the content type is image/bmp and the signature is BMP. Everything looks correct, but it is still interpreted at text/html. The reason for this is that the server states the content type as image/bmp when it really should be image/x-ms-bmp. This mis-statement of content type is not uncommon; we did not specifically configure our server to send the wrong content-type.
security_logo_en.bmp, Content-Type: image/bmp, Signature: BMP