Web Hosting Talk







View Full Version : PHP include Security risk -- Please read!--


XGenesis
10-22-2003, 06:19 AM
It has come to my attention that a PHP exploiter has been leaked and someone is using it to exploit peoples sites and install mail bombers on their servers which is quite easy to do. There is a simple and easy counter measure to this script.

Your vulnerable if you have PHP includes like this: You must change to the newer version of the code at all costs!!


<?
include("$id"); // $id can be anything, $page, $x, $file, etc
?>


Basically, if you dont see file_exists in your include code - YOU RISK BEING HACKED!!! You MUST change to the following code now:

<?
if(file_exists($id))
{
include($id);
}
else
{
include("newsfile.php"); // include your news file, or default page file
}
?>

Basically file_exists() checks that the file you are trying to include is located on your server, thus returning false(doesnt exist) if the file is located on a different server, or is being included via http request, etc.

Tell all the people you know that own websites about this exploit and make it a priority to get it fixed.

Thankyou
- Patrick

John D
10-22-2003, 06:21 AM
Can you include files which arent on your own server?

Website Rob
10-22-2003, 06:29 AM
Nice safety tip, Patrick -- thanks for sharing.

biggulp
10-22-2003, 06:49 AM
better still, have an array of "safe" files

N9ne
10-22-2003, 07:24 AM
Originally posted by biggulp
better still, have an array of "safe" files

THIS IS A MUST!

ALWAYS have an array of safe files. In fact, for anything that the client side can possibly gain control over, you DEFINITELY MUST have an array of safe [enter object] !

John D
10-22-2003, 07:35 AM
Can anyone tell me how to dothis?
I use the include function on most of my sites but its about the only thing i can do in PHP...

NE-Andy
10-22-2003, 07:35 AM
my "$ID" is always listed in two places for authenticy, an array include and a MySQL database. My script will run to the safe file array, nab the appropriate index, then connect to a MySQL database to nab the appropriate record, compare the two, if the same, good, load it, if not, then out put error. It's a pain, and it probably doesn't worth my (and the CPU's) time, but it's good for thing you absolutely sure that has to be "right".

N9ne
10-22-2003, 07:57 AM
Originally posted by Custom-Hosting
Can anyone tell me how to dothis?
I use the include function on most of my sites but its about the only thing i can do in PHP...

Are you including a variable? Or have you specified an actual file name in the include() call? If you specify the actual file name you're ok.

N9ne
10-22-2003, 08:01 AM
For those of you who are wondering what a safe array is, here's an example:


<?php
// list safe filenames here
$safe_array = array('test.php', 'page.html', 'whatever.txt');

if (in_array($id, $safe_array)) {
include_once($id);
} else {
echo 'Cannot include file!';
exit;
}
?>


Basically, for example if the page above is called this_page.php, users can go to:

this_page.php?id=whatever.txt

and the page will show. If they put something as the $id which isn't in your safe array, it will be rejected.

Website Rob
10-22-2003, 08:13 AM
N9ne, thanks for sharing. Now we can have a complete picture to work with. :)

John D
10-22-2003, 08:34 AM
N9ne this is an example of what im doing:

<? php
include("example.html");
?>

N9ne
10-22-2003, 09:01 AM
Originally posted by Custom-Hosting
N9ne this is an example of what im doing:

You have nothing to worry about then :).

I, Brian
10-22-2003, 09:07 AM
Originally posted by Custom-Hosting
Can you include files which arent on your own server?

You used to be able to use absolute URLs in your php includes - but then php was updated so that you need to use absolute PATHS instead - - - precisely to stop people calling up files from other people's servers.

null
10-22-2003, 09:10 AM
This is an old example. Few months ago it was really easy to find such scripts on the Google :)

Loon
10-22-2003, 09:10 AM
You can still include absoloute urls, you can use the @ sign before the include to surpass the error message that php gives you eg:

@include('http://www.google.com');

null
10-22-2003, 09:13 AM
Before you can do that you should check if

allow_url_fopen is equal to 1

in php.ini

Also this feature is not working under the Windows systems

null

