Attackers can disguise malicious scripts (such as PHP code) as images for upload. For example, a script containing a PHP backdoor can be named .jpg or .png and uploaded. If the exif_imagetype() function is not used to detect the actual file type, image_type_to_extension() may incorrectly return a valid extension, misleading subsequent logic and potentially storing it in an executable directory:
$filename = $_FILES['image']['tmp_name'];
$ext = image_type_to_extension(@exif_imagetype($filename));
// Incorrect usage: No check if exif_imagetype() returns false
$newName = uniqid() . $ext;
move_uploaded_file($filename, "/var/www/html/uploads/" . $newName);
If the uploaded file is not a real image, for example, a fake PHP script with a .jpg extension, the attacker could execute malicious code by accessing http://m66.net/uploads/xxxx.jpg.
When exif_imagetype() cannot recognize the file type, it returns false. If this result is passed to image_type_to_extension(), it will return .int(0), causing confusion in the generated filename and potentially causing logical errors. For example:
$type = exif_imagetype($filename);
$ext = image_type_to_extension($type);
// If $type is false, $ext will be "."
This could lead the program to use an incorrect file extension, disrupting subsequent operations and potentially causing resource leakage.
In some server environments, if PHP does not have the fileinfo or exif extension enabled, exif_imagetype() will fail. Relying on its results and passing them to image_type_to_extension() can cause the program to crash or process logic errors, affecting the user experience.
Some services deploy security policies based on file extensions, such as allowing only .jpg or .png files to be accessed. If an attacker spoofs the file name and bypasses the backend check, the server may mistakenly grant access.
For example, a file named .php.jpg could be uploaded, but its real format is PHP. Under certain configurations, Nginx might recognize it as a .php file and execute it, leading to severe consequences:
<?php echo shell_exec($_GET['cmd']); ?>
Then, by accessing:
http://m66.net/uploads/backdoor.php.jpg?cmd=ls
the attacker could remotely control the server.
To avoid the above risks, the following measures should be taken:
Use exif_imagetype() and check if the return value is false
Use finfo_file() to further validate MIME types
Ensure upload directories are non-executable
Do not trust user-submitted file extensions
Use a whitelist to validate image_type_to_extension() results
Example Code:
$filename = $_FILES['image']['tmp_name'];
$imageType = @exif_imagetype($filename);
<p>if ($imageType === false) {<br>
die('Unsupported image format');<br>
}</p>
<p>$ext = image_type_to_extension($imageType, false);<br>
$allowed = ['jpg', 'jpeg', 'png', 'gif'];</p>
<p>if (!in_array($ext, $allowed)) {<br>
die('Disallowed image type');<br>
}</p>
<p data-is-last-node="" data-is-only-node="">$newName = uniqid() . '.' . $ext;<br>
move_uploaded_file($filename, '/var/www/uploads/' . $newName);<br>