Validate an image in PHP - php

I'm using GD to create jpegs from files that a user uploads.
What is the best way to validate that the image the user has uploaded is valid?
By valid I mean that the file is not a corrupt image that GD won't like, I do extension testing client side so they can only upload jpegs/gifs/pngs.
Thanks

You could use getimagesize. It will return FALSE if the image could not be loaded. It has support for most image types.

getImageSize would be your best choice but, be careful, if the file results are not valid you will get a warning. Using # before built in imagesize function will be ideal.

Related

PHP secure file upload

I have an upload form which allowed most of file types to be uploaded.
Here they are:
Image: jpg/jpeg/png/gif ...
Video: mp4/avi/wmv ...
another files: doc/pdf/rar/zip/mp3/...
For image file, I know I can use PHP function getimagesize() or something else to make sure it's the real image. But how about the other files such as Video, and documentation ? Is it a real file without faking the extension ?
How to do that?
Thank you! I need your help.
every file has it's own type, it called mime type , so u can check the mime type , do some things like that :
if (mime_content_type($FILES['file']['tmp'])== "image/png"))
{
// do upload
}else{
die('file type not supported');}
u can put all the mime type into an array the check the type with in_array function
u can find all the mime type here : http://www.freeformatter.com/mime-types-list.html
Any client-side check (even the browser mime-type detection) is doomed to fail because user has access to it. You'd better let the upload begin and complete, then perform a serious server side check. You simply discard the file if that is not what you expected to be.
On top of the server-side check you can of course implement the client-side check just for a neater user experience
The only way to fully secure a file upload is to attempt parsing the uploaded file with PHP or some other extension/tool that expects a specific valid file type. In other words:
Images: use GD functions to parse the file, they'll return false if it isn't a valid image.
Videos: could probably validate using ffmpeg on the command line and check the output or use the ID3 extension as suggested here: https://stackoverflow.com/a/134893 (credit to Zathrus Writer's comment on the question linking to this question)
Documents: Attempt loading the file with PHPExcel/Word/PowerPoint although I'm not sure that these would support just any format of those documents as it works on OpenXML.
From looking at the getID3 extension this might be the best bet as it seems to parse a wide variety of content types.
In any case, what you essentially need is for PHP or some other 3rd party library/extension to determine that the binary data of a file corresponds with its MIME content type.
Hope this helps :)

Can phpthumb generate interlaced images for progressive browser display?

Is it possible to generate interlaced images using phpthumb? Even if phpthumb doesn't generate interlaced images is there a safe walk-around that can be used to achieve this on a webapp that uses phpthumb for image processing?
I tried finding out if phpthumb has this feature and all i could come up with was this configuration directive in phpThumb.config.php file:
$PHPTHUMB_CONFIG['output_interlace'] = true; // if true: interlaced output for GIF/PNG, progressive output for JPEG; if false: non-interlaced for GIF/PNG, baseline for JPEG.
I set mine to true and it is still not generating interlaced images.
I was wondering this myself and checking the phpthumb source looks like for the GD library it is only doing the interlacing when (1) calling the OutputThumbnail() method and (2) when using ImageMagick, the ImageMagickThumbnailToGD() method. Which won't get called as far as I can tell when your using the class and calling GenerateThumbnail()
A patch has been pushed to fix this - Now both OutputThumbnail and RenderToFile will generate a properly interlaced JPEG if the setting was enabled (true)

Image upload security - reprocess with GD

