About the Author

Chris Shiflett

Hi, I’m Chris: web craftsman, community leader, husband, father, and partner at Fictive Kin.


Where Are Your PHP Includes?

Do not store your PHP includes in document root. This is a terrible practice. Here is just one reason why:

http://www.google.com/search?q=inurl%3Adb.inc

Don't recommend naming PHP includes with a .php extension. Don't recommend including code in PHP includes that prevents direct requests. Don't recommend the following for denying requests for .inc resources:


    Order allow,deny
    Deny from all

The problem is not that these techniques are bad, but rather than they are neither optimal nor sufficient. If you employ these techniques, do so only to adhere to the principle of defense in depth. If you're only going to implement one safeguard, choose the best one.

Do not store your PHP includes in document root. There are no exceptions. There are no excuses.

About this post

Where Are Your PHP Includes? was posted on Thu, 24 Mar 2005. If you liked it, follow me on Twitter or share:

29 comments

1.Mitch Pirtle said:

Some applications cannot comply with your command, Chris!

For example, we have to write software that runs in a mass-hosting environment, and those accounts don't have access to the server beyond the document root. In many cases, the document root is also the home directory for that account.

A barbaric practice indeed, and normally I would agree with your opinion on this, but there are some circumstances where there is little wiggle room.

What might be interesting is to see how you could properly secure libraries, or identify/document the most optimal ways of protecting libraries that must be there.

Thu, 24 Mar 2005 at 21:29:06 GMT Link


2.Chris Shiflett said:

I'm aware of this situation, and I hate it. Unless I'm missing something, there is no advantage to making /home/chris document root instead of /home/chris/public_html. Anyone stuck on a shared host like that should find a different host.

In your case, I guess you can't really avoid dealing with the situation. I just hope that you make users explicitly choose such an approach, defaulting to something a little better. :-)

Thu, 24 Mar 2005 at 21:38:47 GMT Link


3.Armand said:

My practice is to include on the top of every script , which is included in the main front controller, the following code.

if (!defined('SECURE_INCLUDE'))

{

die('No Permission on ' . __FILE__);

}

in the main script:

define('SECURE_INCLUDE', 1);

I think it's secure or not?

Thu, 24 Mar 2005 at 22:23:28 GMT Link


4.Christian Dickmann said:

@Armand:

Well, if your Apache config is corrupted, the user might see the source of your files.

Thu, 24 Mar 2005 at 23:27:04 GMT Link


5.Jared Williams said:

Yes, having libraries outside of the public root is prefereable.

But, imo, including a PHP library shouldn't have any side-effects, other than defining classes, functions or constants.

That way even if it is accessed directly, it can't be exploited, like some PHP applications have been, and probably will be in the future.

(Also possibly increases modularity/reusability of code, if no reliance on the global keyword or $GLOBALS.)

Armand, surely better to send back a status 404 Not Found, if going to implement a check explictly.

Fri, 25 Mar 2005 at 01:01:27 GMT Link


6.Alan Knowles said:

I'm not sure that directive is particually sensible. A better rule of thumb would be:

Library's are libraries - not scripts that do things.

Although from the number of projects I've seen idiotic code with random function's placed in 'library files' that nobody's going to find or remember a month after they wrote it, I sometimes wonder, if a bettter directive would be:

Dont release open source projects with libraries that are not classes..

Fri, 25 Mar 2005 at 01:18:18 GMT Link


7.Chris Shiflett said:

Armand, that technique alone is subpar. In fact, that's the point of what I'm saying. An include does not have to be within document root for you to include it, so storing it there is an unnecessary risk. Taking unnecessary risks is rarely a good idea.

Alan, the many db.inc files indexed by Google aren't "scripts that do things." It's not wise to rely on such poor safeguards for something that's so easy to avoid.

Fri, 25 Mar 2005 at 01:34:11 GMT Link


8.Armand said:

> that technique alone is subpar. In fact, that's the point of what I'm saying.

Boarding on an airplane embeds high risks, because you have to make confidence to a lot of technique and the pilot. That’s not optimal but that’s life.

