The Dangers Of Allowing Public File Uploads To Your Web Site

A common question on Yahoo! Answers is how to allow users to upload files to a Web site. Unfortunately, allowing file uploads on a Web site is the single most dangerous thing you can do as a Webmaster.

In short, if you allow people to upload files to your site, you’re opening yourself up to a world of trouble, from having your site defaced to compromising the entire Web server you’re on, straight through to possibly trafficking in illegal materials. So if you’re new to Web programming, it’s wisest to not mess with file uploading at all, or at least use a canned solution that has taken some of the worry out of hosting illegal and dangerous files.

Let’s first talk about why public uploads to Web servers are dangerous, then get into how to mitigate those dangers.

Problem 1: A Web Server Will Allow People To Upload Anything, Including Viruses And Illegal Content

A Web server is nothing more than a file server; therefore, if you have a file uploading script, malicious visitors could put any old file they want on your site, and other nogoodniks can come along and get those files from your Web server.

All a Web server really does is accept requests for files and respond with the files requested (the “request-response” model). Most Web servers do not care what kinds of files are on them (although some Web hosting companies will not allow certain types of files, such as ZIP files, executables, etc., to be stored on a Web site). All Web servers care about is whether they have the file that was requested, and whether they can send back to the visitor the file that was requested.

As a result, if someone uploads a dangerous file, such as a virus, or something illegal, such as child pornography, the Web server doesn’t care. If someone comes along and asks for that file, and the Web server can find it, the Web server will simply send the file along its merry way.

Technically, in the United States, at least,if you do not monitor what is uploaded to your server, you cannot be held liable for it, but you must immediately remove materials that are brought to your attention as being stolen or illegal. (In the case of child pornography, however, the rules are a lot less clear and there’s a strong likelihood you’d be held responsible for distributing it, even via an unmonitored uploading service.)

Morally, it’s incumbent upon you to not distribute dangerous and illegal materials via your Web site. And that ought to outweigh any legal requirements, at least if you’re anything approaching a decent human being.

Problem 2: Allowing Uploads Assisits Hackers In Defacing And Taking Over Your Web Site

The second part of the problem lies in how computers manage permissions to do certain tasks.

Basically, everything you do on a server — even serving up files and pages over the Web — requires you to have a user account with the proper permissions. In the case of Web servers, most requests are made anonymously — that is, you don’t need to log in to the computer itself in order to view Web pages.

The way Web servers manage that is by having a special user account to handle anonymous Web requests. This built-in user generally doesn’t have many permissions at all; basically, all it can do is read certain files in certain directories (namely, your HTML directories).

This keeps the Web server safe because the built-in anonymous Web user is so restricted in what it can do, that even if a hacker was to take over the user, he couldn’t do anything with the account but look at Web pages.

However, if you want any old Joe to be able to upload a file to your Web site, then you need to grant the server’s built-in anonymous Web user the right to write files. That means, if a hacker took over, he, too, could write files to whatever directory you are using to upload files.

If you’re not careful about how you set up, that means a hacker could replace any page in your Web site with a page he wants to use. For example, if you set your root Web directory to be writeable, the user could replace your home page with one of his choosing.

Or he could delete any files other people have uploaded. Or, again depending on how many security lapses you create, the hacker could, in theory, gain root privileges to your Web server and cause real chaos.

Problem 3: There’s No Foolproof Way To Screen A File’s Content Before It Is Uploaded, And Even Then It’s Tough

Because of the way HTTP file uploads work, it’s not easy to check what a file really contains until it is actually on the server.

You can try to use JavaScript and multiple post operations to check a file’s extension, but depending again on your skill level, it’s not difficult for most hackers to bypass such screening efforts. You effectively can’t screen the content type of the file until it’s on the server, and even if the content type is acceptable — for example, it’s not an executable file — you can’t really evaluate the file’s contents unless it’s text.

And even then, any program you write is going to be limited in its ability to discern what’s legitimate and what is not; just notice how easily spam gets through your e-mail filters for an example of what I mean.

Nothing is better than a pair of eyeballs examining each file, is the short of it.

There are ways to defend against all of these problems, but again, you need some experience to employ such solutions.

Rule 1: Never Allow Files To Be Uploaded To Your Public HTTP Path

You should never make a Web-accessible folder writeable. You should never allow people to directly upload any file to a directory that is accessible via Web browser. And the reason for that is simple: If you do, you’ll be overrun with viruses, warez and kiddie porn before you know it. Also, if you’re not careful, you’ll swing the doors wide open for people to deface your site.

Your Web host should provide you with the opportunity to create directories outside your public HTTP path. If you are going to have file uploads, you should create such a directory with a difficult-to-guess name, such as 13gfdo87gyi5.

That protects you from having people put naughty files on your site for others to download, and it prevents hackers from having an easy front door from which to attack your site; since the directory is neither available via HTTP nor easily guessed, it might as well not exist as far as the average script kiddie or other jerk is concerned.

