0

On my website I allow users to upload an image using the following...

$max_filesize = 1572864; // 1.5MB
$upload_path = 'uploads'; 
$upload_path = $upload_path.'/';

$filename = $_FILES['profile_image']['name']; 


if(filesize($_FILES['profile_image']['tmp_name']) > $max_filesize)
      die('The file you attempted to upload is too large.'); 
if(!is_writable($upload_path))
      die('permission errorrr!'); 

if(move_uploaded_file($_FILES['profile_image']['tmp_name'],$upload_path . $filename)){
    // TA DA!
}

Im just after some input on how secure this, and how it can be made even more secure, I ask as Ive manage to change a file a .png file to .jpg and upload it, so in theory could a .exe be renamed and uploaded, and if so how can this be countered?

Liam
  • 9,725
  • 39
  • 111
  • 209
  • Check the mime type of the file (http://php.net/manual/es/function.mime-content-type.php) also check this http://stackoverflow.com/questions/4166762/php-image-upload-security-check-list?rq=1 – Xavi Jun 05 '13 at 11:42
  • Is your server configured to execute `.jpg` files? – Álvaro González Jun 05 '13 at 11:48

6 Answers6

2

Mime types cannot be trusted, and so, as @yoeriboven said, you can use:

if (!getimagesize($_FILES['profile_image']['tmp_name'])){
    die('Not an image');
}

but you can also not allow execution of any files uploaded to your uploads folder. You can do this with .htaccess (assuming you're using Apache) by doing:

AddHandler cgi-script .php .pl .py .jsp .asp .htm .shtml .sh .cgi
Options -ExecCGI

Another little additional thing you can do, just to help users, is to use HTML5's accept attribute:

<input type="file" name="file" accept="image/gif, image/jpeg" />

(obviously the above can be changed client side so it's not to be relied on)

Prisoner
  • 27,391
  • 11
  • 73
  • 102
2

You can first check file extensions, but some people may try to falsify it so :

ForceType application/octet-stream
<FilesMatch "(?i)\.jpe?g$">
    ForceType image/jpeg
</FilesMatch>
<FilesMatch "(?i)\.gif$">
    ForceType image/gif
</FilesMatch>
<FilesMatch "(?i)\.png$">
    ForceType image/png
</FilesMatch>

This code, placed in the .htaccess file in your upload directory will only allow images to be associated with their default handlers. Everything else will be served as a plain byte stream and no handlers will be run. (Check this article [1])

Imane Fateh
  • 2,418
  • 3
  • 19
  • 23
1

i think .exe file can not be renamed. else it will become corrupted file so it is not advisable to rename the .exe file and in php file upload the data goes using post method so data is not visible hence it is secure.

Sagar Rabadiya
  • 4,126
  • 1
  • 21
  • 27
1

You could use this for example. It will return false if it is not an image:

if (!getimagesize($_FILES['profile_image']['tmp_name'])){
    die('Not an image');
}
yoeriboven
  • 3,541
  • 3
  • 25
  • 40
1

Your concern here is not that exe can be uploaded (because there are way to go around any security, even MIME) but can this exe later on be executed (just uploading an exe file doesn't execute it, it will simply lay there)?

But if you want to secure it, i suggest reading up on MIME types and go by it. Enforcing an extension of file is also a way (so a MIME image/png will be changed so the extension will be .png instead of anything put there by user).

Tymoteusz Paul
  • 2,732
  • 17
  • 20
0

Here is my function that I used some while ago for my image uploader. It will check the magic number of the jpeg file and return true or false.

function checkMagicNumberJPEG ($filename) {
    // Open file and read first 2 btytes
    $file = fopen($filename, 'r');
    $contents = fread($file, 2);

    $ascii = '';

    // Convert to hex
    for ($i = 0; $i < strlen($contents); $i++) { 
        $ascii .= dechex(ord($contents[$i])); 
    }

    // Close file
    fclose($file);

    // Check magic number
    if($ascii == 'ffd8') {
        return true;
    } else {
        return false;
    }
}
PBurggraf
  • 475
  • 6
  • 11