0

I have a PHP script which is typically run as part of a bigger web application. The script essentially makes some changes to a database and reports back to the web user on the status/outcome.

I have an opening section in my PHP:

    require $_SERVER['DOCUMENT_ROOT'].'/security.php';
    // Only level <=1 users should be able to access this page:
    if ( $_SESSION['MySecurityLevel'] > 1 ) {
        echo '<script type="text/javascript" language="JavaScript">window.location = \'/index.php\'</script>';
        exit();
    }

So, basically, if the authenticated web user's security level is not higher than 1, then they are just redirected to the web app's index.

The script works fine like this via web browsers.

Now to my issue...

I want to also cron-job this script - but I don't know how to bypass the security check if ran from the CLI.

If I simply run it from the CLI/cron with 'php -f /path/to/report.php' and enclose the security check in a "if ( php_sapi_name() != 'cli' )", it spews out errors due to multiple uses of $_SERVER[] vars used in the script (there may be other complications but this was the first error encountered).

If I run it using CURL, then the php_sapi_name() check won't work as it's just being served by Apache.

Please can anyone offer some assistance?

Thank you! :)

hgp-it
  • 31
  • 4
  • If your script relies on variables that aren't always defined, you either need to wrap every instance in a conditional `isset()` or similar, or you need to define some dummy data up front. – moopet Oct 28 '16 at 08:49
  • Obviously, I meant to say if the user's security level IS higher than 1 then they are redirected to the index! – hgp-it Oct 28 '16 at 08:52
  • @moopet Well, in its current state the $_SERVER variables are always defined - and required. For instance, to create the connection to the database, there is a "require $_SERVER['DOCUMENT_ROOT'].'/dbconnect-rw.php';". So I need to be able to include this additional script whether it's ran from the web for CLI. – hgp-it Oct 28 '16 at 08:55
  • Not an answer to your question, but note that if `/index.php` does not have forther authorization, this application is vulnerable to forced browsing - a user can just browse to that php even if not redirected. Maybe that's not the case just wanted to raise attention. :) – Gabor Lengyel Oct 28 '16 at 09:48

1 Answers1

0

If you invoke the script through the CLI some of the $_SERVER variables will be defined however their values may not be what you expect: for instance $_SERVER['DOCUMENT_ROOT'] will be empty so your require will look for a file called 'security.php' in the filesystem root. Other arrays such as $_SESSION will not be populated as the CLI does not have a comparable concept.

You could get around these issues by manually defining the variables (see "Set $_SERVER variable when calling PHP from command line?" however a cleaner approach would be to extract the code that makes the database changes to a separate file which is independent from any specific and that does not depend on any SAPI-specific variables being defined.

For instance your PHP script (let's call it index.php) could be modified like this:

 require $_SERVER['DOCUMENT_ROOT'].'/security.php';
 require $_SERVER['DOCUMENT_ROOT'].'/db_changes.php';';

    // Only level <=1 users should be able to access this page:
    if ( $_SESSION['MySecurityLevel'] > 1 ) {
        echo '<script type="text/javascript" language="JavaScript">window.location = \'/index.php\'</script>';
        exit();
    } else {
      do_db_changes();
    }

Then in the SAPI-agnostic db_changes.php you would have:

<?
function do_db_changes() {
  // Do the DB changes here...
}
?>

And finally you would have a file, outside the web root, which you can invoke from cron (say cron.php):

<?
  require("/absolute/path/to/db_changes.php");
  do_db_changes();
?>

Like this you can continue using index.php for the web application and invoke cron.php from cron to achieve your desired results.

Community
  • 1
  • 1
llmora
  • 563
  • 5
  • 11