Rich2k
10-22-2003, 09:27 AM
This has been known for a long time not accept requests from a user which hasn't been 'cleaned' before opening anything on the file system based on this request.

Pretty much everytime someone posts some code like that in the Programming forum we mention this exploit.

anlene
10-22-2003, 11:28 AM
Originally posted by Rich2k
This has been known for a long time not accept requests from a user which hasn't been 'cleaned' before opening anything on the file system based on this request.

Pretty much everytime someone posts some code like that in the Programming forum we mention this exploit.

ditto, was just bout to include this.. :D

Jakiao
10-22-2003, 07:22 PM
It's sad, however, that even though his tip does protect from foreign scripts, all a person has to do is this:

include("/etc/passwd");

Or anything like that, and then they have whatever is in that file. Now, if only PHP.net released a php distro that prevented the inclusion of files owned by root; since PHP runs as user nobody, online, that would be a good feature as well.

Anyway, thanks Patrick; I will have to pass this on to a few of my friends that are just learning PHP. Lucky for me, I always include full paths before the variable.

Dan L
10-22-2003, 08:56 PM
I generall use file_exists along with automatically appending an extension and/or prepending a directory. Pretty safe.

platinum
10-22-2003, 09:45 PM
yeah, this is the version I coded up:


<?
include('header.php');

if($action = $_GET['action']){
// Define each page name below
$pages = array('gallery', 'anotherpage', 'somethingelse');
if(in_array($action, $pages)){
include("$action.php");
} else {
print("Invalid Page Requested.");
}
}

include('footer.php');
?>

RuthWells
10-22-2003, 11:15 PM
evil evil but nice to see that people talk about it :)

chrisranjana
10-23-2003, 01:32 AM
here is a nice article

http://www.onlamp.com/pub/a/php/2003/07/31/php_foundations.html

and

http://www.onlamp.com/pub/a/php/2003/08/28/php_foundations.html

Techark
10-23-2003, 01:47 AM
Yeah this is a huge hole as one of my server owners found out recently when they hacked their server and defaced about 70% of their web sites because they had an index.php page with an open include.
This same exploit can be used on any cgi script that does the same thing with out the proper checks also. It also allows them to wget all kinds of scripts to load into the tmp dir.

It is a Nasty little crack and the boyz in Brazil are using it for all it worth, they have exploit sites set up all over geocities and tripod etc that contain the code for the hack.

YUPAPA
10-23-2003, 01:49 AM
Not only PHP, but this apply to perl too~ :angel:

Rich2k
10-23-2003, 04:52 AM
It applies to pretty much any language where you can include files.

However this is one of the reasons for open_basedir because then an inexperienced programmer can't compromise the whole server, just the security of his own site.

Quadra
12-26-2003, 04:38 AM
Originally posted by jakiao
It's sad, however, that even though his tip does protect from foreign scripts, all a person has to do is this:

include("/etc/passwd");

Or anything like that, and then they have whatever is in that file. Now, if only PHP.net released a php distro that prevented the inclusion of files owned by root; since PHP runs as user nobody, online, that would be a good feature as well.
What's wrong with this? Passwords are shadowed so the only thing they can do is brute force.

The Prohacker
12-26-2003, 04:40 AM
This is why Register Globals is turned off by default on servers so you'd have to use $_POST['id']

Lippy
12-26-2003, 05:14 PM
So I can pass this onto my clients(several of them use alot of php) this is only an exploit if they are using a variable in the include statement. Correct?

Jakiao
12-26-2003, 05:41 PM
Quadra, nothing is 100% secure. If a hacker has a list of md5 hash passwords, usernames, uid/gid's, home paths, etc etc, then you can be compromised. Any unprotected (or simple passwords) on those accounts can give hacker access.

No matter how encrypted something is, it can be decrypted.

OUFNecro
12-26-2003, 07:48 PM
I dont see why this is such a big deal... sure it's very hackable, but anyone who writes a script thaaat open deserves to be hacked... this is the way i do it (using a switch)

url: www.whocares.com/index.php?page=<page name, not filename>


