How to prevent every malicious file upload on my server? (check file type)?

16,089

Solution 1

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.

Solution 2

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 bypassable.
  • 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 browser.
  • 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)..

Solution 3

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

Solution 4

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: Stop people uploading malicious PHP files via forms

Solution 5

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

Share:
16,089
Strae
Author by

Strae

I can accept failure, everyone fails at something - But I can't accept not trying. -- You HAVE to assume your visitor is a maniac serial killer, out to destroy your application. And you have to prevent it. Hire me

Updated on June 29, 2022

Comments

  • Strae
    Strae almost 2 years

    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 -.-

  • user1066101
    user1066101 about 15 years
    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.
  • Strae
    Strae about 15 years
    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..
  • Strae
    Strae about 15 years
    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..
  • palako
    palako about 15 years
    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
    palako about 15 years
    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.
  • Christian
    Christian about 13 years
    This has been popularized to a certain extent with the GIFAR issue: infoworld.com/d/security-central/…
  • Christian
    Christian about 13 years
    Don't know why this answer didn't get much replies/points, but it's a great and informative response, more than the novice file <filename> "solutions".
  • Freeman Lambda
    Freeman Lambda almost 11 years
    Great answer palako, it cleared out the question I was going to ask in SO. Thanks +1
  • palako
    palako over 7 years
    Malicious files don't need to be executable to be harmful. A PHP file just need to be readable by the server process to be "executed".