Prevent direct access to a php include file

后端 未结 30 1003
盖世英雄少女心
盖世英雄少女心 2020-11-22 06:32

I have a php file which I will be using as exclusively as an include. Therefore I would like to throw an error instead of executing it when it\'s accessed directly by typing

相关标签:
30条回答
  • 2020-11-22 06:54

    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");
    
    0 讨论(0)
  • 2020-11-22 06:55

    You can use the following method below although, it does have a flaw, because it can be faked, except if you can add another line of code to make sure the request comes only from your server either by using Javascript. You can place this code in the Body section of your HTML code, so the error shows there.

    <?
    if(!isset($_SERVER['HTTP_REQUEST'])) { include ('error_file.php'); }
    else { ?>
    

    Place your other HTML code here

    <? } ?>
    

    End it like this, so the output of the error will always show within the body section, if that's how you want it to be.

    0 讨论(0)
  • 2020-11-22 06:57

    1: Checking the count of included files

    if( count(get_included_files()) == ((version_compare(PHP_VERSION, '5.0.0', '>='))?1:0) )
    {
        exit('Restricted Access');
    }
    

    Logic: PHP exits if the minimum include count isn't met. Note that prior to PHP5, the base page is not considered an include.


    2: Defining and verifying a global constant

    // In the base page (directly accessed):
    define('_DEFVAR', 1);
    
    // In the include files (where direct access isn't permitted):
    defined('_DEFVAR') or exit('Restricted Access');
    

    Logic: If the constant isn't defined, then the execution didn't start from the base page, and PHP would stop executing.

    Note that for the sake of portability across upgrades and future changes, making this authentication method modular would significantly reduce the coding overhead as the changes won't need to be hard-coded to every single file.

    // Put the code in a separate file instead, say 'checkdefined.php':
    defined('_DEFVAR') or exit('Restricted Access');
    
    // Replace the same code in the include files with:
    require_once('checkdefined.php');
    

    This way additional code can be added to checkdefined.php for logging and analytical purposes, as well as for generating appropriate responses.

    Credit where credit is due: The brilliant idea of portability came from this answer.


    3: Remote address authorisation

    // Call the include from the base page(directly accessed):
    $includeData = file_get_contents("http://127.0.0.1/component.php?auth=token");
    
    // In the include files (where direct access isn't permitted):
    $src = $_SERVER['REMOTE_ADDR']; // Get the source address
    $auth = authoriseIP($src); // Authorisation algorithm
    if( !$auth ) exit('Restricted Access');
    

    The drawback with this method is isolated execution, unless a session-token provided with the internal request. Verify via the loop-back address in case of a single server configuration, or an address white-list for a multi-server or load-balanced server infrastructure.


    4: Token authorisation

    Similar to the previous method, one can use GET or POST to pass an authorization token to the include file:

    if($key!="serv97602"){header("Location: ".$dart);exit();}
    

    A very messy method, but also perhaps the most secure and versatile at the same time, when used in the right way.


    5: Webserver specific configuration

    Most servers allow you to assign permissions for individual files or directories. You could place all your includes in such restricted directories, and have the server configured to deny them.

    For example in APACHE, the configuration is stored in the .htaccess file. Tutorial here.

    Note however that server-specific configurations are not recommended by me because they are bad for portability across different web-servers. In cases like Content Management Systems where the deny-algorithm is complex or the list of denied directories is rather big, it might only make reconfiguration sessions rather gruesome. In the end it's best to handle this in code.


    6: Placing includes in a secure directory OUTSIDE the site root

    Least preferred because of access limitations in server environments, but a rather powerful method if you have access to the file-system.

    //Your secure dir path based on server file-system
    $secure_dir=dirname($_SERVER['DOCUMENT_ROOT']).DIRECTORY_SEPARATOR."secure".DIRECTORY_SEPARATOR;
    include($secure_dir."securepage.php");
    

    Logic:

    • The user cannot request any file outside the htdocs folder as the links would be outside the scope of the website's address system.
    • The php server accesses the file-system natively, and hence can access files on a computer just like how a normal program with required privileges can.
    • By placing the include files in this directory, you can ensure that the php server gets to access them, while hotlinking is denied to the user.
    • Even if the webserver's filesystem access configuration wasn't done properly, this method would prevent those files from becoming public accidentally.

    Please excuse my unorthodox coding conventions. Any feedback is appreciated.

    0 讨论(0)
  • 2020-11-22 06:57
    debug_backtrace() || die ("Direct access not permitted");
    
    0 讨论(0)
  • 2020-11-22 06:58

    I found this php-only and invariable solution which works both with http and cli :

    Define a function :

    function forbidDirectAccess($file) {
        $self = getcwd()."/".trim($_SERVER["PHP_SELF"], "/");
        (substr_compare($file, $self, -strlen($self)) != 0) or die('Restricted access');
    }
    

    Call the function in the file you want to prevent direct access to :

    forbidDirectAccess(__FILE__);
    

    Most of the solutions given above to this question do not work in Cli mode.

    0 讨论(0)
  • 2020-11-22 06:59

    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.

    0 讨论(0)
提交回复
热议问题