19

If a user uploads a file but modifies the request by setting the mime-type to something arbitrary, like "superdangerous/blackhatstuff", is it safe for me to send the same mime type back to a different user later on?

I.e. another user downloads the same file and I set the mimetype to "superdangerous/blackhatstuff", is it possible to set the mime type to something potentially dangerous? Because it is user-supplied data, I get the feeling it's not a good idea to store and replay without some kind of sanitization. (I am of course, sanitizing the query before I store the mime type, so I'm not concerned with SQL injection attacks via the mime type.)

I am using clam AV to scan uploaded files, which hopefully catches some of the mime sniffing attacks, but that's not really what I'm asking about here.

If this is, in fact, dangerous, then what is the proper thing to do? Should I not specify a mime-type at all, and let the receiver guess it? Should I try to do my own mime sniffing (I'm using PHP on Linux, which provides an API for file magic.)

Edit: More Details

Let me explain the purpose of this feature. The application in question is used as part of a workflow that requires various kinds of artifacts to be submitted for review and approval, including (but not limited to), word docs, spreadsheets, images, and archives. Other users will need to be able to download these artifacts in order to view them and make an approval decision.

To prevent the some obvious breaches, we have blacklisting in place (such as uploading a PHP or Javascript file) and we are setting the Content-Disposition to "attachment; filename=...". We are running Clam AV on uploaded files as a basic sanitization, since we can't really enforce a whitelist on our users. The app runs on an intranet and requires authentication before anything can be accessed, and our users are [mostly] trusted.

Anyway, point being is that I'm not asking about the safety of storing files and letting users download those files. (I realize it's a large threat vector, but it's not the question I'm asking.) I'm really more concerned about whether it's safe to replay a user-supplied mime-type, and if not, what is the alternative? To not specify a mime type at all?

AviD
  • 72,138
  • 22
  • 136
  • 218
Mark E. Haase
  • 1,902
  • 2
  • 15
  • 24
  • 1
    I think your question would benefit from further clarification. What is the purpose of uploading and downloading files of arbitrary type? Are all files on the system community property: i.e. once uploaded anyone can download? – this.josh Nov 03 '11 at 23:00
  • The additional question is: how to tell HTTP clients that the MIME-type is untrusted? – curiousguy Nov 04 '11 at 05:17
  • @curiousguy, you can't tell HTTP clients that the MIME type is untrusted, but you can defend against attacks in various ways. See my answer for details. – D.W. Nov 04 '11 at 07:13
  • 3
    This will also break normal operation - e.g. Internet Explorer 4-8, in its infinite wisdom, sends `image/pjpeg` when it means `image/jpeg`; thus, JPEGs uploaded from IE will only display correctly in IE, if you trust the browser-supplied MIME type. – Piskvor left the building Nov 04 '11 at 07:44
  • @this.josh Question updated. – Mark E. Haase Nov 04 '11 at 23:36

4 Answers4

13

No, you shouldn't reply the user-supplied MIME type to the user. The simplest attack that you're exposing your users to would be to upload text/html file with arbitrary Javascript code e.g. in [script] elements. Users given the uploaded file URL would have the Javascript executed, resulting in XSS. This can be somewhat mitigated by serving the files with Content-Type-Disposition: attachment header, but there are ways around that.

Another vector would be storing malicious Java applets or Flash files and many other files whose MIME type make them relevant to web security (HTML5 offline manifest file, crossdomain.xml, various files executable on client - exe, vbs, ...).

While we're at it - be sure to serve the user-supplied files from a domain separate from your 'main' applications, to protect from XSS attacks (same origin policy will stop them if files come from a different domain).

Krzysztof Kotowicz
  • 4,068
  • 20
  • 30
  • I like this answer and the one below, but unfortunately this is a product that can be downloaded and installed. It's not possible to enforce a separate domain for user-supplied files. Can you elaborate on how the content disposition header can be worked around? – Mark E. Haase Nov 04 '11 at 23:38
  • 2
    For example, a – Krzysztof Kotowicz Nov 05 '11 at 17:40
  • "_you're exposing your users to would be to upload text/html file with arbitrary Javascript code e.g. in elements._" Your link gives an HTML5 fix to that [text/html-sandboxed](http://www.w3.org/TR/html5/iana.html#text-html-sandboxed), but it is _ad hoc_ and thus ugly. What about Java applets? Flash objects? A generic and fail-safe approach is wanted! Something like "`Content-Type: untrusted/what/ever`" (f.ex. `Content-Type: untrusted/text/html`, `Content-Type: untrusted/application/x-shockwave-flash`). – curiousguy Nov 06 '11 at 01:39
10

The short answer: It is not safe. Allowing the user to specify the MIME type and the contents of the file is a self-inflicted XSS hole.

A malicious user Mallory could specify the MIME type text/html, and provide a HTML document that contains malicious Javascript. When you serve that document to another user Alice, Alice's browser will execute the malicious Javascript. The malicious Javascript could steal Alice's session cookies, Alice's password for this site, and all of Alice's data on this site, or could tamper with the content that Alice sees on this site.

So, no, it's not safe.

Edit (11/4): I see you edited your question to ask what you should do. This is a complex question, but let me give you some basic strategies to defend against this threat:

  • Option 1: No user-provided content. Don't host user-provided content. Then you don't have to worry about this issue.

  • Option 2: Only allow whitelisted MIME types. Allow the user to upload data and specify a MIME type, but only if the user-provided MIME type is on a whitelist of known-safe MIME types that cannot trigger execution of malicious code. For instance, text/plain and image/jpeg are generally safe, if you apply appropriate defenses against content-sniffing attacks, and thus could be included on the whitelist. text/html and application/x-shockwave-flash are not safe and should not be included on the whitelist.

  • Option 3: Use a different domain. Serve the user-uploaded content from a different domain. Make sure that domain only hosts user-submitted content that is not security sensitive. Do not host any of your own material on that site. Then, the browser's same-origin policy will isolate attacks: a malicious uploaded file may be able to attack other user-uploaded content on that domain, but not to steal passwords/session cookies/etc. from your main site.

D.W.
  • 98,420
  • 30
  • 267
  • 572
  • 1
    "_It is not safe._" Well, it should be. This is a flaw in HTTP. – curiousguy Nov 04 '11 at 05:32
  • 1
    @curiousguy: Wait, how is "user can arbitrarily manipulate request headers, as he's in full control of the user-agent" a flaw in HTTP? All user(agent)-supplied data is untrustworthy (and that holds for *any* protocol, not just HTTP), MIME type of uploaded files is user-agent supplied, ergo MIME type is untrustworthy. How exactly would you suggest to fix that? – Piskvor left the building Nov 04 '11 at 10:29
  • 1
    reworded comment: "_Allowing the user to specify the MIME type and the contents of the file is a self-inflicted XSS hole._" Well, it should not be. This is a flaw in HTTP. – curiousguy Nov 04 '11 at 14:22
  • 1
    @Piskvor "_It is not safe. Allowing the user to specify the MIME type and the contents of the file is a self-inflicted XSS hole._" "_This is a flaw in HTTP._" "_How exactly would you suggest to fix that?_" with a new header to indicate the access rights of the content. Of course, if you change HTTP version 1, you have the issue of existing HTTP clients. The solution should be failsafe for existing clients that don't know the new header. OTOH, if you change HTTP major version, you do not have this problem. – curiousguy Nov 06 '11 at 01:48
  • 1
    "_Make sure that domain only hosts user-submitted content that is not security sensitive._" then you cannot implement secure access control to these uploaded documents! Really, the H-couple (HTTP/HTML) sucks baldy. (I won't even mention the applet stuff.) – curiousguy Nov 06 '11 at 01:54
  • 1
    @curiousguy, it's easy to criticize existing web schemes, but I don't know how constructive or helpful that is if you don't have a viable solution. As for your specific proposal, I encourage you to read ["Beware of Finer-Grained Origins"](http://w2spconf.com/2008/papers/s2p1.pdf) and reflect on the fact that you are proposing a finer-grained origin policy -- an approach that turns out to have some non-obvious challenges. – D.W. Nov 06 '11 at 02:14
  • @D.W. "_it's easy_" Pointing how easy something is is easy, but not very constructive. "_I don't know how constructive or helpful that is if you don't have a viable solution_" understanding the flaws of existing tools is IMO essential for protocols users and protocol designers (same with programming languages). I don't think that pointing out that I don't offer any solution is helpful or constructive. – curiousguy Nov 06 '11 at 03:06
1

is it safe for me to send the same mime type back to a different user later on?

I am going to chance my arm and say yes, but you may have to stop if it doesn't work out.

In this case, a closed environment with mostly trusted users, white-listing or limiting uploads MIME types is going to add a little overhead or inefficiency for some percentage of your user base. The more users, the more likely they have some format you had not considered. If a user's file format is not on your list then you will either have to make an exception, modify your white-list, or they will need to convert the file to a different format. Its work and it has cost.

You have thought about the problem and provided some mitigation with the anti-virus scan. This mitigation is not enough. You will need to ensure that you backup your machine and if the machine goes down for any reason you and restore the lost service in a timely manner. Additionally you need to monitor what users are doing with the MIME type and if it gets abused or becomes a problem, then you need to turn on the white-list.

This basically boils down to you providing the users what they need, and if necessary protect them from each other and themselves. Depending on whom your users are, you might even want to point out the issue and let them know you will be watching. Something along the lines of: "Hey everyone, the new review server is up at 192.168.0.240. You can submit any file format you want, which is a little risky but I will be logging and reviewing the uploads."

this.josh
  • 8,843
  • 2
  • 29
  • 51
0

Well, serving back the unmodified content-type from a user could end up with your sending content under the type "third-reich-rules/heil-hitler", which could get you sued and/or laughed at in some circles with low/weird sense of humour (such as half of the land which lies between North Atlantic and North Pacific oceans).

I suppose that if you want to send back a user-specified content-type, it is because you actually want to send back to an user a file which was uploaded by another user -- which is already a whole can of worms. And by "can" I mean "20-gallon tank".

You may console yourself with the idea that e-mail servers do that constantly: each email may have attached files with many content types that the e-mail server has no idea about. Historically, this has implied an awful lot of security issues with mailer agents which, upon receiving a file tagged as "executable" found it fit to react with: "an executable ? Great, let's run it automatically !".

If your lawyers do not let you take the road of not-my-fault, then you will want to thoroughly sanitize the file contents, which necessarily implies knowing the file type, which automatically implies knowing what content-type is appropriate. So the question of letting the user-specified content-type go through should not be relevant. If it is, then there is something fishy in your sanitation process.

Tom Leek
  • 168,808
  • 28
  • 337
  • 475