sroze / SRIORestUploadBundle

A symfony bundle to handle multiple upload ways on your REST API.
46 stars 17 forks source link

There is no mime type checking at all in this bundle #25

Open NinoFloris opened 8 years ago

NinoFloris commented 8 years ago

This leaves you extremely vulnerable to a nice amount of attacks as you cannot safely assume your mimetype validation whitelist will be honored.

Say you have a nice upload directory, a whitelist that only accepts image formats and are allowing any of your users to upload an image.

  1. Send a php script (MyLittleScript.png) with an image/png mime-type
  2. Read this from the upload directory
  3. Pwnd

Better hope all your users know to never put their upload directory in an executable folder, like /web, they probably don't know. For instance Apache with php-cgi will gladly run any php file (your uploaded file included) if it's in the web root, and its even a symfony sanctioned config http://symfony.com/doc/2.8/setup/web_server_configuration.html. Or any of these tricks https://nealpoole.com/blog/2011/04/setting-up-php-fastcgi-and-nginx-dont-trust-the-tutorials-check-your-configuration/

Now with a lot of adapters that do external uploads (s3, dropbox) etc it's usually not a problem. If and only if this external source has their headers setup correctly to prevent further attacks, X-Content-Type-Options=nosniff is the minimum you need.

Without this header, you'll open a new can of worms in the form of neat XSS tricks, picture the process above but with an html file, now imagine a host does not have X-Content-Type-Options=nosniff set. Browsers will then turn to their harmful (old) mimetype sniffing/guessing behavior where they don't care about the mimetype you as host respond with but just guess from the body contents.

If a host serves the 'image' via a common pattern like so <a href="url"><img src="url"/></a>, once a user clicks this link, game over.

When the browser, if it is not explicitly instructed to not do any sniffing, knows the content-type (say image/png), it starts doing this:

If the server-provided MIME type is either known or ambiguous, the buffer is scanned in an attempt to verify or obtain a MIME type from the actual content. If a positive match is found (one of the hard-coded tests succeeded), this MIME type is immediately returned as the final determination, overriding the server-provided MIME type source: https://blog.fox-it.com/2012/05/08/mime-sniffing-feature-or-vulnerability/

After the browser has concluded that this image is actually an html file all script tags inside this file start executing and because it's probably served from the same domain there are no issues with same origin policy at all, it's really just over.

So to summarise, at best you have a huge chance of XSS vulnerabilities and at worst your whole backend gets owned. Nice!

NinoFloris commented 8 years ago

Short update, we are working on introducing this by adding a temp storage filesystem (which should be a local mountpoint/folder) so the file can be scanned before being uploaded.

This fix is the expanded solution I had lying around (and wanted to PR next) for the lurking DOS vulnerability in the resumable upload (https://github.com/sroze/SRIORestUploadBundle/pull/23 see P.S.). With a local filesystem you can seek in the stream and append the new chunk without having to completely download and reupload the file again from and to the remote source. It does require a temp storage big enough to house that file temporarily but considering mime type checking has to be done locally too this is not a strange requirement.