Most of us would have come across the common solutions in PHP to check if the uploaded file is an image, you might have tried the usual way of checking the extensions and accepting the file to be a valid image, what if someone sinister uploaded a malicious script just by changing the extension of the file to .jpg or .gif ? . I bet most of us would have used the following to validate the image uploaded in PHP.
Check if uploaded image is valid with getimagesize( ) in PHP
$imagesizedata = getimagesize($file); if ($imagesizedata ) { //do something }
but PHP docs says not to use getimagesize( ) to check that a given file is a valid image. it’s true that getimagesize( ) returns an array with some random values for image height & width, when the given file is not a valid image.
Check if uploaded image is valid by checking the extensions
$type=$_FILES[ 'image' ][ 'type' ]; $extensions=array( 'image/jpeg', 'image/png', 'image/gif' ); if( in_array( $type, $extensions )){ //do something }
but here you are checking only the extensions, like I said earlier, anyone can rename a file with a different content into jpg or gif and upload them without any problem.
Check if uploaded image is valid with exif data and fileinfo in PHP
Now let’s try something to check if the given image is valid, but before going into the example, let me tell you, even the following functions in PHP will not validate an image correctly.
- finfo_file( )
- mime_content_type( )
- exif_imagetype( )
All the above functions will return the mime/image type for the given image, but they will fail as well if we upload a file after changing the extension or cheat with the first few bytes of image headers. Here is the example I was talking about. I have the following content in a file and saved it as motion.gif
GIF89a< <?php echo "Hello";
and used the following PHP code to check the validity of the image, you can see I have tried the four commonly recommended PHP functions to check if the given image is valid and each one of them failed.
<?php $finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type - all mimetype extension $filename = "motion.gif"; echo $filename . ": " . finfo_file( $finfo, $filename ) . "<br>"; echo $filename . ": " . mime_content_type( $filename ) . "<br>"; echo "exif: " . exif_imagetype( $filename ) . "<br>"; print_r( getimagesize( $filename ) ); finfo_close( $finfo );
this is the output of the above code
so all the above mentioned solutions to check if the uploaded files is a valid image will deceive us in the end, the only best solution is to use imagecreate function in PHP, we have separate functions for jpg, gif , png or to create image with the given string or content of the file. imagecreate function will return false when it fails to create an image with the given image file., so you can check if the given file is a valid jpg or gif or png.
here is the code I tried, to validate the uploaded image files.
<?php $filename = "motion.gif"; $error = ''; $type = exif_imagetype( $filename ); switch( $type ) { case 1: $isimage = @imagecreatefromgif( $filename ); $error .= ( !$isimage ) ? "extn - gif, but not a valid gif" : ' valid gif'; break; case 2: $isimage = @imagecreatefromjpeg( $filename ); $error .= ( !$isimage ) ? "extn - jpg, but not a valid jpg" : ' valid jpg'; break; case 3: echo "png : "; $isimage = @imagecreatefrompng( $filename ); $error .= ( !$isimage ) ? "extn - png, but not a valid png" : ' valid png'; break; default: //if there is no exif data $error .= "Not an image" ; } echo $error; ?>
You can experiment yourself with various images and cheating with the first few headers of jpg, gif or png.
Thanks.
Would be great if PHP team do something more sophisticated to validate imagens
Now we have imagewebp too
I will update the code soon