20

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?

5
  • 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 3, 2011 at 23:00
  • The additional question is: how to tell HTTP clients that the MIME-type is untrusted?
    – curiousguy
    Nov 4, 2011 at 5: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 4, 2011 at 7: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. Nov 4, 2011 at 7:44
  • @this.josh Question updated. Nov 4, 2011 at 23:36

4 Answers 4

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).

4
  • 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? Nov 4, 2011 at 23:38
  • 2
    For example, a <script> tag will load and execute a payload from an URL that returned Content-Type-Disposition: attachment header. Nov 5, 2011 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, 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 6, 2011 at 1:39
  • Worth noting that the correct approach is to whitelist the particular extensions (and specific MIME types, if you're not generating MIME types strictly from extensions) you need. There are some non-obvious ones that can allow nefarious things (for example, SVGs can run JS; in modern browsers this won't happen from <img src> but nevertheless...), plus any new things browsers add in the future. May 26 at 19:06
11

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.

7
  • 1
    "It is not safe." Well, it should be. This is a flaw in HTTP.
    – curiousguy
    Nov 4, 2011 at 5: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? Nov 4, 2011 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 4, 2011 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 6, 2011 at 1: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 6, 2011 at 1:54
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."

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.

1
  • 1
    I don't think he mentioned lawyers.
    – curiousguy
    Nov 4, 2011 at 5:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .