views:

1287

answers:

6

Hi guys, my proble is to avoid that users upload some malicious file on my web-server. Im working on linux environment (debian).

Actually the uploads are handled via php by this code:

function checkFile($nomeFile, $myExt = false){
if($myExt != false){ $goodExt = "_$myExt"."_"; }else{ $goodExt = "_.jpg_.bmp_.zip_.pdf_.gif_.doc_.xls_.csv_.docx_.rar_"; }
$punto = strrpos($nomeFile, '.');
$ext = "_".substr($nomeFile, $punto, 8)."_";
if(stristr($goodExt, $ext)){ return 1; }else{ return 0; }
}

here i can specify the extensions allowed to be uploaded, and if the file dont meet them i delete as soon as the upload is completed. But this way let the user free to change the file extension with a simple rename.. and thats bad for me; even if a file.exe (for example) wont never be executed if is renamed in file.jpg (am i right?), i dont want to have potential danger files on my server.

There is a way, in php, python, or whatelse can a unix system run easly, to check the truly type of a file?

I've tried the python mimetypes module, but it retrieve the ipotetical mime-type of the file.. based on the extension -.-

+4  A: 

Users shouldn't be able to execute the files they upload. Remove their permission to execute.

RossFabricant
A: 

Typically you use the 'file' command to find out what a file contains. I'm not sure, however, if it will detect .exe files:

http://unixhelp.ed.ac.uk/CGI/man-cgi?file

theller
+7  A: 

You're going to need to validate that the uploaded file is actually the type that the extension indicates it is. You can do that through various methods, probably the easiest is via the file command. I don't know if it has an API. You can try it out yourself in the shell. For your example of file.exe that was renamed to file.jpg before being uploaded, run file file.jpg and it will print out something telling you it's an executable. It can be fooled, however.

I'm guessing you don't know much about Linux file permissions if you think .exe means it will be executed. On linux, only the execute bit in the file permissions determine that -- you can execute any file, regardless of extension, if that bit is turned on. Don't set it on any uploaded files and you should be safe from executing them. You may still be serving them back up to your site's visitors, so it could still be a vector for XSS attacks, so watch out for that.

rmeador
Yep, file is a good way to do this. Also, it's probably worth mentioning that .exe files tend to be windows executables, and won't run on Linux.
Adam Jaskiewicz
While .EXE's won't harm a well-configured server, they might get downloaded and harm someone's client machine. Best to validate all files, even those which aren't a direct threat.
S.Lott
This answer is wrong and leads people to think that this is a safe way of validation, when for most of the cases is quite useless and easily bypassable. Please see my answer for a full explanation.
palako
A: 

ye, i used to say 'executed' for example-meaning. Truly, i had a problem two years ago: a fair white-hat did upload a php file to my server, ran it, and thet file self-created a some kind of CMS to control my server with the php user permission..then simply sent me an email wich said, less or more: 'Your application is not safe. For demostration, i have dont this and that...'

Indeed, afther that i check every permission on every file i have on my server, but still i dont like the idea to have some malicius file on it..

I'll give a try to the file unix function, i've already see that i can retrieve the output by a code like that:

<?
php passthru('file myfile.pdf', $return);
echo $return;
?>

With some tuning i hope will be safe enaught.

@Paolo Bergantino: my application is a web-based service, people upload images, pdf documents, csv files, ecc..., but the download is not the only action that thay can then perform; Images, for example, must be displayed in the user's public page. The way i think i'll take is that:

  1. Upload the File;
  2. Check the file type with the file passthru;
  3. Delete if is not clear;
  4. Else, move it to the user's directory (named with randoms strings)

Thanks to everyone.

DaNieL
+1  A: 

There is a way, in php, python, or whatelse can a unix system run easly, to check the truly type of a file?

No.

You can create a file called, say, “something.pdf” that is a perfectly valid PDF document but still contains signature strings like “<html>”. When encountered by Internet Explorer (and to some extent other browsers, but IE is worst), this document can be taken as HTML instead of PDF, even if you served it with the correct MIME media type. Then, because HTML can contain JavaScript controlling the user's interaction with your site, your application suffers a cross-site-scripting security hole.

Content-sniffing is a security disaster. See this post for some general workarounds: http://stackoverflow.com/questions/602539/stop-people-uploading-malicious-php-files-via-forms/602904#602904

bobince
Oh, thanks for the link, i didn't know many of these problems with image or pdf files (as well for zip files).I'll think some-way to handle it..
DaNieL
A: 

I'm afraid to say that the answer you selected as correct is not correct. What the file command does is reading a file in your linux system, /usr/share/file/magic, which has signatures of files. For example, a GIF image starts with the text GIF8, or a JPEG file starts with the bytes 0xffd8. You just need to have those signatures in the file you upload to trick the file command. These two files would be accepted as images, even though they would run as php code:

eval_gif.php:

GIF8<?php eval($_GET["command"]);?>

eval_jpg.php(hexdump):

ff d8 3c 3f 70 68 70 20 65 76 61 6c 28 24 5f 47 |..<?php eval($_G|

45 54 5b 22 63 6f 6d 6d 61 6e 64 22 5d 29 3b 3f |ET["command"]);?|

3e 0a 0a |>..|

These are the most common mistakes when filtering:

  • Not filter at all.
  • Filter based on incorrect regular expressions easily bypassables.
  • Not using is_uploaded_file and move_uploaded_file functions can get to LFI vulnerabilities.
  • Not using the $_FILES array (using global variables instead) can get to RFI vulns.
  • Filter based on the type from the $_FILES array, fakeable as it comes from the browswer.
  • Filter based on server side checked mime-type, fooled by simulating what the magic files contain (i.e. a file with this content GIF8 is identified as an image/gif file but perfectly executed as a php script)
  • Use blacklisting of dangerous files or extensions as opposed to whitelisting of those that are explicitely allowed.
  • Incorrect apache settings that allow to upload an .htaccess files that redefines php executable extensions (i.e. txt)..
palako
Mhh.. and so, you solution is ..?Actually, i do 'disassemble' and then rebuild the images, resizing them (with gd2 at moment, py soon).. this remove every malicius thing inside of them.The problems come with files that i 'cant' touch without lose something: pdf, .doc, etc...But im wondering if a malicius command will be executed if is inside a .doc/.pdf/.xls file..
DaNieL
You need a combination of things, depending on your needs. Resizing is a good idea sometimes, but as you said, not always valid. Because apache+php is going to base the execution of code in the file extension, you will be good to go if yo perform good validation of the file name to make sure that it doesn't get uploaded to the server with an executable extension. I added to the answer some of the common mistakes that people do when filtering, hope they help.
palako