Page 1 of 1
Upload image security
Posted: Mon Dec 15, 2008 12:09 am
by Frozenlight777
I have a php image upload script that lets the user upload images to a folder on the webserver and then uses opendir() and readdir() to view the images in the folder.
I'm assuming letting a user upload images directly to the webserver is very unsafe and I'd prefer to not use that method however I do have the following security features and was wondering if I'm missing anything or if I should just use a different approach.
- There is only 1 account and that is an administrator account. (using tokens, salts, md5, mysql_real_escape_string)
- Can only upload jpeg, jpg, bmp and gif image types (also checking to make sure they don't upload image.jpg.exe or whatever) of a certain size
- Script renames the image when uploading
- Database records all of the users history of uploading what and when
I'd prefer to not use opendir() and readdir() because I know there's still potential threats, but what in the php world is the best method of implementing image uploads? I've tried using a database and that has never worked for me
Thank you.
Re: Upload image security
Posted: Mon Dec 15, 2008 2:13 am
by jaoudestudios
If you google 'image upload php', there are many examples and they all use move_uploaded_file.
Post your code!
Re: Upload image security
Posted: Sat Dec 20, 2008 7:16 am
by kaisellgren
Frozenlight777 wrote:I have a php image upload script that lets the user upload images to a folder on the webserver and then uses opendir() and readdir() to view the images in the folder.
I'm assuming letting a user upload images directly to the webserver is very unsafe and I'd prefer to not use that method however I do have the following security features and was wondering if I'm missing anything or if I should just use a different approach.
- There is only 1 account and that is an administrator account. (using tokens, salts, md5, mysql_real_escape_string)
- Can only upload jpeg, jpg, bmp and gif image types (also checking to make sure they don't upload image.jpg.exe or whatever) of a certain size
- Script renames the image when uploading
- Database records all of the users history of uploading what and when
I'd prefer to not use opendir() and readdir() because I know there's still potential threats, but what in the php world is the best method of implementing image uploads? I've tried using a database and that has never worked for me
Thank you.
A couple of thoughts:
- Make sure the opendir(), readdir() part of the script is not vulnerable to LFI -- make sure no one can try to a dir like "../../../etc/" and so on..
- You should upload the files outside the document root. If this is not possible (which is doubt), then use .htaccess (if Apache) to 'deny from all' the access to files. And under no circumstances you should allow executive permission to that folder or files. I would personally use a permission level of 0640. Better is to not allow public read, and instead provide a php script that displays the images.
- An attacker may upload virus.php%00.jpg and you script thinks the file is ok, because it ends with .jpg. Even if its file.jpg, it may contain PHP code, and if it's run by PHP parser then you are out of luck. The sizelimit you have can not be anyhow fooled and it's good you have it. (Or can it? Anyone have experience with *nix sparse files? On Windows & NTFS they work great, a file is 1 GB in size but 4 kB in the disk

)
- Renaming is good, an attacker does not know the filename of his upload.
- Db records are good.
What comes to opendir(), readdir(), you do not have to use db to store images. Using files is better imo. Just makes sure you validate/sanitize the variables you pass into these two functions. Make sure a dir is a dir and it is exactly what you suppose it is.
Re: Upload image security
Posted: Mon Dec 22, 2008 9:11 am
by The_Anomaly
How do you plan to do this?:
- Can only upload jpeg, jpg, bmp and gif image types (also checking to make sure they don't upload image.jpg.exe or whatever) of a certain size
From this forum, I learned the simply checking the MIME types is extremely easy to get around. For obvious reasons, the extension is also very unsafe. I use a function (i.e. GD library) to try to do something with it (resize or something) and if it throws an error, you know it's not a real image, and send it back saying so. Probably better ways of doing it, but it's worked with all of the tests I've given it.
Re: Upload image security
Posted: Mon Dec 22, 2008 9:16 am
by John Cartwright
The_Anomaly wrote:How do you plan to do this?:
- Can only upload jpeg, jpg, bmp and gif image types (also checking to make sure they don't upload image.jpg.exe or whatever) of a certain size
From this forum, I learned the simply checking the MIME types is extremely easy to get around. For obvious reasons, the extension is also very unsafe. I use a function (i.e. GD library) to try to do something with it (resize or something) and if it throws an error, you know it's not a real image, and send it back saying so. Probably better ways of doing it, but it's worked with all of the tests I've given it.
Along those lines, however, you can simply run it against getimagesize(). An error means it's an invalid image, obviously.
Re: Upload image security
Posted: Mon Dec 22, 2008 9:22 am
by kaisellgren
Jcart wrote:The_Anomaly wrote:How do you plan to do this?:
- Can only upload jpeg, jpg, bmp and gif image types (also checking to make sure they don't upload image.jpg.exe or whatever) of a certain size
From this forum, I learned the simply checking the MIME types is extremely easy to get around. For obvious reasons, the extension is also very unsafe. I use a function (i.e. GD library) to try to do something with it (resize or something) and if it throws an error, you know it's not a real image, and send it back saying so. Probably better ways of doing it, but it's worked with all of the tests I've given it.
Along those lines, however, you can simply run it against getimagesize(). An error means it's an invalid image, obviously.
One can easily make a file "image.gif" and insert malicious PHP code inside color pallettes, or comments block, or possibly somewhere else. When you run tests with GD (like getimagesize()) they will work fine, because it does not check the colors -- who says the colors can not be <?php ... ?>
And when the PHP parser runs the "image.gif" it ignores the binary data and executes the PHP code.
There's no simple way to make sure the image does not contain malicious PHP code. Even using string replacements do not work that easily since the content is in binary data. Besides, why can't I have PHP code in my image comments block?
One could do serious manipulation on the image to get rid off possible PHP code -- but this comes with a price of performance drop.
Re: Upload image security
Posted: Mon Dec 22, 2008 10:01 am
by onion2k
kaisellgren wrote:One can easily make a file "image.gif" and insert malicious PHP code inside color pallettes, or comments block, or possibly somewhere else. When you run tests with GD (like getimagesize()) they will work fine, because it does not check the colors -- who says the colors can not be <?php ... ?>
And when the PHP parser runs the "image.gif" it ignores the binary data and executes the PHP code.
Why would you put image.gif through PHP's parser? That seems like a very strange thing to do. Strange, and pointless because any proper image isn't going to contain any code.
As security concerns go, I'd say that's quite low priority.
Re: Upload image security
Posted: Mon Dec 22, 2008 10:04 am
by John Cartwright
onion2k wrote:kaisellgren wrote:One can easily make a file "image.gif" and insert malicious PHP code inside color pallettes, or comments block, or possibly somewhere else. When you run tests with GD (like getimagesize()) they will work fine, because it does not check the colors -- who says the colors can not be <?php ... ?>
And when the PHP parser runs the "image.gif" it ignores the binary data and executes the PHP code.
Why would you put image.gif through PHP's parser? That seems like a very strange thing to do. Strange, and pointless because any proper image isn't going to contain any code.
As security concerns go, I'd say that's quite low priority.
I would think some people do this where they need dynamic images (by php) that end with a valid image extension. Unfortunately that means for some people passing all jpg's through the php parser.
Re: Upload image security
Posted: Mon Dec 22, 2008 10:05 am
by kaisellgren
onion2k wrote:kaisellgren wrote:One can easily make a file "image.gif" and insert malicious PHP code inside color pallettes, or comments block, or possibly somewhere else. When you run tests with GD (like getimagesize()) they will work fine, because it does not check the colors -- who says the colors can not be <?php ... ?>
And when the PHP parser runs the "image.gif" it ignores the binary data and executes the PHP code.
Why would you put image.gif through PHP's parser? That seems like a very strange thing to do. Strange, and pointless because any proper image isn't going to contain any code.
As security concerns go, I'd say that's quite low priority.
As security concerns go, it is
not low priority.
For example, many people use dynamically generated avatars in forums. They assign Apache to parse .png/.gif through PHP. This is very common. And this is just one case, many graphics related scripts may alter the way of images used on the server. I know personally three persons having their website hacked by running other than .php files through PHP.
Security is not a measurement. It's also possible through buffer overflows to run image data on PHP. If that image data is gathered from an uploaded image file, then you have
yet another security hole in your application.
Also, you may not forget a thing called
Defense in Depth. Are you really sure you want to take the route that relies on the current system configurations, current software configurations, etc and when the time comes that you or your server admin (may it be you or someone else) alters any configurations by editing configs or by updating software -- will you remember to update your script to 'match' your server configuration? What about the users of your script? You are very vulnerable to chain attacks.
So as security concerns go, you can not trust image files. You just can not, unless you do run many different image related manipulation functions on the image.
Re: Upload image security
Posted: Mon Dec 22, 2008 10:19 am
by onion2k
kaisellgren wrote:For example, many people use dynamically generated avatars in forums. They assign Apache to parse .png/.gif through PHP. This is very common.
Yes. I do it myself. But not for
every image on the server, only an idiot would do that. You shouldn't be pushing
any user uploaded content through PHP regardless of what it is so the fact it's possible to put code inside an image file is irrelevant. Consequently this is a low priority issue. It can't happen unless you're being stupid.
Re: Upload image security
Posted: Mon Dec 22, 2008 10:24 am
by kaisellgren
onion2k wrote:kaisellgren wrote:For example, many people use dynamically generated avatars in forums. They assign Apache to parse .png/.gif through PHP. This is very common.
Yes. I do it myself. But not for
every image on the server, only an idiot would do that. You shouldn't be pushing
any user uploaded content through PHP regardless of what it is so the fact it's possible to put code inside an image file is irrelevant. Consequently this is a low priority issue. It can't happen unless you're being stupid.
So can you guarantee what your script user does? Will he properly assign certain files/directories only to go through PHP?
Like I said,
buffer overflow attacks are still possible. Regardless you specify any files to go through PHP or not. Even if .php is the only filetype to be run through PHP, that's not enough.
EDIT: I remember one website being under serious attack, the designers talk forums. This was due to buffer overflow attacks of image files uploaded by the attack itself. The image extension was never specified to be run through PHP -- that's not the case here.
What would I do if your website is vulnerable and I want to hack it? I would probably include a c99 -like script within your server and execute it from overflow attacks. Gain the access, open backdoors, gather DB access - hack the whole website at once. That's something ugly... why would you not want to take the safer route and read my first post in this post and learn more about safe uploading practise and avoid all mess or you may end up doing

some day

Re: Upload image security
Posted: Mon Dec 22, 2008 10:29 am
by onion2k
kaisellgren wrote:So can you guarantee what your script user does? Will he properly assign certain files/directories only to go through PHP?
Even the best code can be broken on a poorly configured server. There's no point spending loads of time defending against it. So long as my code doesn't have security issues I'm happy. If people run my code on a server that does then it's not my problem.

Re: Upload image security
Posted: Mon Dec 22, 2008 10:35 am
by kaisellgren
onion2k wrote:kaisellgren wrote:So can you guarantee what your script user does? Will he properly assign certain files/directories only to go through PHP?
Even the best code can be broken on a poorly configured server. There's no point spending loads of time defending against it. So long as my code doesn't have security issues I'm happy. If people run my code on a server that does then it's not my problem.

Well yeah, but you can take the route 2 and be safe
EDIT: Some people call the usual way of doing this (vulnerable) the route 1, and the route 2 is what I described in my first post in this topic. These are called upload routes among some black hat hackers

Re: Upload image security
Posted: Fri Dec 26, 2008 9:32 am
by Mordred
Another way for a hacker to use malicious.gif as a backdoor is through a LFI vulnerability.
Re: Upload image security
Posted: Fri Dec 26, 2008 10:16 am
by kaisellgren
Mordred wrote:Another way for a hacker to use malicious.gif as a backdoor is through a LFI vulnerability.
Yes that's just another reason why not to trust files being uploaded by a user.
Doesn't matter if you specify a .gif to go through a PHP parser by default or not.