switch ($_GET["page"])
{
case "members":
$page="members.php";
break;
case "serv_info":
$page="servinfo.php";
break;
case "allmatches":
$page="dispmatches.php";
break;
case "matches":
$page="matches.php";
break;
case "about":
$page="about.php";
break;
case "contact":
$page="contact.php";
break;
default:
$page="news.php";
break;
}


very simple, and impossible to hack...

Quadra
12-26-2003, 08:02 PM
jakiao, md5 hash is not stored in /etc/passwd

Jakiao
12-26-2003, 09:00 PM
It was an example.

include("/etc/shadow");

That is just as effective. I used /etc/passwd as an example. I would assume that you would understand that I also knew of the shadow file.

Quadra
12-26-2003, 09:09 PM
On any system that security hasn't been totally messed up, this includes any default installation of any modern unix, shadow file is only readable by root. So nobody else but root can open the shadow file, whether they have shell access, php, perl or anything else.

Quadra
12-26-2003, 09:20 PM
I fully understand that users can open files they are not _supposed_ to snoop around but these files at the same time are harmless. ALL sensitive files should be set to be readable only by root and all sensitive directories should be set to writable only by root. They can read the rest to their heart's content, but nothing they can do about it unless if your system has a known vulnerability that hasn't been patched. In this case, they can still exploit the vulnerability without reading too many files.

My point is the ability to read other files, especially system files in itself is not necessarily a security "hole".

The only security hole associated with this is the ability to read other user's php files, not the system files. I just want to point out that reading /etc/passwd is absolutely harmless. All the information you can get from /etc/passwd you can also get it from many function calls, including other user's uid/gid, its home directories, etc. This is exactly why /etc/passwd should be made readable to everyone.

As for any other system files, if they are readable then they probably should be readable.

Getting back to the topic, the security hole associated with include has nothing to do with including system files... it's more about including other user's files which is well known, and the ability to allow remote attacker to do something bad. The extent of the damage depends on your system's security itself. I'm not going to go too much into details here but someone has already posted some hints in this thread.

You were correct though that nothing is 100% secure.

Jakiao
12-26-2003, 09:30 PM
At least we agree on something.

Some unix systems have problems when shadow is chmod'd to ug=rwx though, some FTP programs become unusable because it can't check hashes.

Anyway, I just make it a point, and teach to others, that if you're going to include a file, don't do include("blah/blah.html"); instead fo include($_SERVER['DOCUMENT_ROOT'] . "/blah/blah.html"); at a bare minimum.

Schumie
12-30-2003, 12:30 PM
Originally posted by jakiao
No matter how encrypted something is, it can be decrypted.

This statement is sort of correct, but incorrect at the same time. MD5 being a uni directional encryption system, you cannot decrypt it. However, that doesn't mean to say it's not possible to work out the password, you just encrypt all combinations of characters and find a match to the hash.

Jakiao
12-30-2003, 03:41 PM
That's how you can decrypt it though, in a sense. If you can find the original value before it's MD5 hash, then you have technically decrypted it.

Sheps
12-30-2003, 07:41 PM
Originally posted by jakiao
Anyway, I just make it a point, and teach to others, that if you're going to include a file, don't do include("blah/blah.html"); instead fo include($_SERVER['DOCUMENT_ROOT'] . "/blah/blah.html"); at a bare minimum.
That is not a problem. It is normally with scripts that you can inject something like:

/etc/shadow

because the include is include($filename); and $filename is a variable passed through the URL or web form

Jakiao
12-30-2003, 07:47 PM
Uh yeah, I already pointed that out.

cyberlot
12-31-2003, 11:05 AM
Originally posted by jakiao
That's how you can decrypt it though, in a sense. If you can find the original value before it's MD5 hash, then you have technically decrypted it.

Then you didnt decrypt it..

Decryption is the process of taking a unknown value and using a system to restore it to its proper state.

You can not restore a MD5 hash. You can use a brute force method.. But its not decryption.

Jakiao
12-31-2003, 11:06 AM
I'm using the term as an example. Give me a better word to use and I'll use it. If you want me to say hash matching, fine.

Studio64
01-03-2004, 01:19 PM
I don't mean to flame but the simple fact of include($filename) isn't the security hole and this IS NOT a PHP problem nor a PHP exclusive problem

