简体   繁体   中英

GetImageSize() not returning FALSE when it should

Working on a little upload script here. I'm trying to check if the uploaded image really is an image and not just a renamed PHP file.

When the script is posted I can print the array with

foreach ($_FILES['images']['name'] as $key => $value){             
        print_r(getimagesize($_FILES['images']['tmp_name'][$key]));

That works just fine, so it won't return false. But even if I upload a file that is not an image, it won't give false. It just returns nothing at all, and the rest of my script just processes the thing like an image.

Could anyone tell me what I am doing wrong?

Upload

you can not use getimagesize on $_FILES['images']['tmp_name'][$key] directly .. you need to copy it into your system first before you can use it

Use $_FILES['images']['size'][$key] temporarily

Or

  move_uploaded_file($_FILES['images']['tmp_name'][$key], $destination);
  print_r(getimagesize($destination));

Fake Image

Please not that $_FILES['images']['type'][$key] can be faked

Using Fake image Headers

Example

file_put_contents("fake.png", base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAABGdBTUEAALGPC/xhBQAAAAZQTFRF////
AAAAVcLTfgAAAAF0Uk5TAEDm2GYAAAABYktHRACIBR1IAAAACXBIWXMAAAsSAAALEgHS3X78AAAAB3RJTUUH0gQCEx05cq
KA8gAAAApJREFUeJxjYAAAAAIAAUivpHEAAAAASUVORK5CYII='));

Uploading fake.png

array
  'name' => 
    array
      0 => string 'fake.png' (length=8)
  'type' => 
    array
      0 => string 'image/png' (length=9)
  'tmp_name' => 
    array
      0 => string 'C:\Apache\xampp\tmp\php44F.tmp' (length=30)
  'error' => 
    array
      0 => int 0
  'size' => 
    array
      0 => int 167

Validate Image

Usage

var_dump ( getimagesizeReal ( "fake.png" ) );

Function Used

function getimagesizeReal($image) {

    $imageTypes = array (
            IMAGETYPE_GIF,
            IMAGETYPE_JPEG,
            IMAGETYPE_PNG,
            IMAGETYPE_SWF,
            IMAGETYPE_PSD,
            IMAGETYPE_BMP,
            IMAGETYPE_TIFF_II,
            IMAGETYPE_TIFF_MM,
            IMAGETYPE_JPC,
            IMAGETYPE_JP2,
            IMAGETYPE_JPX,
            IMAGETYPE_JB2,
            IMAGETYPE_SWC,
            IMAGETYPE_IFF,
            IMAGETYPE_WBMP,
            IMAGETYPE_XBM,
            IMAGETYPE_ICO 
    );
    $info = getimagesize ( $image );
    $width = @$info [0];
    $height = @$info [1];
    $type = @$info [2];
    $attr = @$info [3];
    $bits = @$info ['bits'];
    $channels = @$info ['channels'];
    $mime = @$info ['mime'];

    if (! in_array ( $type, $imageTypes )) {
        return false; // Invalid Image Type ;
    }
    if ($width <= 1 && $height <= 1) {
        return false; // Invalid Image Size ;
    }

    if($bits === 1)
    {
        return false; // One Bit Image .. You don't want that  ;
    }
    return $info ;
}

Firstly, you can use getimagesize on $_FILES['images']['tmp_name'], so that's not an issue.

If you want to check if the file is an image, then try this:

if(isset($_POST['submit'])) {
    $check = getimagesize($_FILES['images']['tmp_name']);
    if($check !== false) {
        echo 'File is an image - ' . $check['mime'];
    }
    else {
        echo 'File is not an image';
    }
}

I'd like to recommend against trusting the results of getimagesize() when deciding whether to place the uploaded file anywhere in your document root. That's because PHP code embedded in GIF files (titled like image.gif.php ) will be identified as images by getimagesize() , but serving them will run the PHP code inside them in addition to displaying the image. Here is some more information on the issue.

The article linked above recommends setting up a separate controller through which all the user uploaded files are served. Files read with readfile() are not parsed when accessed through the local filesystem.

You can simply use $_FILES['images']['type'] . it'll give you the type of file uploaded. Then check it againt octate stream or other executable file. If so then do not allow it.

@user1362916 If you are uploading multiple images with HTML then perhaps you need to add one more array like this.

if(isset($_POST['submit'])) {
    $check = getimagesize($_FILES['images']['tmp_name'][$i]);
    if($check !== false) {
        echo 'File is an image - ' . $check['mime'];
    }
    else {
        echo 'File is not an image';
    }
}

Here check [i] because this is for multiple file upload.

Below is full script

<!DOCTYPE html>
<html>
<body>

<form action="#" method="post" enctype="multipart/form-data">
    Select image to upload:
    <input name="my_files[]" type="file" multiple="multiple" />
    <input type="submit" value="Upload Image" name="submit">
</form>


<?php

 if (isset($_FILES['my_files']))
 {
    $myFile = $_FILES['my_files'];
    $fileCount = count($myFile["name"]);


        for ($i = 0; $i <$fileCount; $i++)
         {
           $error = $myFile["error"][$i]; 

            if ($error == '4')  // error 4 is for "no file selected"
             {
               echo "no file selected";
             }
            else
             {
               if(isset($_POST['submit'])) {
                 $check = getimagesize($_FILES['my_files']['tmp_name'][$i]);
                 if($check !== false) {
                 echo 'File is an image - ' . $check['mime'];
                 }
                 else {
                 echo 'File is not an image';
                   }
                 }

             }
       }  
 }
        ?>


</body>
</html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM