How can I verify that the remote image uploaded to the server is actually a PHP image?

I am creating a PHP application that will be distributed to hundreds or thousands of users as a SugarCRM module. The functionality I'm working with allows users to download images from a remote url.

StackOverflow has the same functionality as in the image below.

I mention this on other servers because my upload function needs to be very reliable in many server and web host configurations!

To make it more reliable when fetching and loading remote images, I have some checks in my function fetch_image($image_url)

, like ...

ini_get('allow_url_fopen')

to make sure they allow you to file_get_contents()

use URLs instead of file paths.

I am using function_exists('curl_init')

to see if CURL is installed.

Besides getting a remote image using several methods. Now I also need to verify that the file returned or generated from the remote server is actually a legitimate image file and not some malicious file!

Most servers at least have it installed GD image processor

, maybe it can be used in some way on my image to make sure it's an image?

My code so far is below ...

Any help appreciated in making sure the image is the image!

The socket method seems to actually create a file stored in the server's temp folder. Other methods simply return an image string.

<?php

class GrabAndSave {

    public $imageName;
    public $imageFolderPath = 'remote-uploads/'; // Folder to Cache Amazon Images in
    public $remote_image_url;
    public $local_image_url;
    public $temp_file  = '';
    public $temp_file_prefix = 'tmp';

    public function __construct(){
        //
    }

    public function fetch_image($image_url) {

        // check if CURL is installed
        if (function_exists('curl_init')){
            return $this->curl_fetch_image($image_url);
        // Check if PHP allows file_get_contents to use URL instead of file paths
        }elseif(ini_get('allow_url_fopen')){
            return $this->fopen_fetch_image($image_url);
        // Try Sockets
        }else{
            return $this->sockets_fetch_image($image_url);
        }
    }



    public function curl_fetch_image($image_url) {

        if (function_exists('curl_init')) {
             //Initialize a new resource for curl
             $ch = curl_init();

             //Set the url the retrieve
             curl_setopt($ch, CURLOPT_URL, $image_url);

             //Return the value instead of outputting to the browser
             curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

             $image = curl_exec($ch);
             curl_close($ch);

             if ($image) {
                  //Do stuff with the image
                  return $image;
             } else {
                  //Show error message
             }

        }else{
            die('cURL is not enabled on this server.');
        }
    }


    public function fopen_fetch_image($url) {
        $image = file_get_contents($url, false, $context);
        return $image;
    }


    public function sockets_fetch_image($image_url)
    {
        if($this->temp_file)
        {
            throw new Exception('Resource has been downloaded already.');
        }

        $this->temp_file = tempnam(sys_get_temp_dir(), $this->temp_file_prefix);

        $srcResource = fopen($image_url, 'r');
        $destResource = fopen($this->temp_file, 'w+');

        stream_copy_to_stream($srcResource, $destResource);

        return $this->temp_file;
    }


    public function save_image($image_filename, $raw_image_string){
            $local_image_file = fopen($this->imageFolderPath . $image_filename, 'w+');
            chmod($this->imageFolderPath . $image_filename, 0755);
            fwrite($local_image_file, $raw_image_string);
            fclose($local_image_file);
    }

}

      


StackOverflow Image Dialog Preview Using Remote URL Load ...
enter image description here

+3


source to share


2 answers


A simple and effective method uses getimagesize

the file. A valid file will provide an array of image metadata for many types of generic image files. (This can, incidentally, also be used to provide additional constraints such as image dimensions.)



Be aware that even legitimate images can contain malicious code as various image viewers have encountered security issues with image data streams in the past. It can add a layer of security to internally transform an image before delivery to protect customers.

+1


source


You can



  • check response headers, especially Content-Type header
  • check file type mime
  • verify a valid file signature
  • try to create an image resource from a file
  • other...
0


source







All Articles