Question

I'm developing an ASP.NET Web app and would like the user to be able to either upload an image from their local system, or pass in a URL to an image. The image can either be a JPG or PNG. What security issues should I be concerned about doing this? I've seen various ways of embedding code within JPG files. Are there any methods in C# (or external libraries) which can confirm that a file is a JPG/PNG, otherwise throw an error? At the very least, I'm making the directory which holds uploaded images non-browsable and putting a max size limit of 1mb, but I'd like to implement further checks.

Thanks for any advice.

Was it helpful?

Solution

Are there any methods in C# (or external libraries) which can confirm that a file is a JPG/PNG, otherwise throw an error?

Maybe, but that doesn't really help in itself. You can easily make file that is both a valid image format and contains active HTML/script content for IE content-sniffing to stumble on. Or then there's the broken Java and Flash origin policies to worry about, which can have the same effect of scripting into your server's security context.

  1. If you process the image (eg. crop, resize) and re-save that makes it very, very difficult to do content-smuggling attacks. However, you should always ensure that your server-side tools are up-to-date, as vulnerabilities in image processing libraries might expose you to server-side exploit.

  2. If you can't do that, your best bet as a mitigation for all content-injection problems is to serve your images from a different [sub]domain which doesn't have access to any of the sensitive credentials (cookies, basic auth) of the main site.

  3. If using a subdomain for this purpose such as images.example.com, your main site should be accessible only through www.example.com and not example.com. Otherwise, content injected into images.example.com can access cookies for example.com in IE. example.com should 301-redirect to www.example.com to prevent unwanted cookie leakage in general.

  4. Add the header X-Content-Type-Options: nosniff to the response to block content-smuggling attacks from IE8. (Doesn't help with earlier versions, alas.)

Also:

  1. Sanitising user-specified filenames is hard, especially if your app is likely running on a Windows server where the rules about usable filenames are complicated indeed. A good place to start is allowing only alphanumerics, and adding your own file extension and prefix. (A prefix is necessary to avoid the Windows reserved filenames, and the empty filename.)

  2. Better: store the user-supplied filename in the database instead of using it as a real filename.

See this question for more discussion of file upload security problems.

OTHER TIPS

This is an absolute minefield. Something to take into consideration (not necessarily an exhaustive list, no guarantees, etc.).

  • Some people use regexs for parsing, so there is no way of knowing if the file contains code. ZIP files have their directory at the end. Sun/Oracle Java PlugIn/WebStart now checks that the file starts with a ZIP local header/entry magic number to avoid "GIFAR" attacks.
  • Serve from a different domain, to avoid same-origin problems.
  • Serve from a different IP address, to avoid same-origin problems.
  • It's a bit tricky to check if the file is exploiting, say, a 0-day buffer overflow. It might even exploit an infinite loop to create a DoS.
  • It's best to re-encode the image.
  • Careful with the URL/file path name. If you give an option, use whitelist checking. In particular NUL characters are "fun". See also directory traversal attacks. In general being able to place a file of given contents an a known location is, at the least, a big dodgy.
  • Or images you might want to check that the size is sane. Decompressing a huge image could well lead to a DoS. Also note that compression algorithms often allow compressing trivial data by huge factors.

Don't let the user determine the file name that will be used on your server. Use [generated guid].jpg instead and put the file name they used in a database table if you need it.

See #12 here: http://www.codinghorror.com/blog/2009/01/top-25-most-dangerous-programming-mistakes.html

External Control of File Name or Path When you use an outsider's input while constructing a filename, the resulting path could point outside of the intended directory. An attacker could combine multiple ".." or similar sequences to cause the operating system to navigate out of the restricted directory. Other file-related attacks are simplified by external control of a filename, such as symbolic link following, which causes your application to read or modify files that the attacker can't access directly. The same applies if your program is running with raised privileges and it accepts filenames as input. Similar rules apply to URLs and allowing an outsider to specify arbitrary URLs.

Be careful with the URL too, make sure it's an absolute, external URL so they can't use your own web server to copy a confidential file off your LAN out into an area they can access it since you'll be loading that URL from code running on your web server.

You may use Infrastructure as a Service for handling images, for example our solution - Uploadcare:

https://uploadcare.com

If you apply any of the image operations to the uploaded image, it gets modified, and therefore any code that might be embedded within the file will be destroyed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top