Steve P
Steve P

Reputation: 11

How To Perform Secure Image Upload Using MIME Instead Of Allowed File Types Which Detects Image Extension Only

I have written a php script which checks the image file for its extension, such as JPG, JPEG, PNG, GIF, uploaded through an HTML form.

Now comes my problem: anyone may upload any kind of file by giving it an extension of JPG, JPEG, PNG, GIF.

Can someone help me on that? One should strictly be able to upload only an image file and not any other file which carries just extension of Image file.

I tried hard... but failed... Here is the php script I have written CHECK MY FULL CODE I HAVE WRITTEN & ITS WORKING FINE BUT WHEN I CHANGE ANY FILE EXTENSION WITH IMAGE EXTENSION ITS ALLOWING UPLOAD ON SERVER WHICH IS NOT SERCURE PLEASE SEE THIS FULL CODE AND ADD SOLUTION , THIS WILL HELP OTHERS TOO -THANK YOU https://www.dropbox.com/s/prza75dyo7usjqy/secure%20image%20upload%20with%20checking%20extension.txt?dl=0

if (isset($_POST['submit']))

    $filename = $_FILES["file"]["name"];
    $file_basename = substr($filename, 0, strripos($filename, '.')); // get file extention
    $file_ext = substr($filename, strripos($filename, '.')); // get file name
    $filesize = $_FILES["file"]["size"];
    $allowed_file_types = array('.jpg','.png','.jpeg','.gif');  
    
    //instead of allowed file type i want to check image authenticity with MIME

    if (in_array($file_ext,$allowed_file_types) && ($filesize < 100000))
    
  

Upvotes: 1

Views: 881

Answers (2)

Evert
Evert

Reputation: 99561

The most secure way to check if something is really an image, is to open the file as an image and then re-generate it.

Things that are valid images can still carry loads of other information and sometimes can trick whatever is reading it. So the most safe thing is to take the pixels from the image, and regenerate it.

Extensions like fileinfo only check the first few bytes for a marker, but it's not 100% reliable. It might be good enough for you

Upvotes: 0

rugolinifr
rugolinifr

Reputation: 1281

You should use the fileinfo API, which makes you able to check a file MIME content-type by looking at its bytes, not its name.

An image MIME type always starts with image/, for example image/png.

$finfo = new finfo();
$mimeType = $finfo->file($_FILES['file']['tmp_name'], FILEINFO_MIME_TYPE);

$isImage = strpos($mimeType, 'image/') === 0;

If you want to be very restrictive on your allowed images, check the list of available MIME types.

Edit: be more specific

if (isset($_POST['submit'])) {
    $filename = $_FILES["file"]["tmp_name"];
    $filesize = $_FILES["file"]["size"];
    $allowed_file_types = array('image/jpeg','image/png','image/gif');
    $finfo = new finfo();
    $mimeType = $finfo->file($filename, FILEINFO_MIME_TYPE);
    $isImage = in_array($mimeType, $allowed_file_types);

    if ($isImage && $filesize < 100000) {

Upvotes: 2

Related Questions