Is using php_sapi_name() to detect CLI reliable? [duplicate] - php

can the user manipulate the value which is returned by php_sapi_name()?
I have a script which looks like this:
if( php_sapi_name() !== "cli" ){
die( "NoAccess" );
}
// Do some admin stuff
This script should only (!) be called through command line. Is the code above safe? Or can somebody call the script through HTTP and execute it beyond the if condition?

php_sapi_name()'s return value is safe to rely on. It's not generated from user data.
You shouldn't have this script accessible to your web server though if you don't want it to be called from your web server. If you cared about safety, this script wouldn't be accessible at all.
You also mentioned .htaccess... don't use that, use a proper config file elsewhere. .htaccess has to be loaded and parsed for every request, which is not efficient.

Related

PHP detect if connection is browser or script

I am trying to prevent users from connecting to certain pages with a script. Thus, is there any method I can use to detect if a connection to a specific web page is a client browser versus an automated script?
I know certain headers can be spoofed, but is there another mechanism I can use; say like if unable to set a sesseion_start or setCookie. Do those return true/false values if able or unable be to be set?
Something like:
$sessionID = session_id() ;
$isSet = setCookie('cookieName',$sessionID, [ .... ]) ;
if ($isSet == false) {
... do something to kill the session
... or do something to redirect
}
Is this even possible? And even if it is, I know this probably isn't reliable, but what would be a better or more reliable method?
And to clarify, detect if its a script and if so, kill it before even serving the rest of the html page.
If you are trying to prevent pages from being called entirely, you can reliably do this with a combination of using an .htaccess file and a php "check" file .. This will check to see if the requested file came from your scripts, or an outside source. Make a directory, and put your "hidden" script files in it along with the following 2 files:
.htaccess
php_value auto_prepend_file check.php
check.php
<?php
if( !#$_SERVER["HTTP_X_REQUESTED_WITH"] ){
header('/page_404.php'); // Or whatever you want it to do.
exit;
}
All the .htaccess directive does is make check.php happen before every script call -- So technically you COULD just include check.php at the top of every file .. But I find this a more complete, elegent solution.
You can check with php_sapi_name() if you are running on CLI.
This example will only allow scripts from CLI.
if (PHP_SAPI !== php_sapi_name()) {
die('CLI only');
}
You can reverse the condition to make it only running for web server.
if (PHP_SAPI === php_sapi_name()) {
die('Web Server only');
}
You can do it with $_SERVER['HTTP_REFERER'] but it can be fake/dummy made.
<?php
if (isset($_SERVER['HTTP_REFERER']) && strtolower(parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST)) === 'example.com') {
//your code
} else {
die('Bots are not allowed!');
}
You can use UserAgent
(You can see how to get it here : How to get user agent in PHP)
This will let you know user web browser which -I assume- will be different for 'scripts'

PHP: Is php_sapi_name() safe (can the user manipulate it)?

can the user manipulate the value which is returned by php_sapi_name()?
I have a script which looks like this:
if( php_sapi_name() !== "cli" ){
die( "NoAccess" );
}
// Do some admin stuff
This script should only (!) be called through command line. Is the code above safe? Or can somebody call the script through HTTP and execute it beyond the if condition?
php_sapi_name()'s return value is safe to rely on. It's not generated from user data.
You shouldn't have this script accessible to your web server though if you don't want it to be called from your web server. If you cared about safety, this script wouldn't be accessible at all.
You also mentioned .htaccess... don't use that, use a proper config file elsewhere. .htaccess has to be loaded and parsed for every request, which is not efficient.

securing PHP page with GET var

