2

What is the correct to allow a PHP file only to be executed if it is included in another PHP file?

For example, let's say I have my main application file "main.php". This file includes "settings.php" as such:

// www.mydomain.com/MAIN.PHP
<?php
require 'settings.php';
?>

// www.mydomain.com/SETTINGS.PHP
<?php
// DO SOMETHING
?>

How can I precent "settings.php" from being executed if a user runs "www.mydomain.com/SETTINGS.PHP" from their browser?

I'm looking for a PHP-Only solution.

Andrew
  • 2,691
  • 6
  • 31
  • 47
  • 2
    simple: don't put it into your site's document root. If you don't want it to be available, then don't put it where it IS available. – Marc B Jul 14 '14 at 17:06
  • If the script just contains variable assignments, but doesn't print anything or modify anything on the server, what's the problem if someone executes it? They can't see the variables. – Barmar Jul 14 '14 at 17:13
  • @Barmar - That's a good point but I guess I feel more comfortable knowing my core classes and settings are hidden or inaccessible except where I explicitly include... – Andrew Jul 14 '14 at 17:16
  • Then like @MarcB said, put them where they can't be accessed. – Barmar Jul 14 '14 at 17:17
  • The only files you should have under public_html is the index file and assets such as Javascript, images and css. If you have PHP files within the home directory you may want to rethink your application and how it works. – Ian Jul 14 '14 at 17:25
  • @Ian - that's not always possible. For example, what about PHP pages where you do an Ajax post? Obviously having those pages outside the webroot will not work... – Andrew Jul 15 '14 at 01:50
  • @Andrew as I generally use a framework the routing part goes through domain.com/+module(/+options), therefore you can still do ajax requests which routes through the index page, yet doesn't need to be in the home directory – Ian Jul 16 '14 at 10:01

5 Answers5

5

The first solution is obviously to not put it in a web accessible location. Sometimes this isn't feasible, so you can make a check:

// www.mydomain.com/MAIN.PHP
<?php
define('SOMETHING', true);
require 'settings.php';


// www.mydomain.com/SETTINGS.PHP
<?php
if(!defined('SOMETHING')) { die(); }
// DO SOMETHING

Or you can use something similar to this in a global header include:

if(strpos($_SERVER["PHP_SELF"], basename(__FILE__) !== false) { die(); }
AbraCadaver
  • 78,200
  • 7
  • 66
  • 87
2

One way is to check for a "magic" value that is set when you include settings.php.

// www.mydomain.com/MAIN.PHP
<?php
$magic = "c00f0c4675b91fb8b918e4079a0b1bac";
require 'settings.php';
?>

// www.mydomain.com/SETTINGS.PHP
<?php
if ($magic != "c00f0c4675b91fb8b918e4079a0b1bac") {
    die("Cannot be executed independently.");
}
// DO SOMETHING
?>

This protects against casual fooling around; it will not protect you from someone who can read your PHP files, i.e. someone who has access to your server.

Bob Brown
  • 1,463
  • 1
  • 12
  • 25
  • Also, see this question: http://stackoverflow.com/questions/24748475/which-method-is-more-secure-suitable-for-blocking-access-to-a-subdirectory-using – Bob Brown Jul 15 '14 at 01:15
1

In settings.php, you can check if the $_SERVER['SCRIPT_FILENAME'] is settings.php; if it is: the script is being accessed directly, if not: the script is being included

//settings.php
echo $_SERVER['SCRIPT_FILENAME']; // echoes 'settings.php'

//file.php
include 'settings.php'; //echoes 'file.php';

This means you can do something like this:

//settings.php
if($_SERVER['SCRIPT_FILENAME'] != 'path/to/the/settings/file/settings.php'){
    define('SETTING', true);
}
Jonan
  • 2,485
  • 3
  • 24
  • 42
0

If you want to allow include of remote files, the directive allow_url_include must be set to On in php.ini

See reference

Community
  • 1
  • 1
  • He doesn't want to include a remote file. He wants to prevent an include file from being accessed as a normal web page. – Barmar Jul 14 '14 at 17:10
0

Another method is to check if the requested file (usually $_SERVER['REQUEST_FILENAME']) matches __FILE__. __FILE__ is set to the name of the file you are currently in, even if in an include. If they are the same, then you are loading a file directly. If different, it can be assumed as included.

Jonathan Kuhn
  • 15,279
  • 3
  • 32
  • 43