Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

So I have a client wants a photography site where users can upload their photos in response to photography competitions. Though technically this isn't a problem, I want to know the risks associated with allowing any user to be able to upload any image onto my server. I've got the feeling the risks are high...

I was thinking of using something like this http://www.w3schools.com/php/php_file_upload.asp

If I do let anonymous users upload files, how can I secure the directory the images (and potentially damaging files) will be uploaded into?

share|improve this question

migrated from serverfault.com Mar 19 '13 at 13:55

This question came from our site for professional system and network administrators.

    
Josh did a very good job of answering this question. security.stackexchange.com/a/32853/31943 I think one should also read the guide mentioned here: stackoverflow.com/a/7065880/181562 which is: blog.insicdesigns.com/2009/01/… –  CrandellWS Oct 14 '13 at 0:58

2 Answers 2

up vote 38 down vote accepted

The biggest concern is obviously that malicious users will upload things that are not images to your server. Specifically they might upload executable files or scripts which they will attempt to trick your server into executing.

One way to protect against this is to make sure that the files are not executable after you move_uploaded_file in PHP. This is as simple as using chmod() to set 644 permissions.

Note that a user can still upload PHP scripts or other scripts and trick Apache into executing them depending on your configuration.

To avoid this, call getimagesize() on the files after they are uploaded and determine what file type they are. Rename the files to a unique filename and use your own extension. That way, if a user uploads evil.jpg.php, your script will save that as 12345.jpg and it won't be executable. Better yet, your script will not even touch it as it will be an invalid JPEG.

I personally always rename uploaded images to either the current timestamp from time() or a UUID. This also helps prevent against very evil filenames (like someone trying to upload a file they've named ../../../../../../../../etc/passwd)

As further protection you can use what's sometimes known as an "Image Firewall". Basically this involves saving uploaded images to a directory which is outside the Document Root and displaying them via a PHP script which calls readfile() to display them. This might be a lot of work but is the safest option.

A secondary concern is users uploading too many files or files which are too large, consuming all the disk space available or filling the hosting user's quota. This can be managed within your software, including limiting the size of individual files, the amount of data one user can upload, the total size of all uploads, etc. Make sure the website admin user has a way to manage and delete these files.

Do not rely on any of the data in $_FILES. Many sites tell you to check the mime type of the file, either from $_FILES[0]['type'] or by checking the filename's extension. Do not do this. Everything under $_FILES with the exception of tmp_name can be manipulated by a malicious user. If you know you want images only call getimagesize as it actually reads image data and will know if the file is really an image.

Do not rely on checking the HTTP Referrer for any security. Many sites advise you to check to make sure that the referrer is your own site to ensure that the file is legitimate. This can easily be faked.

For further information, here are some good articles:

share|improve this answer
5  
Brilliant answer. –  Starkers Mar 19 '13 at 12:57
    
Nice answer, but now I want to look at the source for getimagesize() to see if I can subvert it :P –  lynks Mar 19 '13 at 15:03
1  
@lynks you probably can to some degree. But my point was it detects and returns the file and mime type of the image, and from that your code can save the file as .jpg, .png, .gif or reject it. On a properly configured Apache server, none of those file types will be executed as PHP / CGI scripts. Compare that to using the mime type from $_FILE which might be a lie, or trusting the filename sent from the client. –  Josh Mar 19 '13 at 15:47
1  
@lynks, have at it. –  Adnan Mar 19 '13 at 16:05
1  
@MikeWeller When you did so, do you remember what the filename was? I'd be willing to bet it was something.php.jpg or even worse, something.php. A properly configured Apache server will not execute PHP code inside a file which does not have .php in the name. –  Josh Mar 20 '13 at 16:57

Consult https://www.owasp.org/index.php/PHP_Security_Cheat_Sheet#File_uploads for some important tips.

getimagesize() can be tricked into running PHP code.

http://www.php.net/manual/en/features.file-upload.php has a user comment by CertaiN that provides a better alternative with finfo(FILEINFO_MIME_TYPE)

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.