I have a page that I want to execute via cron. It just does some pretty simple archiving stuff, nothing super high-security, no DB access etc.
Is it a secure practice to simply require a GET var to be present in order to execute the page? So myarchiver.php would be something like:
<?php
$mysecret_word = "abc123";
if ($_GET['secret'] == $mysecret_word){
// execute my stuff here
}
Then you'd just call myarchiver.php?secret=abc123 in the crontab and the process would run, while any wrong answer or attempt to execute the page with no secret would simply present a blank page (with no extra server load).
I realize this is not "secure" against man in the middle attacks and if the site was compromised-- but I believe in general it's plenty secure to keep this script from being fired by random script kiddies and other idiots who may somehow know about its existence? The thing I'm guarding against is random malicious users who may know about this script bombarding it with requests in order to dos/tie up resources.
EDIT TO ADD: the server is not accessible via SSH and the cron is being executed on a remote machine-- so it must be done via an http request.
Thanks for input.
If this script is never going to be run from the browser, you should place the file outside of your web root directory where browsers cannot reach it and just have your cron run the script at the alternate location. It would definitely be the most secure way to do it.
If you're on a shared hosting environment, you may need browser access for manual running. I would just use SSH to manually run the file from its location since it only takes me a couple seconds to login to SSH and get to the directory. Personally, I just prefer not to have excess pages laying around on my website.
First off, why not just check the IP address of the server making the request?
If it has to be done via an HTTP request and simply checking the IP address isn't an option, you can have your cron run a script similar to "runcron.php". That script would in turn make a CURL or WGET request to the actual cron script you want to run.
That would allow you to pass a dynamic hash instead of a static key. That would prevent someone from just repeating the HTTP request if they happen to sniff the traffic. For the hash you could use anything dynamic like the date combined with a salt.
Example:
if (md5('secretword') . date('H')) == $_GET['hash']) { // do cron }
That would at least rotate your key once an hour.
Also, crontab won't let you pass GET variables. You'll have to do this -
/usr/bin/php /home/blah.php hello
Then in the script -
$argv = $_SERVER['argv'];
echo $argv[1];
Someone correct me if I'm mistaken.
This is a technique that facebook uses on their logout.php file, so that if someone sends a link to logout.php it won't log them out. I would recommend doing this.
$mysecret_word = "abc123";
if ($_GET['asd2edxc32cwqcxad'] === $mysecret_word){
// execute my stuff here
} else {
error_log('oopis');
header('HTTP/1.0 404 Not Found');
die();
}

How to check if a php script is being called by another script on the server?

I have a script scripty.php
Sometimes this script gets called through the browser.
Other times it gets called by another script on the server.
How can I (securely) check within scripty.php to see whether or not it is being called by the server?
in the form of an http URL
The $_SERVER["REMOTE_ADDR"] variable that gives you the IP address of the client who made the request should be 127.0.0.1 when the script is called from the server.
you can create a variable before including your script
$by_script = true;
include("new_script.php");
and check it inside
Just a guess: You want to know, if the script its called trough a browser, or from CLI
var_dump(PHP_SAPI);
On any script that will be calling it define a constant like define("IN_SCRIPT") and within scripty.php you can check for the constant to determine if it's inside another script or not.
e.g.
if(defined("IN_SCRIPT")){
// We must be inside a script right now!
}
or
if(!defined("IN_SCRIPT")){
// We are working alone now
}
consider a file named test.php, this is the only code contained:
echo str_replace("\\","/",$_SERVER["SCRIPT_FILENAME"]);
echo str_replace("\\","/",__FILE__);
when a user execute* test.php by browser url, this is the output:
"C:/xampp/htdocs/test.php"
"C:/xampp/htdocs/test.php"
otherwise, differ (( in this case another.php was executed by browser url, who include test.php ))
"C:/xampp/htdocs/another.php"
"C:/xampp/htdocs/test.php"

PHP: invoking remote server from my php server?

how can I invoke a php script on a remote server from my server code ?
I'm currently using:
header('Location: http://www.url.com/script.php?arg1=blabla');
in my code, but it doesn't work.
thanks
If you mean by invoking just "calling" it, so you only need it to run, then you can use curl.
If you mean by invoking that you want it to act the same as include, then you can't trough http (the server does ofcourse not return code, but runs it). You might be able to obtain the file trough other means (ftp?), and then include it, but that seems like a bit of a hack.
If you mean by invoking that you want to redirect the user to the page, then this should work:
header('Location: http://www.site.nl/');
exit;
(your script continues to run after a header call, so you might need to call that exit). How doens't your code work for you? (I'm guessing because you want one of the other options)
If you only want to invoke the script you can simply use $result = file_get_contents('http://www.example.com/');.
Your version using header() will as said above redirect the user.
Use cURL, it gives you much wider manipulation options.

Categories