PHP Tips – Manage correctly file inclusion

In this article we’ll treat a quite simple argument but if badly managed can lead to big problems, the topic is the inclusion of files.
According to my experience I established three golden rules that should be enough; if you come up with other ones, I’ll be glad to talk about it.
1. Include once
Only if strictly needed , it’s always better to specify that we want to execute the inclusion only one time using the commands include_once or require_once.
Let’s do an example to understand why:
The file 1.php contains the definitions of a series of constants.
The files 2.php and 3.php need a few of the constants defined in file 1.php, so we’ll include 1.php in both files.
In the page page.php we need the functions contained in 2.php and 3.php so we will include them.
At this point if in 2.php and 3.php we included 1.php with the command include, in page.php a series of errors at the notice level will raise, because we are trying to define twice the same constants contained in 1.php.
Using include_once we resolve these problems. Therefore we use include and require only when we need to repeat the inclusion.
2. Absolute paths
If we want to include files in a file that in turn will be included, it’s important to do it through absolute paths. Take for example the following structure:

Now the file db_config.php will contain the connection parameters to the database and has to be included in the file db_connect.php that in turn will provide the connection.
However it would be a mistake to include it this way:
include_once ‘db_config.php’;
The file db_connect.php in fact will be used in index:php, so we should include db_config.php in db_connect.php this way:
include_once ‘inc/db_config.php’;
But what happens if the file db_connect.php has to be used also by admin.php?
A mess.
If we want to include files in a file that in turn will be included, we have to do it through absolute paths. Therefore we’ll include db_config.php in db_connect.php in this way:
include_once dirname(__FILE__) . ‘/db_config.php’;
The magic constant __FILE__ returns the absolute path where the file physically resides (different from $_SERVER[‘PHP_SELF’] that returns the path where the file is executed). Therefore with dirname() we pick up only the path.
At this point we only have to add the path of the file we intend to include, in this case it’s in the same folder, so it’s very simple.
This way, in whatever point we’ll go to include db_connect.php, the file db_config.php will be included correctly because taken from its absolute position.
Note: Starting from PHP 5.3 the magic constant __DIR__ has been introduced that is equivalento to:
dirname(__FILE__)
3. Pay attention to dynamic inclusions
A lot of attention, indeed. This code:
include $_GET[‘page’];
with no adjustments it is equivalent, in terms of security, to a suicide.
To avoid problems, I send you to the very complete guide on security written by Cristian, in particular to this article, at the indirection chapter.
Conclusion
As you see, even for a very simple argument like file inclusion, there’s a lot to say.
*****************************************
L'immagine principale dell'articolo è stata fornita da @Fotolia


5 comments
Trackback e pingback
-
Tweets that mention PHP Tips – Manage correctly file inclusion | Your Inspiration Web -- Topsy.com
[...] This post was mentioned on Twitter by Web RSS News and Tom Bangham, V. Tavares (E-Goi). V. Tavares (E-Goi) ... -
PHP Tips – Manage correctly file inclusion | Garry Lachman
[...] Read full article here [...]



really useful tips you sharing. thanks
Thanks Dzinepress
1. Mostly wrong. Only use the _once variants when you can’t find better ways to ensure singularity of file includes. They are very very slow.
2. Viable. But worth mentioning __DIR__ which was adding in 5.3 and is nice.
3. Should be changed to “If you need this tutorial, don’t use Dynamic includes” because this is a serious security vulnerability and is varsity level PHP. And especially because you offered no tips on what to avoid and why.
For those interested. If you MUST have dynamic includes pick the first one of these you can make work:
a. Use a switch statement to pick the includes, not letting user input into the include statement at all.
b. This and all below should begin the include statement with a hard-coded starting path. Eliminate everything other than alphanumeric characters from the variable. /[^A-Za-z0-9]/
c. Allow only a few select additional characters but not “.” or “/”.
d. Only allow “.” or “/” but not both. (Still potentially risky)
This above is all to avoid letting users change directories away from the ones you intended and changing the file extension from the one you specified. Letting users do so can mean letting them output any file on your system like; configuration files, password files, backup files, user lists, and other data that can be useful in cracking your server.
What’s worse is that because this is seen as expected behavior on a lot of systems, it happens without being logged, and the only trace left by the attacker will be messages that the PHP user loaded some files, and often not even that.