This is simply poorly written code. Whoever wrote these applications that include code that is affected by the above problems don't know a great deal about designing secure software. YOU NEVER TRUST INPUT FROM THE USER.

Read that last sentence again and you'll get the idea. YOU NEVER TRUST INPUT FROM THE USER.

You never trust input from the user because when you ask for a number he might put in letters. When you ask for only 20 charecters he might put in 3000. You never trust input from the user.

I have no idea why in the world would anyone ever include a filename from the user that hasn't been checked (is it local, is it supposed to be there, is the files md5 hash valid against a known and authorized source, why do i have to include a file name in this method)...

This is why there are standard coding practices and guidelines as well as code review and audits...

include($file).... That scares me...

nybble
01-03-2004, 01:37 PM
sorry to add to this... but how can $id be anything? $id must be defined as something.... its not like you can go index.php?id=mysql_query blah

Are you getting $GET['id'] mixxed up with $id? :eek:

Studio64
01-03-2004, 01:54 PM
Originally posted by nybble
sorry to add to this... but how can $id be anything? $id must be defined as something.... its not like you can go index.php?id=mysql_query blah

Are you getting $GET['id'] mixxed up with $id? :eek:

Depending on the server config $GET['id'] can == $id... Although you should always use the http arrays anyhow...

axx2k
01-04-2004, 08:09 AM
Originally posted by OUFNecro
I dont see why this is such a big deal... sure it's very hackable, but anyone who writes a script thaaat open deserves to be hacked...



Anyboody who 'writes a script that open' needs to be informed, which is why this post was originally made. Whether they decide to take and use the information is their choice, and therefore, their responsibility. Knowing is half the battle.

The only people who 'deserve to be hacked' are those who attempt to hack for malicious reasons in the first place (ie: the losers who are tryinig to exploit this 'hole'). Are you trying to say that newbies who need to learn more should be hacked just because they don't know? It's people like this post originator that are really helping out, by supplying some 'FYI' for the 'DIY'.

Cheers everyone. :cool:

denkhelder
01-04-2004, 01:23 PM
LMFAO, you PHP coders sure crack me up....


<?
if(file_exists($id))
{
include($id);
}
else
{
include("newsfile.php"); // include your news file, or default page file
}
?>


is _EXACTLY_ the same as include($id); except when the file you try to include doesn't exist, it includes the newsfile.php.

Example:
Let's say $id is '/usr/local/etc/apache/httpd.conf', with include($id); the file will be included and printed, with your so called 'fix' the file will be included and printed, because file_exists('/usr/local/etc/apache/httpd.conf') returns true.

If you're going to banter about exploits, make sure the fix you provided is a real fix.

As others mentioned, an array of allowed files is the way to go, because local or remote files, you don't want people including stuff they shouldn't be doing.

Rich2k
01-04-2004, 01:40 PM
Except the fact that most PHP (or any other language) coders I know wouldn't do that as it's obviously still a security risk.

ferox
01-08-2004, 03:40 AM
I agree Rich2k.

Acecool
01-09-2004, 05:01 PM
Originally posted by denkhelder
LMFAO, you PHP coders sure crack me up....


<?
if(file_exists($id))
{
include($id);
}
else
{
include("newsfile.php"); // include your news file, or default page file
}
?>


is _EXACTLY_ the same as include($id); except when the file you try to include doesn't exist, it includes the newsfile.php.

Example:
Let's say $id is '/usr/local/etc/apache/httpd.conf', with include($id); the file will be included and printed, with your so called 'fix' the file will be included and printed, because file_exists('/usr/local/etc/apache/httpd.conf') returns true.

If you're going to banter about exploits, make sure the fix you provided is a real fix.

As others mentioned, an array of allowed files is the way to go, because local or remote files, you don't want people including stuff they shouldn't be doing.

I agree

Rich2k
01-09-2004, 05:46 PM
Originally posted by Acecool
I agree

Yeah I just object to the comment at the top of that post which makes it sound like he's saying all PHP coders are bad programmers. Some of use spend a lot of time investing in security and making sure the scripts can't be abused.