Do you know a method in PHP to check the type of an uploaded file
without relying on extension or Mime-type because these two can be faked?
Verifying the file type in PHP
Relying on the Mime-type of a file submitted by a user is a bad practice, using the extension is even worse!
Some people use functions of the php fileinfo extension, these functions do not rely on file extensions but do rely on bytes sections of the file that can be easily faked.
You can retrieve the mime type with finfo_file() like this:
$filename = "test.gif"
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$file_mime_type = finfo_file($finfo, $filename);
echo $file_mime_type; // Expected ouput: image/gif
So you can use the php fileinfo functions to determine if the file is what it claims to be, I mean that the file extension matches the result of finfo_file(), if it doesn’t, there is no need to go further, the file should be rejected from being stored on your server and from beig served to your website visitors.
If the extension matches the MIME type we will have to go further and check if the files is really a GIF/JPEG/ZIP file or a fake file with malicious code.
For that we need to have a set of functions for the MIME types we are interested in, for images for example (TIFF, PNG, GIF, JPEG…), there is a good function that uses the identify linux command, modify it to suit your needs
exec("/usr/bin/identify -format %m $fullpathtoimage",$out);
//using system() echos STDOUT automatically
//identify returns an empty result if the file is not an image
if($out === 'JPEG')
Original code written by Ryan Day
Since I do not use file uploads, I can not provide functions for other file types, but I will search for them and edit my post if I find any.
There’s another solution that should work for all types but I’m not sure about it, it uses the linux file command:
exec("/usr/bin/file -bi $fullpathtoimage",$out);
$mime_type = array_shift(explode(';',$out));
print_r(file_mime_type(__FILE__)); // Outputs: text/x-c++ which is ok