A secure configured http, sql server, OS, or secure server room and server geographic place (earthquake? political situation?), is far from the job scope of a php programmer who can only take care that a script in it self is secure. Else it would be a never ending story.

Fri, 25 Mar 2005 at 06:04:17 GMT Link


9.Basti said:

Even if you are on a shared host you have a simple option to protect files like db.inc - just add a PHP extension and call it db.inc.php

I don't see the down side of this method - it protects the code and even if somebody would call it they would get a blank page.

Fri, 25 Mar 2005 at 08:46:32 GMT Link


10.Leendert said:

I don't see the problem either. Just give your php files a .php extension and be fine. If the PHP interpreter fails at some point, who cares? As long as you store _sensitive_ data outside the webroot.

Fri, 25 Mar 2005 at 10:42:00 GMT Link


11.Chris Shiflett said:

Arnaud wrote:

> Boarding on an airplane embeds high risks, because you have to make

> confidence to a lot of technique and the pilot. That's not optimal but that's

> life.

For your analogy to make sense, you would have to board a plane that takes off and lands at the same place. :-)

There's no gain. It's an unnecessary risk.

> A secure configured http, sql server, OS, or secure server room and server

> geographic place (earthquake? political situation?), is far from the

> job scope of a php programmer who can only take care that a script in it self

> is secure.

That's right, and the topic being discussed is well within your job scope. Don't try to evade your responsibility as a PHP developer.

Basti wrote:

> Even if you are on a shared host you have a simple option to protect files

> like db.inc - just add a PHP extension and call it db.inc.php

Did you not read what I wrote? :-)

This (the .php extension) should only be used as a redundant safeguard and not the only safeguard. If you're only going to implement one safeguard, choose the best one.

On shared hosts, document root isn't the only unsafe place. You might want to try to run a script like this:

http://shiflett.org/code/browse.phps

You can follow the technique mentioned at the end of this article for protection:

http://shiflett.org/articles/security-corner-mar2004

Leendert wrote:

> As long as you store _sensitive_ data outside the webroot.

That's true, but data exposure isn't the only risk. There are also the unknown risks of executing code out of context, and these are application dependent.

Rather than offer a complex best practice, I chose to offer a simplistic one. As you can see from the comments, it's hard enough to get people to adopt best practices without complicating things with special cases and caveats.

Fri, 25 Mar 2005 at 16:10:53 GMT Link


12.Harry Fuecks said:

Think you're right. There are problems though, number one, as I see it, being ease of use always trumps security concerns, in terms of what people actually end up doing.

What people expect to be able to do with any PHP project is just unzip and go and I'd hazard a guess that at least 90% of Open Source PHP apps cater to that.

Skipping the definition of the word library for a moment, placing the files that get included (be that class or configuration) outside the web root will typically involve some of;

- A further step after unzipping - move the files to be included somewhere

- Understanding how include paths work

- An environment that allows it

- Possibly understanding of Unix permissions

- Possibly modifying the code - many Open Source projects expect you to place files to be included below the web root.

Think all of those act as disincentives to security, whether the cause of lack of knowledge or time.

Can't see any obvious solutions but think, fundamentally, there may need to be a shift in attitude towards shared hosting.

If we say "ease of use" is _why_ PHP is a success, shared host is _where_ PHP is a success as can be seen here: http://www.php.net/usage.php "PHP: 18,455,683 Domains, 1,317,871 IP Addresses".

The shared hosting environment is PHP's grass roots and together they've become a platform which is almost as predictable as Windows - as software developers we can target it, knowing there's a large user base.

But often get the feeling that those that know PHP well would like to forget is exists, while in pursuit of the "Enterprise" of happily running their own servers.

And at the same time it's practically impossible to make a typical shared hosting entirely secure, without locking down everything and removing the ease of use. It surprises me that the shared hosting providers aren't up in arms.

Add to that the type problems like the one you've just described, which are common with people that know "just enough" PHP and it's a recipe for trouble, as perhaps the phpBB XMas special demonstrates.

