how to make php page disabled from browser - php

I'm writing a PHP script that I want to disable from web access (I will ask users to move it out of the web root and execute via CLI, but you never know if they'll listen!)
Is there a simple function that occurs to anyone to make the page die if it's requested by a browser?
Thanks for any ideas.

You could test whether the script is being run through the CLI using php_sapi_name().
It can return a whole bunch of different possible values when run on a HTTP server - difficult to make a reliable distinction there - but there seems to be only one possible return value for the CLI: cli.
If you're looking for an all-purpose solution, make sure you read the comment thread below for more detailed discussion on some potential gotchas.

'PHP_SELF' The filename of the
currently executing script, relative
to the document root. For instance,
$_SERVER['PHP_SELF'] in a script at
the address
http://example.com/test.php/foo.bar
would be /test.php/foo.bar. The
FILE constant contains the full path and filename of the current (i.e.
included) file. If PHP is running as a
command-line processor this variable
contains the script name since PHP
4.3.0. Previously it was not available.
http://www.php.net/manual/en/reserved.variables.server.php

I'm not a PHP expert but you could check the $_SERVER variable ?

You can use php-sapi-name function to detect if script was requested by web server or cli interface.

$sapi_type = php_sapi_name();
if (substr($sapi_type, 0, 3) != 'cli') {
die "You are not using CLI".PHP_EOL;
}

you can use php-sapi-name or you can use the predefined constant which is marginally faster (although you'd never notice!)
<?php
if(PHP_SAPI != 'cli') exit;
// continue

Related

How can I ensure my PHP script is only run as a schedule job and not when run from a browser?

Each time when I am opening e.g. retrieveContent.php the script is executed and insert records into the database. Since I use this script in a schedule job it should not be a problem.
However I noticed that a user found the script path and did opened the retrieveContent.php file which was executed and inserted a record in the database.
How can I prevent browser transactions by a user using PHP? Thanks in advance!
Look at the php_sapi_name() function. It will tell you if you're running in CLI (command-line interface).
http://php.net/manual/en/function.php-sapi-name.php
You can also move the PHP script to somewhere outside of your web server's document tree.
You have lots of options. I'll mention just three:
Append a query parameter, that only you know and that is hard-coded in the script, e. g. retrieveContent.php?key=secret. (Or in CLI mode, a secret command line argument.) Check this parameter in your script and only perform the actions if it matches the hard-coded value.
If your scheduled job is performed on the same server where the script resides, move the script to a separate directory protected by a .htaccess file with the following content:
Deny from all
Allow from localhost
If your scheduled job fetches the script via HTTP, figure out, which user agent is sent in $_SERVER['HTTP_USER_AGENT'], and only perform the actions if the script is accessed by that user agent. But this is less safe, since the user can fake the user agent (if he manages to find out the correct one).
Pass a secret argument to your script when called via CLI and confirm it on PHP side. For example:
-- terminal --
php script.php secret-argument
-- script.php --
<?php
if(!isset($argv[1]) || $argv[1] != 'secret-argument')
{
die('restricted access');
}
// Rest of script
$argv is a global PHP variable that Contains an array of all the arguments passed to the script when running from the command line.
Couple of ways this could be done:
if(php_sapi_name() != 'cli'){ die();} or if(PHP_SAPI != 'cli'){ die();}
The following solutions won't always work depending on server settings:
Check for $_SERVER['argv'], it is only set on CLI execution if (empty($_SERVER['argv'])) { die();}. This is mostly true, unless your server loads those on HTTP request.
if(!empty($_SERVER['REMOTE_ADDR'])) { die();} REMOTE_ADDR is empty when called via CLI.
if(empty($_SERVER['TERM'])) { die();} PHP loads the TERM variable with the terminal type. Same is true for $_SERVER['SHELL'] or $_SERVER['USER'].

Limit execution only through localhost

This could be a kind of strange question. I have a php file in a public web site where I have access to the server. For the moment we do not need to set Cron job for this file execution. However I need to limit the execution of this file only via localhost. I don't have any precise idea about the way should I do this. Is there any way to detect whether the request is localhost or not? I mean with PHP. Or should I need to handle this via security setting or firewall of the server?
I'm assuming you mean you want to be able to execute the script only from the server, and not via the web from another host. You have two options:
Option 1
move it out of the public_html folder. There is no reason you should not take this option, unless there is something preventing you from doing so. In that case,
Option 2:
Wrap the entire code in the following if statement
if (php_sapi_name() == 'cli')
{
//your code
}
Alternatively,
if (php_sapi_name() != 'cli')
die();
//your code
This ensures your script will only run if invoked from the command line, and not via the web.
You could check IP addresses like this:
if($_SERVER["REMOTE_ADDR"]!=$_SERVER["SERVER_ADDR"])
{
exit;
}

Possible for Google Bot to Execute PHP Script

I have a CRON job php script that I just set up not too long ago. However, I noticed that the PHP file executed (without the cron job activating). It appears that it happened when a Google Bot crawled the file, because I noticed that the following engine visited my page:
http://www.google.com/bot.html
My question is:
1) Is it possible, that by crawling my webpage, it could have executed the script?
2) How can I "hide" the CRON file from Google?
3) Would it be smart to place this file in somewhere other than my public_html directory?
Many thanks!
1) of course it is
2) see robots.txt (http://www.searchtools.com/robots/robots-txt.html)
3) yes. but if for some reason you depend on calling it via a http daemon you can use a little trick.
eg. first line of code:
if(!isset($_GET['execute'])
exit;
in your crontab:
http://server.tld/file.php?execute=1
1) If the file is placed in a public web directory, then yes, it could be executed by Googlebot (or any other visitor)
2) You could add a Disallow clause for it in your robots.txt. Any regular user can still go and execute it by visiting if you do this.
3) Yes.
You can use also php-cli. Define if it is cron job:
define('_DOING_CRON_', true);
Then in php file:
if(_DOING_CRON_ && php_sapi_name() != 'cli'){
die("You cannot get here: this is only cron task.");
}
Runifus' answer above solved it for me, however the Cron job command line does not work with the ? in the url to pass the querystring as I learnt here: Cron Jobs calling a PHP script with variables
It should be like so:
http://server.tld/file.php execute=1
also the php condition is missing a closing parenthesis
if(!isset($_GET['execute'])) exit;