The idea is that you allow the upload to this non-public directory. There, you evaluate the file: Is it safe? Once that’s done, you can then move it to some public place, or better yet, use a programmatic solution, such as a PHP page, to serve it from the non-public directory. More on that shortly.

Rule 2: Protect Your Upload Form Against Forgeries

If you aren’t careful, and you make it easily known to the public where you are writing uploaded files, it’s no great trick for someone else to create an upload form of his own that uses your Web server to do all the work.

Yes, that’s possible: If I know of a publicly accessible, writable directory on your Web server, and you weren’t careful about securing it, I can make an upload form on my server that will actually store my files on your Web server. Thus, I steal all your bandwidth to distribute my files.

Rule 3: Use Intermediary Scripts Where Possible

The best defense against having your Web site upload application hijacked is to use intermediary scripts and keep all the parts out of the HTTP path.

For example, building on our non-public folder in Rule 1, we can easily create a script that handles serving the files contained therein. For example, in PHP, we can have a publicly accessible page accept a query string that contains the name of a file, try to locate said file in our non-public folder, and send it along to the user if it exists:

$path = "/home/user/13gfdo87gyi5/";

if($_GET['file'] == "") {
	die('You need to provide a file name.');
}
else {
	$file = $path . $_GET['file'];
	if(!file_exists($file)) {
		die('No such file exists.');
	}
	else {
		$type = "Content-type: " . mime_content_type($file);
		$size = "Content-Length: " . filesize($file);
		header($type);
		header($size);
		readfile($file);
	}
}

By using such scripts, you never expose the weak part of your site — the writable directory — to the public.

Rule 4: Monitor What People Are Uploading And Track Uploaders

Again, it is a huge mistake to not screen the files people are uploading to your Web site. And at the same time, you should make it transparent to users that they will be held accountable for what they upload.

I’d recommend that you have some sort of user account system in place before allowing someone to upload to your server. But at the very least, you should track the IP addresses of people uploading to your site; require some sort of CAPTCHA or similar humans-only screening method, and time-limit / bandwidth-limit each user so that he can’t overrun your server with files.

4 Comments

  1. Hello I saw this post has been created a long time ago, but i was wondering how i can do this:
    “Your Web host should provide you with the opportunity to create directories outside your public HTTP path. If you are going to have file uploads, you should create such a directory with a difficult-to-guess name, such as 13gfdo87gyi5.”
    And also, if i use a difficult name to guess like 13gfdo87gyi5, isnt this name will be available anyway when i display the picture uploaded?
    Thanks!

  2. @Karina: You would use a script to retrieve the image from wherever it is and render it onscreen, or you could store the image in a database.

    The point I am trying to make is this: That you are asking these kinds of questions suggest that you lack enough experience to protect your Web site from hackers. So you should use a canned solution, such as Gallery, or drop the idea of allowing public uploads.

  3. Doug,

    What canned solution do you recommend for the following application?

    => Public file upload from an upload form on my website via secure link to my account on dropbox.com
    => The upload form on my website asks for the name and email address of the uploading person (both are mandatory) and optional comments
    => The upload form has a ‘Browse’ button that can be used multiple times to locate a number of files that can be uploaded with a single click on the ‘Upload’ button. The files are small, the total size of the upload can be limited to 10 MB max.
    => Upon upload, the uploading person will see a ‘Thank You’ page, a confirmation email will be sent to the uploading person with a list of the uploaded files, and a notification email will be sent to me with the name, the email address, and any comments of the uploading person, and a list of the uploaded files.

    The files on dropbox.com will not be shared with anyone. The application resembles students submitting exam paper pages to their teacher for review. The application has to be secure, but only requires the above simple features.

    Thanks for any recommendations for a canned solution.

  4. @AdviceSeeker: As far as a canned solution goes, if what you need is collaboration — that is, the ability of many people to make many revisions to common documents — it makes the most sense to buy a Software As A Service (SAAS) solution, such as Google Apps for Business or Microsoft Office 365.

    Just buy a seat for every person who needs to work on your documents. The cost is $5 or $6 per user, per month, and believe me, it’s worth it. Unless you have an enormous organization, you will never realize a short-term savings over the cost of creating your own reliable solution, and will almost certainly never realize a long-term savings, either.

    If your need is one-way — that is, someone creates a document, sends it to you, and that’s the last they see of it — just have them email you the documents, and buy an unlimited-storage IMAP email service, such as GoDaddy sells for $3.50 a month.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  • Check out the Commenting Guidelines before commenting, please!
  • Want to share code? Please put it into a GitHub Gist, CodePen or pastebin and link to that in your comment.
  • Just have a line or two of markup? Wrap them in an appropriate SyntaxHighlighter Evolved shortcode for your programming language, please!