On that note, think before anyone cries "stupid users", this remark needs considering: http://usablesecurity.com/2005/03/17/path-of-least-resistance/#more-5

"When we arrive at a 'solution' that consists of blaming the user, it's time to take a step back and ask ourselves what we're really trying to accomplish. Is the primary goal to serve the user’s needs or merely to disclaim responsibility? If we're really interested in serving the user's needs, then whether the user is at fault is beside the point. Users are bound to be at fault sometimes; after all, they are human. The real issue is whether we, as designers of the tools, can do any better. If we can improve the user's chances of getting it right, we should."

Daring a flame war, reckon if those with access to cvs.php.net and beyond were willing sign up for a $5/month shared hosting account, with only FTP access to modify files, and put their personal blogs there, we'd pretty quickly have some innovative solutions to the type of security issues that follow PHP.

Fri, 25 Mar 2005 at 20:34:28 GMT Link


13.Jared Williams said:

Whilst your on a theme of blogging "Things thou shalt not do". How about this one.

Constructing SQL statements dynamically (using string operations or variable injection) when using PHP5 & PDO.

Whilst it was/is pretty much the only way to use SQL in pre-PDO times. These methods should be retired.

Fri, 25 Mar 2005 at 21:46:26 GMT Link


14.Alan Knowles said:

the day you classify configuration files (db.inc) as libraries, is the day you have totally lost the security ball game..

'protecting your configuration data'... is maybe a better byline..

Sat, 26 Mar 2005 at 04:11:46 GMT Link


15.Chris Shiflett said:

Harry, you raise some very good points, many of which I'm sure are shared by Mitch, since he's a Mambo developer. I should point out that my recommendation is not meant to neglect the shared hosting environment. If anything, I think I'm neglecting open source applications that must be painfully easy to install. I see these as two different things, and you're right (as is Mitch) to be mindful of the latter.

In my talks, I almost always mention that security must be balanced with usability. I also make sure to mention that these two things are not necessarily opposites. It's nice to see a "Usable Security" blog that focuses on the intersection of these things. Thanks for the link.

Alan, I've changed "libraries" to "includes" to be more generic and to hopefully avoid pointless semantic debates (library is a generic term). I feel justified in pointing out that the day you think the outcome of the "security ball game" depends upon semantics is the day you totally miss what the game is about. :-)

Sat, 26 Mar 2005 at 04:40:11 GMT Link


16.Armand said:

I always try to make the setup procedures of my applications as simple as possible. It's one feature what most end users expects, what makes an application popular and what i understand under the term "usability".

1969 was the first moon landing of Aldrin and Armstrong. This was only possible because they trusted to others (this was a crazy but extraordinary job!).

Now in 2005, if we expect from end users to deal manually with endless configuration file settings, understanding how include works ...... we are no further than in 1963. But what i expect from a end user is to take its responsibility by not choosing the cheapest shared hosting platform to run a site.

If we cant trust in the fingers of those who have access to the httpd.conf, we are lost.

Sat, 26 Mar 2005 at 08:43:31 GMT Link


17.Ammar Ibrahim said:

on some shared hosting enviroments you're not allowed to change Apache's settings, not even with a .htaccess file.

So this leaves us with very few options if we're gonna write applications to run securely on shared hosts. I always add '.php' to my include files, so include files have '.inc.php'

If I'm able to have the includes directory outside the doc root that would be great, but otherwise it'll go under the doc root, still it would be "safe".

Now here's one problem for those who think that by just adding '.php' to your include files you're safe. Actually you're not. e.g. you have an include file that resets tha database 'reset_db.inc.php' . Now if you're includes directory is in your doc root, executing certain scripts "Even if it gives the user blank page" still it would be a disaster.

Sat, 26 Mar 2005 at 16:57:56 GMT Link


18.Nev said:

@Armand

your code is good.

I also take this code-part to check the permissions:

IF (1 >= SIZEOF(GET_INCLUDED_FILES())) {

DIE();

}

also I put my Includes out of the webroot, but I can put it everywhere.

