Search code examples
phpservercron

What is the risk of whitelisting IP addresses in PHP scripts used for Cronjobs before running them


I have some PHP scripts on my server which I use for periodic cron jobs (for daily rapports and updating leaderboards for example).

To prevent outsiders from running these scripts manually (by running http://url/script.php in the browser for example) I included the following code to check the IP-address before running the actual script. Where XX.XX.XX.XX represents the IP address of my own network.

    $remote = isset($_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : '127.0.0.1';
    $whitelist = array('XX.XX.XX.XX', '127.0.0.1');

    if (!in_array($remote, $whitelist))
    {
        exit;
    } 

So now I have the following questions:

  • How safe is this?
  • What are the risks?
  • How can I make this more safe?
  • Are there other (better) solutions?

PS. My previous questions was closed because someone thought this question is a duplicate of PHP IP Address Whitelist with Wildcards. But I this is not the case! That question is about using wildcards in whitelisting while this questions is about the safety and risks of this solution.


Solution

  • The presented method is not completely secure.

    PHP acts as a text preprocessor, which means that in the event of a web server gateway error, the script content can be sent with the mime-type text/html, which is a risk of revealing sensitive data such as passwords to SQL database or (s)ftp accounts.

    Administrative scripts placed in public also carry the risk of their unauthorized execution if the IP address controlled in the script was a shared (or dynamically transmitted) address. Cron scripts are executed using php-cli, therefore the web server gateway is not needed for anything and IP analysis in the script becomes unnecessary if it is outside the public directory.

    Remote execution using e.g. curl could be the only reason for placing administrative scripts in the public space of the www server. This is usually a weak solution because then the script performs the php interpreter (and not php-cli) with other settings, usually with drastically limited execution time. However, if it is for some reason necessary it should be in a separate directory to which access is limited to specific IP addresses using .htaccess (and/or .iptables) and with assigned username and password by using htpasswd (Basic Auth).

    The ideal situation is when the public directory of the www server (hereinafter referred to as public) contains only static content (img, css, js ... files) and the application trigger located in the parent directory. Example structure is:

    /home/username/domainname/(apps,crons,public,tmp)
    

    The apps directory should contain all application files and directories. The public directory should contain only static content (for order in some subdirectories) and a symbolic link to the main file of the application which can be obtained with the command:

    ln -s ../apps/app.php index.php
    

    Some server configurations do not allow the use of symlinks. Then you can use the index.php file containing:

    <?php
    include('/home/username/domainname/apps/app.php');
    

    This solution is a bit worse because in the event of a gateway failure, the directory structure is revealed. However, sensitive data is still secure because the web server cannot display the content of files that are not there.

    The presented IP analysis can be used to display part of content for authorized addresses, assuming that the php file itself is outside the public web server. If these are entire websites, however, I would prefer to use iptables or .htaccess to manage access to them.