Get apache linux user from php

I'm on a foreign linux system and need to determine the user that apache runs on (and so does php).
The aim:
I need to get the owner of the script (this is no problem as I can use SplFileInfo) and compare it to the owner of the apache process.
I'm open to any alternative proposals.
Regards,
Mario
Edit:
Additional info:
The script is a thumbnail generator, that uses an XML file to generate thumbs from larger images. The script needs to create folders and write files. As I cannot influence the php configuration and I do not have any shell access, this has to be done very silently.
The creation process stopps via exception and sends a mail on failue. As most of php's function cannot throw exceptions on failue, I need some manual checks to determine the environment I'm in. Therefore I need the apache user to compare it to some directory or fileowner.
You can call the php exec function to execute whoami:
<?php echo exec('whoami'); ?>
see posix_getuid() and posix_getpwuid()
Some complicated answers here.
This works for me:
$user = getenv('APACHE_RUN_USER');
Not sure if this is just a new thing that been added to apache since this question was asked but it's definitely there now.
phpinfo will dump a lot of system information. For apache2 installs, there is a section that displays the apache user and group ids. Try creating a php script that just has one line, a call to phpinfo(), and open it in your web browser.
Some php script must be run on apache user (cli), whoami is not appropriate in that case.
Here is my solution :
$output = exec('apachectl -S 2>/dev/null | grep User');
$apacheUser = preg_match('/name="([^"]+)"/', $output, $match) ? $match[1] : 'www-data';

How to distinguish command-line and web-server invocation? [duplicate]

This question already has answers here:
Closed 14 years ago.
Is there a way to distinguish if a script was invoked from the command line or by the web server?
(See What is the canonical way to determine commandline vs. http execution of a PHP script? for best answer and more detailed discussion - didn't find that one before posting)
I have a (non-production) server with Apache 2.2.10 and PHP 5.2.6. On it, in a web-accessible directory is my PHP script, maintenance_tasks.php. I would like to invoke this script from the command line or through a HTTP request (by opening in a browser). Is there some variable that allows me to reliably determine how script is invoked?
(I already tackled the issues of different views for each type of invocation and HTTP response timeout, just looking for a way of telling the two invocation types apart)
I'll be trying different things and add my findings below.
Duplicate: What is the canonical way to determine commandline vs. http execution of a PHP script?
If called from command line, the server variable HTTP_USER_AGENT is not set. I use this constant to define, whether the script is called from command line or not:
define("CLI", !isset($_SERVER['HTTP_USER_AGENT']));
UPDATE: Since this answer is still marked as the 'correct' one, I'd like to revise my statement - relying on the "User-Agent" header can be problematic, since it's a user-defined value.
Please use php_sapi_name() == 'cli' or PHP_SAPI == 'cli', as suggested by Eugene/cam8001 in the comments.
Thanks for pointing this out!
I've compared the $_SERVER superglobal in both invocations. It seems that $_SERVER['argc'] (i.e. number of arguments passed to the script) is only set when running from shell/command line:
<?php
if (isset($_SERVER['argc'])) {
define('CLI', true);
} else {
define('CLI', false);
}
That seems to work both on Linux and Windows hosts. (First I thought about checking for some of the environment variables, but those are different for every operating system. Also, all the $_SERVER['HTTP_*'] headers are missing in the CLI version, but I'm not sure if that's reliable enough.)

Categories