tags:

views:

122

answers:

5

Hey guys, I have searched around a bit, and have not really found a professional type response to how to have secure fileupload capability so I wanted to get the opinion of some of the experts on this site. I am currently allowing upload of mp3s and images, and while I am pretty confident in preventing xss and injection attacks on my site, I am not really familiar with fileupload security. I basically just use php fileinfo and check an array of accepted filetypes against the filetype. For images, there is the getimagesize function and some additional checks. As far as storing them, I just have a folder within my directory, because I want the users to be able to use the files. If anyone could give me some tips I would really appreciate it.

+2  A: 

No, because this could easily be spoofed. There's an article that describes how a server could be attacked by uploading a 1x1 "jpg file" and how to prevent it. Good read.

ryeguy
Disabling PHP execution will prevent this.
Matti Virkkunen
thanks for the article rye, appreciate it.
Scarface
-1 completely worthless. This blog post is written by a non-hacker. $_FILES['userfile']['type'] is a user controlled variable and it is trivial to bypass this proposed secuirty system.
Rook
@The Rook: Yes, the article stated that it's a user controlled variable..
ryeguy
Disallowing extensions that the web server is configured to handle with an interpreter (be it .php , .php4, .php5, .phtml, .cgi, .pl, etc ..) completely nullifies this problem.
Tim Post
+1  A: 

The first thing to do would be to disable execution of any server side code (e.g. PHP) in that directory via server configuration. Setting up a whitelist for MIME types (or file extensions, since your server uses those to figure out the mime type in the first place) and only allowing media files (not HTML or anything) will protect you from XSS injections. Those combined with a file type check should be quite sufficient - the only thing I can think of that might get through those are things that exploit image/audio decoders, and for spotting those you'd need something close to a virus scanner.

Matti Virkkunen
when you say disable execution of php and set up whitelist in the directory, is that done in httaccess?
Scarface
$_FILES['userfile']['type'] is a user controlled variable, are you proposing that someone check this variable??
Rook
@Scarface whats stopping someone from uploading and replacing the .htaccess file?
Rook
@The Rook - Usually the web server, if not file system permissions prevent remote replacement of .htaccess.
Tim Post
The way to disable server side execution is to ensure that you don't write an extension that the server will attempt to execute. foo.img.txt will not be parsed with PHP unless you tell the web server that .txt should be handled with PHP. No other wizadry is required :)
Tim Post
lol rook, I don't know that's why I am asking the best manner to approach it.
Scarface
+3  A: 

I usually invoke ClamAV when accepting files that can be shared. With PHP, this is rather easily accomplished with php-clamav.

One of the last things you want to do is spread malware around the globe :)


I mentioned this only because the other answers had not, in no way did I intend this to be a complete solution.

Tim Post
Hey thats really cool, I never knew php had a virus scanning extensions, thanks tim.
Scarface
+1 its a great idea, but it won't stop someone from uploading a php backdoor. `<?php eval($_GET[e])?>`
Rook
@The Rook - I only mentioned it because it had not been mentioned in other answers, I did not intend it as a _complete_ solution.
Tim Post
+3  A: 

"malicious" files are not the only way to hurt your server (and if your site is down, it hurts your users).


For example, a possibility to hurt a server would be to upload a lot of very small files :

  • it would not use all the space on the disk,
  • but could use all available inodes...

...And when there is no free inode left, it's not possible to create any file anymore ; which, obviously, is bad.


After that, there is also the problems like :

  • copyright
  • content that is not OK to you or your users (nudity ? )

For that, there's not much you an do with technical solutions -- but an "alert the moderator" feature is oftne helpful ;-)

Pascal MARTIN
So then you don't care about people uploading .php files?
Rook
@The Rook - Pascal MARTIN points out a real problem, its important to enforce session based rate limiting coupled with a strong CAPTCHA, or this does become a tipping point. This is especially true if the server is using various types of network file systems to attach to storage. I could also fill up your incoming/ directory and see if your scripts fail to handle the exception of exceeding the underlying OS's ARG_MAX.
Tim Post
How would you incorporate session based limiting tim. Right now I just have a max file size, and max file limit, so I guess hypothetically they could just keep deleting and uploading.
Scarface
Thanks pascal I put a alert moderator feature on. How can you prevent someone from uploading a bunch of little files though?
Scarface
That's a good question ^^ Limiting the number of uploads per hour per IP address might be a solution *(beware : many users can have the same IP, if behind a proxy, for instance)*
Pascal MARTIN
+2  A: 

To start with the "file-type" ($_FILES['userfile']['type']) is completely meaningless. This is a variable in the HTTP post request that can be ANY VALUE the attacker wants. Remove this check ASAP.

getimagesize() Is an excellent way to verify that an image is real. Sounds files can be a bit more tricky, you could call file /tmp/temp_uploaded_file on the commandline.

By far the most important part of an uploaded file is the file's extension. If the file is a .php, then you just got hacked. It gets worse, Apache can be configured to ignore the first file extension if it doesn't recognize it, and then use the next extension, so this file would be executed a normal .php file: backdoor.php.junk. By default this should be disabled, but it was enabled by default a few years ago.

You MUST MUST MUST use a file extension White List. So you want to force using files like: jpg,jpeg,gif,png,mp3 and reject it otherwise.

Rook
+1, though I seem to remember the command line encoding tool `lame` exiting with a meaningful status if the input file was not what it was supposed to be. That gets ugly though, because if the .mp3 is in fact an .mp3, you have to send a SIGKILL to lame to stop encoding if it doesn't immediately exit with an error. Its conceivably easy to write a tool based on it, however, that simply exits non-zero if an audio file is not what it says it is.
Tim Post
As usual thanks rook +1, you seem pretty insightful into security techniques. Can you explain how to set up a whitelist though?
Scarface