 |
|
|
09-02-2007, 06:31 PM
|
|
#1
|
 |
|
Lord (Level 16)
Join Date: Feb 2006
Location: Houston, Texas
Posts: 719
|
How to Verify File is an Image...
Ok, I've built this PHP script which takes a image (from url) and resizes it (makes a thumbnail) to a specified size (Example pasted to bottom of this post). I have used is_numeric to verify that $size is a number, and not some weird hack or whatever. But i am having difficulties verifying the $src is an actual image, instead of a file with maliscious PHP code for example.
As my script works now is if $size is a number, it resizes to that number. If its not a number, or is null, the no resizing takes place and the normal image gets displayed. this works brilliantly how I wanted it to. However, if I was to feed the script a file thats not an image (haven't actually tried feeding it code yet, but it scares me) and the script breaks, and starts throwing out all sorts of warnings/errors that give away a lot of details of the script, which could potentially be used in a hacking attempt.
What I am looking for is a safe way to check this $src to see if its actually an image (gif, jpg, or png) and if its not, error out safely (a single custom error). I have tried checking the mime of the $src which works beautifully if the image is in fact an image, but it was brought to my attention that mime's can be faked.
So here I am asking for some advice on how to verify that $src is actually an image, safely.
Here is my current code:
PHP Code:
<? $src = @$_GET['src']; $size = @$_GET['size']; $data = getimagesize($src); if (is_numeric($size)) { if ($data[1] > $data[0]) { $new_w = ($size / $data[1]) * $data[0]; $new_h = $size; } else { $new_h = ($size / $data[0]) * $data[1]; $new_w = $size; } } else { $new_h = $data[1]; $new_w = $data[0]; } $im2 = imagecreatetruecolor($new_w, $new_h); switch ($data['mime']) { case "image/gif": $image = imagecreatefromgif($src); break; case "image/jpeg": $image = imagecreatefromjpeg($src); break; case "image/png": $image = imagecreatefrompng($src); break; default: trigger_error('Not an image, or image type not acceptable!', E_USER_WARNING); break; } imagecopyresampled ($im2, $image, 0, 0, 0, 0, $new_w, $new_h, $data[0], $data[1]); header("Content-type: ".$data['mime']); switch ($data['mime']) { case "image/gif": imagegif($im2); break; case "image/jpeg": imagejpeg($im2); break; case "image/png": imagepng($im2); break; default: trigger_error('Not an image, or image type not acceptable!', E_USER_WARNING); break; } ?>
To see a live example with this image resized to 150, here is the url:
http://houston.pl3x.net/forums/func/...0.png&size=150
__________________
-Billy
"Traditional software is like witchcraft. In history, witchcraft just died out. The same will happen in software. When problems get serious enough, you can't have one person or one company guarding their secrets. You have to have everybody share in knowledge." --- Linus Torvalds
I am using Linux every day to up my productivity - so up yours!
Last edited by BillyGalbreath : 09-02-2007 at 06:55 PM.
Reason: fixed url
|
|
Add to del.icio.us
Can you digg it?
|
|
|
09-02-2007, 06:41 PM
|
|
#2
|
 |
|
Lord (Level 16)
Join Date: Feb 2006
Location: Houston, Texas
Posts: 719
|
Update!
This seems to have done the trick, for now. If anyone has anything else to add/suggest, please don't hesitate! I am trying to get this as secure as possible!
PHP Code:
<? $src = @$_GET['src']; $size = @$_GET['size']; $data = getimagesize($src); switch ($data['mime']) { case "image/gif": $image = imagecreatefromgif($src); break; case "image/jpeg": $image = imagecreatefromjpeg($src); break; case "image/png": $image = imagecreatefrompng($src); break; default: die("<strong>Error:</strong> Not an image, or image type not acceptable!"); exit; break; } if (is_numeric($size)) { if ($data[1] > $data[0]) { $new_w = ($size / $data[1]) * $data[0]; $new_h = $size; } else { $new_h = ($size / $data[0]) * $data[1]; $new_w = $size; } } else { $new_h = $data[1]; $new_w = $data[0]; } $im2 = imagecreatetruecolor($new_w, $new_h); imagecopyresampled ($im2, $image, 0, 0, 0, 0, $new_w, $new_h, $data[0], $data[1]); header("Content-type: ".$data['mime']); switch ($data['mime']) { case "image/gif": imagegif($im2); break; case "image/jpeg": imagejpeg($im2); break; case "image/png": imagepng($im2); break; default: die("<strong>Error:</strong> Not an image, or image type not acceptable!"); exit; break; } ?>
__________________
-Billy
"Traditional software is like witchcraft. In history, witchcraft just died out. The same will happen in software. When problems get serious enough, you can't have one person or one company guarding their secrets. You have to have everybody share in knowledge." --- Linus Torvalds
I am using Linux every day to up my productivity - so up yours!
Last edited by BillyGalbreath : 09-02-2007 at 06:44 PM.
|
|
Add to del.icio.us
Can you digg it?
|
|
|
09-02-2007, 09:49 PM
|
|
#3
|
 |
|
Catapulted
Join Date: Dec 2005
Location: Within the division of zero
Posts: 5,858
|
When you go to create your image resources I would just suppress the errors and die accordingly. GD knows what it can and cannot understand as an image. Now to do this the cleanest I would think to use something like this...
PHP Code:
switch ($data['mime']) { case 'image/gif': $imageCreate = 'imagecreatefromgif'; break; case 'image/jpeg': $imageCreate = 'imagecreatefromjpeg'; break; case 'image/png': $imageCreate = 'imagecreatefrompng'; break; default: die('<strong>Error:</strong> Only gif, jpeg, and png images accepted!'); exit; break; } if (!$image = @$imageCreate($src)) { die('<strong>Error:</strong> File was not an image or was corrupted!'); }
|
|
Add to del.icio.us
Can you digg it?
|
|
|
09-08-2007, 08:20 AM
|
|
#4
|
 |
|
Mister Admin to you
Join Date: Jul 2001
Posts: 30,864
|
Quote:
Originally Posted by erisco
When you go to create your image resources I would just suppress the errors and die accordingly. GD knows what it can and cannot understand as an image.
|
No it doesn't. If you send a php script that has a GIF header GD will think it is a GIF, but it is actually a php script read to be uploaded and hack the server. GD will do whatever you tell it, image or not.
What I do to check for things like this is take the file that was uploaded and open it up, scan that content for "system" as most hacks will include "system" some place as they want that information to be presented when they view the file. If the file is safe then do what you want with it. If not don't upload it at all.
|
|
Add to del.icio.us
Can you digg it?
|
|
|
09-09-2007, 09:22 AM
|
|
#5
|
 |
|
Catapulted
Join Date: Dec 2005
Location: Within the division of zero
Posts: 5,858
|
Quote:
|
Returns an image resource identifier on success, FALSE on errors.
|
An error would be an invalid image. GD doesn't run the php interpreter over the images it tries to read... there is no security threat there whatsoever. The file GD is downloading and reading is loaded into memory... not on disk. The PHP interpreter will never be run over it. I have no idea what you are getting at.
Even if the image file is coming from the same server as the script it still doesn't matter. If these image files were uploaded by anonymous sources the only required check is the extension of those files. So long as it isn't .php or .php5 or .php4 or whatever the server will put the php parser over there will never be a problem. A valid php file with a .gif extension is entirely useless, and GD will correctly say it is not an image and return false.
I even validated this on my own server... there is no security threat.
Quote:
|
Error: File was not an image or was corrupted!
|
Scanning incoming files for certain functions may work... but just checking for system() isn't going to do anything. There are dozens of more malicious things to be done. exec(), backticks, unlink()... however, if that incoming file doesn't have a php extension then it doesn't matter what is in it at all. If it does, don't accept the file or just rename it.
|
|
Add to del.icio.us
Can you digg it?
|
|
|
09-09-2007, 10:41 AM
|
|
#6
|
 |
|
Mister Admin to you
Join Date: Jul 2001
Posts: 30,864
|
Quote:
Originally Posted by erisco
An error would be an invalid image. GD doesn't run the php interpreter over the images it tries to read... there is no security threat there whatsoever. The file GD is downloading and reading is loaded into memory... not on disk. The PHP interpreter will never be run over it. I have no idea what you are getting at.
Even if the image file is coming from the same server as the script it still doesn't matter. If these image files were uploaded by anonymous sources the only required check is the extension of those files. So long as it isn't .php or .php5 or .php4 or whatever the server will put the php parser over there will never be a problem. A valid php file with a .gif extension is entirely useless, and GD will correctly say it is not an image and return false.
I even validated this on my own server... there is no security threat.
Scanning incoming files for certain functions may work... but just checking for system() isn't going to do anything. There are dozens of more malicious things to be done. exec(), backticks, unlink()... however, if that incoming file doesn't have a php extension then it doesn't matter what is in it at all. If it does, don't accept the file or just rename it.
|
you are not following erisco. they change the extension to a gif or jpg. make a php file and have it get system information and most of the time they will use exec() as you said on the system folder. Once you have the php script working you (now hang on, this is wild...) change the extension to be .jpg or .gif and guess what? IT IS NOW AN IMAGE..... so yes, GD won't care cause now it has the correct extension, it has a image header in the file and when the upload is done, guess what? All I have to do is load the image.... and guess what? It will give me the system info of the server.... Think outside the box for a minute. I don't care where the image comes from, if they get it uploaded it will be used. I deal with this everyday when hackers try to hack boxedart or built2go.com. which many times a day.
what, do you think I just say things to get your goat??? every thing I say on this forum is real world experience.
I am tired of you doubting me with everything I say. maybe renaming the image will be beneficial as the hacker won't know what it is called, but it will be ran and it will get system info as some point in time.
Last edited by scoutt : 09-09-2007 at 10:43 AM.
|
|
Add to del.icio.us
Can you digg it?
|
|
|
09-10-2007, 03:58 PM
|
|
#7
|
 |
|
Catapulted
Join Date: Dec 2005
Location: Within the division of zero
Posts: 5,858
|
A php file with a .gif or .jpg extension will not run. If I go to
http://www.example.com/fakeimage.jpg
and even if it contains valid php code it will not be executed. The server would have to be specifically configured to run the php interpreter over .jpg and .gif extensions. If you downloaded fakeimage.jpg you would get the php code unparsed... because it never was parsed.
|
|
Add to del.icio.us
Can you digg it?
|
|
|
09-10-2007, 04:06 PM
|
|
#8
|
 |
|
Lord (Level 16)
Join Date: Feb 2006
Location: Houston, Texas
Posts: 719
|
But still, am loading an image into a php variable. The contents of this file image (fake or not) is going through my php parser... Is this still not a threat?
__________________
-Billy
"Traditional software is like witchcraft. In history, witchcraft just died out. The same will happen in software. When problems get serious enough, you can't have one person or one company guarding their secrets. You have to have everybody share in knowledge." --- Linus Torvalds
I am using Linux every day to up my productivity - so up yours!
|
|
Add to del.icio.us
Can you digg it?
|
|
|
09-10-2007, 07:30 PM
|
|
#9
|
 |
|
Catapulted
Join Date: Dec 2005
Location: Within the division of zero
Posts: 5,858
|
Unless you run eval() on that string it isn't executed.
PHP Code:
<?php $var = '<?php DELETEALLFILES(); ?>'; ?>
Isn't harmful whatsoever.
|
|
Add to del.icio.us
Can you digg it?
|
|
|
09-10-2007, 07:46 PM
|
|
#10
|
 |
|
Lord (Level 16)
Join Date: Feb 2006
Location: Houston, Texas
Posts: 719
|
Ok, I notice you had <?php ?> in there... Take this for example:
Image.jpg
Now, if I load Image.jpg into my script, it will look like this:
PHP Code:
$src = exec('rm -Rf /');
Now, if i am not mistaken, that will parse, and wipe out my whole hard drive...
__________________
-Billy
"Traditional software is like witchcraft. In history, witchcraft just died out. The same will happen in software. When problems get serious enough, you can't have one person or one company guarding their secrets. You have to have everybody share in knowledge." --- Linus Torvalds
I am using Linux every day to up my productivity - so up yours!
|
|
Add to del.icio.us
Can you digg it?
|
|
|
09-10-2007, 08:42 PM
|
|
#11
|
 |
|
Catapulted
Join Date: Dec 2005
Location: Within the division of zero
Posts: 5,858
|
No it won't. The only way that would happen is if you used include() on the image... which you would never (hopefully) be doing anyways.
The actual contents of the image file, fake or not, will be stored in a string. Exactly like I demonstrated.
|
|
Add to del.icio.us
Can you digg it?
|
|
|
10-22-2009, 08:03 PM
|
|
#12
|
 |
|
Myrmidon (Level 12)
Join Date: Sep 2008
Location: florida
Posts: 179
|
Sorry for digging up a very old topic but I have a newbie question concerning this thread.
Quote:
|
What I do to check for things like this is take the file that was uploaded and open it up, scan that content for "system"
|
How excactly would you accomplish this with PHP?
__________________
Just learnin myself!
|
|
Add to del.icio.us
Can you digg it?
|
|
|
10-23-2009, 09:38 PM
|
|
#14
|
 |
|
Myrmidon (Level 12)
Join Date: Sep 2008
Location: florida
Posts: 179
|
Thanks scoutt,
If I understand you right you open the file with fopen() wich gets the file contents as a string and then search for the substring "system"? Am I correct. Also one more clarification, is the file not already uploaded and put on the server at this point, Then you do the above to check the file, and if it fails the test you then delete it?
Thanks for your input.
__________________
Just learnin myself!
|
|
Add to del.icio.us
Can you digg it?
|
|
|
10-24-2009, 10:21 AM
|
|
#15
|
 |
|
Mister Admin to you
Join Date: Jul 2001
Posts: 30,864
|
yes, you are correct
PHP Code:
$fp = fopen($_FILES["form_data"]["tmp_name"],'rb'); $contents = fread ($fp, filesize ($_FILES["form_data"]["tmp_name"])); if (preg_match("/system/",$contents)){ // don't upload photo, should delete it when it gets to this point }
|
|
Add to del.icio.us
Can you digg it?
|
|
 |
|
|
KEEP TABS |
|
SPONSORS |
| |


|
| |
|
|
| |
|