Jump to content

Malicious image uploads?


jacko310592

Recommended Posts

...i read on a few forums that "getimagesize()" shouldn’t be trusted to validate image extensions as the image can be edited to show misleading information;  so, instead, before i allow any image file to be processed, i now check the file extension using the explode function and an array for valid file types (as follows)...

 

$imgInfo = explode('.', $_FILES['image']['name']);
$ext = strtolower($imgInfo[sizeof($imgInfo) - 1]);

$accepted = array('gif', 'jpg', 'jpeg', 'jpe', 'png');

if (in_array($ext, $accepted) && $_FILES["image"]["size"] <= 1048576) {

//Process image... (includes file being saved... NOT named as client named the file)

}
else {
echo 'Wrong file format!';
}

 

but i have a feeling that this will not fully protect me?..

 

..what about when images are called to display on a webpage... if the image still has "malicious" code within, will the browser run/display that, or will it ignore it as it has the extension of a real image?

 

thanks

Link to comment
Share on other sites

Only IE. An image file, in its first few bytes has the type,JFIF,PNG,JPEG,etc. That along with the file extension is good enough for all browsers but IE. Microsoft, in their great wisdom, goes even farther. it also checks the first 256 bytes and will determine the MIME type by that sometimes. So you hide some js in the start of the image along with say, PNG, then name the image xxx.gif and IE will treat the file as an html file and execute the js.

 

So you can examine the first few bytes and if the embedded type does not match the file extension you can treat it as bad.

 

 

HTH

Teamatomic

Link to comment
Share on other sites

bloody IE, when will it just die, then coding would so much easier for everyone.

 

thanks for your advise teamatomic,  will this following code protect me more then?...

 

 

$imgInfo = getimagesize($_FILES['image']['tmp_name']);	//Get image info

//--	Match to an image Ext
if ($imgInfo[2] == 1) {$MIMEext = "gif";}
elseif ($imgInfo[2] == 2) {$MIMEext = "jpeg";}
elseif ($imgInfo[2] == 3) {$MIMEext = "png";}
else {$MIMEext = "";}

//-- Get file ext from original file name
$extSplit = explode('.', $_FILES['image']['name']);
$ext = strtolower($extSplit [sizeof($extSplit) - 1]);

//--	Array of accepted file ext's
$accepted = array('gif', 'jpeg', 'jpg', 'jpe', 'png');
if (in_array($ext, $accepted) && filesize($_FILES["image"]["tmp_name"]) <= 1048576
&& ($ext == "gif" && $MIMEext == "gif")
|| ($ext == "jpeg" && $MIMEext == "jpeg" || $ext == "jpg" && $MIMEext == "jpeg" || $ext == "jpe" && $MIMEext == "jpeg")
|| ($ext == "png" && $MIMEext == "png")
&& filesize($_FILES["image"]["tmp_name"]) == $_FILES['image']['size']) {

//PROCESS IMAGE

}
else {

//BAD IMAGE

}

 

 

thanks (:

Link to comment
Share on other sites

If you wish to tackle that imaginary problem, Why not verify the binary itself?

class PNG_Reader
{
    private $_chunks;
    private $_fp;

    function __construct($file) {
        if (!file_exists($file)) {
            throw new Exception('File does not exist');
        }

        $this->_chunks = array ();

        // Open the file
        $this->_fp = fopen($file, 'r');

        if (!$this->_fp)
            throw new Exception('Unable to open file');

        // Read the magic bytes and verify
        $header = fread($this->_fp, ;

        if ($header != "\x89PNG\x0d\x0a\x1a\x0a")
            throw new Exception('Is not a valid PNG image');

        // Loop through the chunks. Byte 0-3 is length, Byte 4-7 is type
        $chunkHeader = fread($this->_fp, ;

        while ($chunkHeader) {
            // Extract length and type from binary data
            $chunk = @unpack('Nsize/a4type', $chunkHeader);

            // Store position into internal array
            if ($this->_chunks[$chunk['type']] === null)
                $this->_chunks[$chunk['type']] = array ();
            $this->_chunks[$chunk['type']][] = array (
                'offset' => ftell($this->_fp),
                'size' => $chunk['size']
            );

            // Skip to next chunk (over body and CRC)
            fseek($this->_fp, $chunk['size'] + 4, SEEK_CUR);

            // Read next chunk header
            $chunkHeader = fread($this->_fp, ;
        }
    }

    function __destruct() { fclose($this->_fp); }

    // Returns all chunks of said type
    public function get_chunks($type) {
        if ($this->_chunks[$type] === null)
            return null;

        $chunks = array ();

        foreach ($this->_chunks[$type] as $chunk) {
            if ($chunk['size'] > 0) {
                fseek($this->_fp, $chunk['offset'], SEEK_SET);
                $chunks[] = fread($this->_fp, $chunk['size']);
            } else {
                $chunks[] = '';
            }
        }

        return $chunks;
    }
}

 

Simple 'nough to do other extentions verifying off JP2000 EXIF/alpha-ret.

 

EDIT: Why does your code contain such redundancy?

Link to comment
Share on other sites

huh? imaginary?.. look around, this problem isnt uncommon, sites have been disrupted in the past by images consealing hidden code.

 

and i dont really know anything about the layout of binary, but il give it a look at, so thanks.

 

 

and what do you mean with "Why does your code contain such redundancy?"?

:shrug:

Link to comment
Share on other sites

and what do you mean with "Why does your code contain such redundancy?"?

:shrug:

 

You repeat the most redundant code, which does not help your.. "problem." Why not copy the image to another plane and save that? Obviously if it fails then it's not an image.

Link to comment
Share on other sites

oh, that was only a fast mock up, i realised i have some repeated/pointless code in there after posting.

 

what do you mean by "copy the image to another plane and save that"? is there some function you can direct me to look at to do this?... maybe some kind of GD function?

Link to comment
Share on other sites

oh, that was only a fast mock up, i realised i have some repeated/pointless code in there after posting.

 

what do you mean by "copy the image to another plane and save that"? is there some function you can direct me to look at to do this?... maybe some kind of GD function?

 

http://www.php.net/manual/en/ref.image.php

Why not look yourself? If you wake up you'd see you answered yourself long before. Why not read what some of the functions do.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.