views:

7370

answers:

13

I have a php file which I will be using as exclusively as an include. Therefor I would like to throw an error instead of executing it when it's accessed directly by typing in the URL instead of being included.

Basically I need to do a check as follows in the php file:

if ( $REQUEST_URL == $URL_OF_CURRENT_PAGE ) die ("Direct access not premitted");

Is there an easy way to do this.

+1  A: 

The easiest way is to set some variable in the file that calls include, such as

$including = true;

Then in the file that's being included, check for the variable

if (!$including) exit("direct access not permitted");
Kyle Cronin
This is dangerous if register_globals is on.
jmucchiello
*PHP* is dangerous if register_globals is on.
David Precious
@bigpresh super dangerous to be clear.
Unkwntech
+10  A: 

The best way to prevent direct access to files is to place them outside of the web-server document root (usually, one level above). You can still include them, but there is no possibility of someone accessing them through an http request.

I usually go all the way, and place all of my PHP files outside of the document root aside from the bootstrap file - a lone index.php in the document root that starts routing the entire website/application.

Eran Galperin
This is a great solution if you are able to do so. I only recently had to start working with shared webhosts and discovered one of many annoyances to be that everything must be inside the docroot.
Beau Simensen
In every hosting provider I worked with I always had access to (exactly) one level above the document root.
Eran Galperin
At some hosts (including my current one), you can point your domain to whichever folder you wish.
Dinah
+16  A: 

The easiest way is to put your includes in a directory and deny access to that directory in your .htaccess file.

Chuck
Thanks, since I do have full control over the server where I run this app, this is the answer I went with.
Alterlife
if you have full control of the server is better if you put the config into a directory directive into the virtual host config file. Apache read it only once on startup, .htaccess is read on every access and slow down the server
Eineki
+9  A: 

Add this to the page that you want to only be included

<?php
if(!defined('MyConst'){die('Direct access not premitted');}
?>

then on the pages that include it add

<?php
define('MyConst', TRUE);
?>
Unkwntech
I really need to learn to type quicker. This is the same way I would suggest, as its more secure than a method that uses a variable to check. Since with some PHP setups it may be possible to override the variable.
Mark Davidson
This is how a few 'mainstream' applications handle it. I know Joomla does it this way and I think Wiki, Wordpress, and others as well.
Unkwntech
Maybe the message is too helpful for a hacker (no real user would find these pages), you can simply send a redirect header and stop the php processing.
bandi
Just send a 404 header and exit -- the error page will look identical to normal 404 pages (at least on Apache).
gnud
A: 

Do something like:

<?php
if ($_SERVER['SCRIPT_FILENAME'] == '<path to php include file>') {
    header('HTTP/1.0 403 Forbidden');
    exit('Forbidden');
}
?>
kmkaplan
This will not prevent it from being loaded in the browser.
Unkwntech
+1  A: 

An alternative (or compliment) to Chuck's solution would be to deny access to files matching a specific pattern by putting something like this in your .htaccess file

<FilesMatch "\.(inc)$">
    Order deny,allow
    Deny from all
</FilesMatch>
Kevin Loney
+2  A: 

Actually my advice is to do all of these best practices.

  • Put the documents outside the webroot OR in a directory denied access by the webserver AND
  • Use a define in your visible documents that the hidden documents check for:
      if (!defined(INCL_FILE_FOO)) {
          header('HTTP/1.0 403 Forbidden');
          exit;
      }

This way if the files become misplaced somehow (an errant ftp operation) they are still protected.

jmucchiello
+3  A: 

I have a file that I need to act differently when it's included vs when it's accessed directly (mainly a print() vs return()) Here's some modified code

if(count(get_included_files()) ==1) exit("Direct access not permitted.");

The file being accessed is always an included file, hince the == 1.

null
+1  A: 

Besides the .htaccess way, I have seen a useful pattern in various frameworks, for example in ruby on rails. They have a separate pub/ directory in the application root directory and the library directories are living in directories at the same level as pub/. Something like this (not ideal, but you get the idea):

app/
 |
 +--pub/
 |
 +--lib/
 |
 +--conf/
 |
 +--models/
 |
 +--views/
 |
 +--controllers/

You set up your web server to use pub/ as document root. This offers better protection to your scripts: while they can reach out from the document root to load necessary components it is impossible to access the components from the internet. Another benefit besides security is that everything is in one place.

This setup is better than just creating checks in every single included file because "access not permitted" message is a clue to attackers, and it is better than .htaccess configuration because it is not white-list based: if you screw up the file extensions it will not be visible in the lib/, conf/ etc. directories.

bandi
A: 

I had this problem once, solved with:

if (strpos($_SERVER['REQUEST_URI'], basename(__FILE__)) !== false) ...

but the ideal solution is to place the file outside of the web-server document root, as mentioned in another anwser.

mati
+1  A: 
<?php
if (eregi("YOUR_INCLUDED_PHP_FILE_NAME", $_SERVER['PHP_SELF'])) { 
 die("<h4>You don't have right permission to access this file directly.</h4>");
}
?>

place the code above in the top of your included php file.

ex:

<?php
if (eregi("some_functions.php", $_SERVER['PHP_SELF'])) {
    die("<h4>You don't have right permission to access this file directly.</h4>");
}

    // do something
?>
Blogging Tips
A: 

What Joomla! does is defining a Constant in a root file and checking if the same is defined in the included files.

`defined('_JEXEC') or die('Restricted access');`

or else

one can keep all files outside the reach of an http request by placing them outside the webroot directory as most frameworks like CodeIgniter recommend.

or even by placing an .htaccess file within the include folder and writing rules, you can prevent direct access.

Pradeesh kumar
A: 

The following code is used in the Flatnux CMS (http://flatnux.altervista.org):

if ( strpos(strtolower($_SERVER['SCRIPT_NAME']),strtolower(basename(__FILE__))) )
{
    header("Location: ../../index.php");
    die("...");
}
Lwangaman