How to check if image has no code injected?

If you let images with code injection be saved on your server, it is possible, that it's a highwayto your php files and whole database, so it is important to make sure, that if user uploads avatar, it is really an avatar, not some hacky stuff with code injected into the image.

If you will try to get mime type of the file, that is not good solution, because it is possible to insert headers to the file and your functions will think, that it is an image even with php code inside.
getimagesize() is not good solution too, because it may not fail on images with injected code, it will give you sizes and stuff as it would be normal image.

Solution

The only good solution i've found so far is this little peace of code:

$file = 'uploaded_file.gif';
try{
    $im = new Imagick($file);
    $im->scaleImage(0, 300); // try to resize
    unset($im);
} catch (Exception $e){
    echo 'File is NOT OK. '.$e->getMessage();
    exit;
}

Exception message would look like:

File is NOT OK. `uploaded_file.gif' @ error/gif.c/ReadGIFImage/1333


Requirements 

 This solution will require ImageMagick available on your server. On ubuntu you can try instaling it by this command: sudo apt-get install php5-imagick

Extra tips 

If you are thinking abuot resizeimage, I haven't tried it, it might work OK, but according to comments on http://php.net/manual/en/imagick.resizeimage.php scaleImage requires less CPU juices.

In our linux environment, using resizeImage with any filter produced extremely high CPU Utilization (in the range of 40-50%) while doing batch resizing.
We switched to scaleImage, which produces similar results to FILTER_BOX, and CPU Utilization dropped to 2-3%. 
Using XHProf to profile the two batch jobs showed amazing decreases in CPU Time, so if you're doing a lot of picture resizing, it might be beneficial to use scaleImage instead of resizeImage, as it seems to be much much more efficient.

No comments:

Post a Comment

You can ask IT questions in comments!