Forum Moderators: coopster
This cannot be over-emphasised - it's been said here before and will be said many times again:
You must rename files when you upload them
It is a serious security risk otherwise. If your code is for internal use only and you have otherwise secured your server, then maybe it's okay.
To test your own application's file upload for security risks, open notepad, and enter the following in a file (changing YOUR@EMAIL.ADD to your own address):
<?php
mail("YOUR@EMAIL.ADD","This could be spam","Coming from your server");
?>
Save it as image.php.jpg
Upload it.
Type the direct path to where that file went:
http://www.example.com/img_upload/image.php.jpg
Be aware that this can often work with other languages as well (not confined to PHP). Don't try removing '.php' from filenames. Hackers can easily use .asp, .pl, .cgi or anything else you happen to support.
Don't try checking the file type by using built-in functions! It is easy to prefix the file above with the first chunk of a true jpg file and it will identify as a valid jpg.
This massive flaw exists in a large number of image galleries and many other software suites. Any time you take a user-supplied file and store it on the server, rename it.
My recommendation for good practice is to rename it to a serial number and then keep the true filename in a database table with the serial number as an index. That way you can easily use mod_rewrite to make it appear that the image has kept the correct name.
if EXIF is installed on your server you can do this all with a single function called exif_imagetype() [php.net]
A workaround could be to explode your image in a variable, read first few bytes and make sure it is an image and doesn't contain text etc.
That is not a work around. Anyone can put the first few bytes of a real jpeg or similar before the <?php and bypass the function. I'd show an example but those characters won't paste properly in WebmasterWorld.
The best workaround is to name it yourself. Most other workarounds just leave gateways for attacks with only small variations.
Some reasonable other options:
1) Use GD to parse the entire image and write it again from GD
2) Store the image in a database as BLOB (although this is practically the same as renaming the image to a serial number)
I caution you against using file permissions or server configuration to deal with this. One day you will give or sell the script to someone and they won't do (or won't be able to do) the needed changes. Just as likely, your server will crash, you'll install a fresh OS and forget all the extra non-standard settings you need.
Summary: Never do this
move_uploaded_file($_FILES[file][tmp_name],"images/".$_FILES[file][name]);
Don't ever trust the original file name. Pick a new one yourself.
<?php
mail("YOUR@EMAIL.ADD","This could be spam","Coming from your server");
?>Save it as image.php.jpg
Upload it.
Type the direct path to where that file went:
http://www.example.com/img_upload/image.php.jpg
I can't understand why you are considering this a vulnerability? Do you have server setup to parse jpg/png/gif files as php? If so, this would be a useless server load.
php/asp/etc code injections into images can only cause troubles if your script is doing include($image_file_name) instead of readfile($image_file_name). I believe using readfile avoids all these vulnerabilities. Am i missing something?
Try it. Create the file and upload it. Visit it through your browser and await email. You might be okay. We're not talking about using include() or readfile()... we're talking about visiting these files directly from the browser.
[edited by: vincevincevince at 10:22 am (utc) on Sep. 26, 2007]
have blocked your images folder direct access with htaccess file then nobody could call his uploaded files.
One other thing you could do is explode your file and regex it to see if any '@', or 'mail(' string is present in it.
I am not saying that your idea to rename file is wrong, it is good and easy but a hacker must tell us how they explode this because I bet they must know that people can rename files :)
You want to learn about this stuff, hack your scripts, break stuff, delete dbs through a contact form, it can be done. Learn escape chars, injection, read a ton of howto's
ignorance is not a valid defense ;)
HOW WILL YOU LEARN ABOUT HACKING?
Is the real question.
I am not gutsy enough to start looking for "dark corners" of the web and try to comm with hackers or hacker boards
And I do not think there are books about it :)
Many books about security, indeed the reverse of security coding could be used in hacking but I could not really figure it out aside of the very basic stuff?
So how hacking our own script?
<edit>
minor change
</edit>
[google.com...]
among a million other searches, yes care is required when you search these dark corners but they are fairly easy to find
script kiddies start somewhere, usually google ;)
The standard setup of even reasonably recent (and older versions) Apache + PHP will mistakenly parse any file containing '.php' in the filename... not only if it is placed at the very end of the filename.
Do you have some information on precisely which Apache versions might be affected, and exactly what configuration might cause this? I'm trying to reproduce the problem, but without any success, both on 2.0.59 and an ancient 1.3.33.
Do you have some information on precisely which Apache versions might be affected, and exactly what configuration might cause this? I'm trying to reproduce the problem, but without any success, both on 2.0.59 and an ancient 1.3.33.
How exactly are you serving these renamed files?
if you go this route then your users won't be able to view the pictures / documents / etc. they uploaded!How does your method allow this without actually serving a tainted file?
All fine until you tar up the files in the directory to send to someone and forget that .htaccess gets missed by tar *... or it needs to run somewhere without .htaccess.
The best workaround is to name it yourself.
One other thing you could do is explode your file and regex it to see if any '@', or 'mail(' string is present in it.
This would be a foolish solution.
Sorry, I'm not convinced. I serve 'native' graphics conventionally, and use .htaccess/gd for uploaded ones.
Why, exactly?
Because there is always a chance that you won't think of one of the tokens that could be used. Some examples were given earlier, but that is by no means all of them. What if you happened to miss one and it is used in an injection attempt?
If the potential hacker can't find the "image" after upload, you've stopped them before anything else can be attempted.
What if you happened to miss one
The point is his immediate, unfounded dismissal that it's "foolish". It may not be complete, it may not be the best but it's far from foolish, it's a viable solution.
Keeping something locked up is better than hiding it. Burglars prove that every day.
I am still convinced that the best way is to use htaccess to stop direct access of your images folder and if possible put it above public_html/www/httpdocs folder.
The second solution could be to parse your images for all possible strings at least 'mail(' will appear whatsoever if the file contains the mailing function, since we are talking about mail() injection with uploading.
As long as it is about renaming files, since we are supposing conditions so let's suppose that you have a social networking site and I as a hacker upload an injection file for my profile picture section.
You have renamed it after uploading good work. I will visit my profile and will get the renamed name of my injection file from that page. and I can call it then with the new name.
If it is possible to take out / provoke execute permission from the image folder you are on the safe side.
I am still convinced that the best way is to use htaccess to stop direct access of your images folder
<edit>
I might also via eregi() deal with any client and server side file extension name, plus mail @, CC etc..
</edit>
Its that validation of the input that is the most important thing. Also that those people who know what weaknesses are around share those with people so that we can all make our scripts more secure. While this thread may have taught a new trick to those hackers just starting out it has potentially exposed a weakness in people scripts that we can now test for and fix.
The best method to stop hackers it not to allow any user input...but that isnt very interesting is it? So validation of that user input is hugely important.
The standard setup of even reasonably recent (and older versions) Apache + PHP will mistakenly parse any file containing '.php' in the filename... not only if it is placed at the very end of the filename.
It is not a mistake, it is by design:
Filenames may have multiple extensions and the extension argument will be compared against each of them.[httpd.apache.org...]
Do you have some information on precisely which Apache versions might be affected, and exactly what configuration might cause this? I'm trying to reproduce the problem, but without any success, both on 2.0.59 and an ancient 1.3.33.
Apache isn't affected or even infected for that matter. The HTTP server is setup this way by design.
[httpd.apache.org...]
Many shared hosting providers will turn off Content Negotiation because of the general lack of understanding. They cinch things down tight because of this lack of understanding. If you aren't using Content Negotiation, turn it off. If you are using PHP and allowing user input, including file uploads, you just need to know what you are doing.
Apache defined with PHP as a handler is doing exactly what it is supposed to do, allow the PHP engine to parse the document because it has been defined in the extension. Our job as programmers is to understand how this works and code accordingly.
Great discussion, much to be learned here folks --
coopster