to solve this problem, i take a php-file, named __go_admin.php, it's in the web-root.

in my files I include this file, like this:

$Sys_Dir = '../';

INCLUDE ($Sys_Dir.'__go_admin.php');

in this __go_admin.php, there are 2 lines:

$Sys_Dir .= '../admin/';

INCLUDE ($Sys_Dir.'global.php');

You see, I change the path of the same Variable.

so I am very flexibal with the place for my includes.

Sorry, about my bad english, i trained it hardly

Tue, 29 Mar 2005 at 06:28:39 GMT Link


19.James Benson said:

Could always just chmod 000 your include files then chmod 755 in your script before including a file then also chmod 000 at the end of your script, this way the file cannot be viewed without changing permissions first and is essentially locked to the public.

Fri, 03 Jun 2005 at 20:55:38 GMT Link


20.Adair said:

Continue adding that kind of content, please!

Thu, 27 Oct 2005 at 04:00:39 GMT Link


21.Scottie said:

Nice site, we'll share with friends.

Fri, 28 Oct 2005 at 17:29:39 GMT Link


22.Ariella said:

Nice site

Sat, 05 Nov 2005 at 15:20:36 GMT Link


23.Katey said:

looks great

Wed, 09 Nov 2005 at 20:01:49 GMT Link


24.karma said:

can someone write example code for include from out of root folder?

Thu, 24 Nov 2005 at 08:35:08 GMT Link


25.orbach said:

Adding a .php extension takes care of any problems. You state:

"This (the .php extension) should only be used as a redundant safeguard and not the only safeguard. If you're only going to implement one safeguard, choose the best one."

But you never explain exactly what the problem is or how the solution of adding .php is incomplete. You just state your conclusion without any justification. How is using a subfolder better than using the php extension? As far as I can tell, users will never see the php code in a file with the php extension. In addition, files in subfolders could be accessed as well as files at the root.

The only reason to use subfolders for included, or any other files, is organization, not security.

Just my .02 cents.

Sat, 22 Jul 2006 at 21:37:09 GMT Link


26.orbach said:

Try this one:

http://www.webtelegraph.co.za/includes/db.inc

Sat, 22 Jul 2006 at 21:47:27 GMT Link


27.orbach said:

or these:

http://www.bjpldx.edu.cn/xyl/include/db.inc

http://www.artplus.it/include/db.inc

Sat, 22 Jul 2006 at 21:52:28 GMT Link


28.orbach said:

Ammar wrote:

"Now here's one problem for those who think that by just adding '.php' to your include files you're safe. Actually you're not. e.g. you have an include file that resets tha database 'reset_db.inc.php' . Now if you're includes directory is in your doc root, executing certain scripts "Even if it gives the user blank page" still it would be a disaster."

This is a more enlightening statement. One thing is to protect the data (which a php extension does well), another is to protect the execution of the script. The reset_db script Amman describes should only be executed by authorized users. Otherwise, the script should be considered "safe". For example, the database being reset is really a temporary database and we don't care about its contents.

This shows that security does not come from absolute "dogma" like the ones discussed here. It results from careful analysis and addressing the issues found.

A good example of bad security is the "primitive spam prevention techniques" Chris uses when submitting posts here (adding Chris to a text field) This does nothing to prevent a spammer from adding posts here.

Sat, 22 Jul 2006 at 22:09:55 GMT Link


29.Glenn said:

In terms of securing files, is the following configuration equivalent to placing files outside of the webroot?

My shared hosting provider gave me a random domain name assigned to /some/path/htdocs. So this was my webroot, and I don't have access to anything above this.

However, I can change the random domain so that its destination is some/path/htdocs/randomdomain; this acts like my new webroot.

Now, if I create a directory like some/path/htdocs/phpincludes, will this be the equivalent of placing this directory outside of my webroot?

Thanks in advance. I've been looking for an answer on this, but haven't found anything that directly addresses it.

Mon, 26 May 2008 at 21:45:43 GMT Link


Hello! What’s your name?

Want to comment? Please connect with Twitter to join the discussion.