I've heard that the best way to handle uploaded images is to "re-process" them using the GD library and save the processed image. see: PHP image upload security check list
My question is how do this "re-processing" in GD? What this means exactly? I don't know the GD library very well and I'm afraid I will mess it up...
So if anyone who did this before could you give me an example for this?
(I know, another other option is to use ImageMagick. For ImageMagick I found an answer here: Remove EXIF data from JPG using PHP, but I can't use ImgMagick now. By the way.. removing EXIF data means completely recreate the image in this case?)
(I'm using Zend Framework if someone interested.)
If the user uploads a JPEG file, you could do something like this to reprocess it:
$newIm = #imagecreatefromjpeg($_FILES['file']['tmp_name']);
if (!$newIm) {
// gd could not create an image from the source
// most likely, the file was not a valid jpeg image
}
You could then discard the $newIm image using imagedestroy() and use the uploaded file from the user, or save out the image from GD and use that. There could be some issues with saving the GD image as it is not the original image.
Another simple method would be to check the header (first several bytes) of the image file to make sure it is correct; for example all JPEG files begin with 0xff 0xd8.
See also imagecreatefromstring(), and you can also use getimagesize() to run similar checks on the uploaded image.
function isvalidjpeg($file)
{
$finfo = finfo_open(FILEINFO_MIME_TYPE);
return is_resource($finfo) &&
(finfo_file($finfo, $file) === 'image/jpeg') &&
finfo_close($finfo);
}
if(isvalidjpeg($_FILES['file']['tmp_name'])) {
$newIm = #imagecreatefromjpeg($_FILES['file']['tmp_name']); .....

PHP GD Library and uploaded files

I'm working on a project where I upload an image (jpg) and manipulate it using the PHP GD library.
I know that I can use GD functions to edit an image resource (created from imagecreatefromjpeg()) but I was wondering if there was a way I could use the file uploaded in the $_FILES array directly with the GD library. One solution I thought of was saving the uploaded file, pushing it into imagecreatefromjpeg, then deleting it afterwards.
This seems cluinky though, is there a more efficient solution?
I'm still a bit new to PHP so I'm not sure as to how files are stored in the $_FILES array. I hope I'm making sense here. Thanks.
You can simply do this:
$img = imagecreatefromjpeg($_FILES['image']['tmp_name']);
// do gd operations on $img
imagejpeg($img, '/path/to/target');
You'll have to use imagecreatefrom in some form or another, and you can use it directly on the uploaded file. Then just save the result of your manipulations using imagejpeg. The uploaded file in tmp_name will we thrown away automatically.
Having said that, you should save the original somewhere. It's always good to have it around for later use.

Secure User Image Upload Capabilities in PHP

I'm implementing a user-based image uploading tool for my website. The system should allow any users to upload JPEG and PNG files only. I'm, of course, worried about security and so I'm wondering how the many smarter people than myself feel about the following checks for allowing uploads:
1) First white list the allowable file extensions in PHP to allow only PNG, png, jpg, JPG and JPEG. Retrieve the user's file's extension via a function such as:
return end(explode(".", $filename));
This should help disallow the user from uploading something malicious like .png.php. If this passes, move to step 2.
2) Run the php function getimageize() on the TMP file. Via something like:
getimagesize($_FILES['userfile']['tmp_name']);
If this does not return false, proceed.
3) Ensure a .htaccess file is placed within the uploads directory so that any files within this directory cannot parse PHP files:
php_admin_value engine Off
4) Rename the user's file to something pre-determined. I.E.
$filename = 'some_pre_determined_unique_value' . $the_file_extension;
This will also help prevent SQL injection as the filename will be the only user-determined variable in any queries used.
If I perform the above, how vulnerable for attack am I still? Before accepting a file I should hopefully have 1) only allowed jpgs and pngs, 2) Verified that PHP says it's a valid image, 3) disabled the directory the images are in from executing .php files and 4) renamed the users file to something unique.
Thanks,
Regarding file names, random names are definitely a good idea and take away a lot of headaches.
If you want to make totally sure the content is clean, consider using GD or ImageMagick to copy the incoming image 1:1 into a new, empty one.
That will slightly diminish image quality because content gets compressed twice, but it will remove any EXIF information present in the original image. Users are often not even aware how much info gets put into the Metadata section of JPG files! Camera info, position, times, software used... It's good policy for sites that host images to remove that info for the user.
Also, copying the image will probably get rid of most exploits that use faulty image data to cause overflows in the viewer software, and inject malicious code. Such manipulated images will probably simply turn out unreadable for GD.
Regarding your number 2), don't just check for FALSE. getimagesize will also return the mime type of the image. This is by far a more secure way to check proper image type than looking at the mime type the client supplies:
$info = getimagesize($_FILES['userfile']['tmp_name']);
if ($info === FALSE) {
die("Couldn't read image");
}
if (($info[2] !== IMAGETYPE_PNG) && ($info[2] !== IMAGETYPE_JPEG)) {
die("Not a JPEG or PNG");
}
All the checks seem good, number 3 in particular. If performance is not an issue, or you are doing this in the background, you could try accessing the image using GD and seeing if it is indeed an image and not just a bunch of crap that someone is trying to fill your server with.
Concerning No. 2, I read on php.net (documentation of the function getimagesize() ):
Do not use getimagesize() to check that a given file is a valid image. Use a purpose-built solution such as the Fileinfo extension instead.

Categories