PHP detect if connection is browser or script - php

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'

Related

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

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.

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.

Make php file function for specific website

Suppose I would have a PHP file on my server. Now in my HTML I have a piece of Javascript code which refers to the path/url of the PHP file. Is it possible to restrict the PHP code to function only for a specifed website?
Short answer: yes.
My assumption is that you have the same PHP script on many different domains, and you want it to behave differently for some domains
First off you need to make sure your PHP script has a reliable way of detecting which domain it's running on. This should be in your configuration somewhere. I wouldn't trust HTTP_REFERER and $_SERVER may not have what you need.
If you have this it should be easy enough to decide what the script should do.
try:
if ($_SERVER['SERVER_NAME'] == 'site1') {
// some code...
} else if ($_SERVER['SERVER_NAME'] == 'site2') {
// some other code...
} else {
// some other code...
}

How to end a PHP session on page close

I have several pages inside an AJAX directory. I don't want these pages accessible directly so you cannot just type in the URL of the page within the AJAX directory and access it. I "solved" this by using a PHP session on the page that calls it as follows:
Main page:
<?php
session_start();
$_SESSION['download']='ok';
?>
and on the ajax page I have this:
<?php
session_start();
if($_SESSION['download']!=='ok'){
$redirect='/index.php'; //URL of the page where you want to redirect.
header("Location: $redirect");
exit;}
?>
The only problem is that if a user goes through the correct process once, the cookie is stored and they can now access the page directly. How do I kill the session once they leave the parent page?
thx
why use session ?
if i understood what you want:
<?php /// Is ajax request var ?
if (isset($_SERVER['HTTP_X_REQUESTED_WITH'])) {
if (strtolower($_SERVER['HTTP_X_REQUESTED_WITH'])=="xmlhttprequest") {
// do your ajax code
} else {
// redirect user to index.php since we do not allow direct script access, unless its ajax called
$redirect='/index.php'; //URL of the page where you want to redirect.
header("Location: $redirect");
exit();
}
} ?>
A really simple solution is to open up each of the files you want to protect from direct URL entry & add the following to the top:
<?php if (isset($_GET['ajax']) != true) die();?>
Now get rid of your redirect script since it's useless now. You don't need to use sessions for this. Every time you request a page, use it's direct URL, just add ?ajax=1 to the end of it.
By adding the ?ajax=1, PHP will set a key of 'ajax' to the $_GET global variable with the value of 1. If ?ajax=1 is omitted from the URL then PHP will not set a key of 'ajax' in $_GET and thus when you check if it's set with isset() it will return false, thus the script will die and not output anything. Essentially the page will only output data if ?ajax=1 is at the end of the URL.
Someone could still "spoof" the URL and add '?ajax=1' themselves, but that is not the default behavior for people or web browsers. If you absolutely need to prevent this then it will be much more complicated, e.g. using templates outside of a publicly available folder. Most other "simple" solutions will have the same "spoofing" potential.
There's really no way to accomplish this with a 100% certainty - the problem is, both AJAX and regular web browser calls to your web site are using the same underlying protocol: HTTP. If the integrity and security of your site depends on keeping HTTP clients from requesting a specific URL then your design is wrong.
so how do you prevent people from directly accessing files inside certain directories while still letting the site use them??
Create a controller file. Send all AJAX requests to this controller.
ajax-control.php
<?php
$is_ajax = true;
include "ajaxincludes/test.php";
// ... use the ajax classes/functions ...
ajaxincludes/test.php
<?php
if (!isset($is_ajax) || !$is_ajax)) {
exit("Hey you're not AJAX!");
}
// ... continue with internal ajax logic ...
If clients try to access the file directly at http://mysite/ajaxincludes/test.php they'll get the error message. Accessing http://mysite/ajax-control.php will include the desired file.
I don't think there is a surefire way to do what you are asking, since HTTP request headers can be faked. However, you can use $_SERVER['HTTP_REFERER'] to see if the request appears to be coming from another page on your site.
If the rest of the security on your site is good, the failure of this method would not grant the user access to anything they were not already able to access.
I've never tried this but maybe you could do something with jQuery's .unload() and then call a PHP page to unset() the session.
Why not (on Ajax page):
session_start();
if($_SESSION['download']!=='ok'){
$redirect='/index.php'; //URL of the page where you want to redirect.
header("Location: $redirect");
exit;
}
// do whatever you want with "access granted" user
// remove the download flag for this session
unset($_SESSION["download"]);

How to detect if file is being accessed or requested?

A I have a PHP file that if the user access it directly he should be redirected to another location, but if my script call it through ajax, it should do nothing special.
For example, if a user access
/site/page.php
he should be redirected to
/index.php?view=page
But if he is on the index.php?view=page the file should load without redirects.
How can I do that?
EDIT: If you want to determine if a script was requested through Javascript or not, you'll have to signal it somehow.
Several toolkits define the header X-Requested-With. In that case, you can check for a Javascript call with:
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) &&
strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
//requested with Javascript
}
You can check the size of the result given by debug_backtrace.
Alternatively (better), you can check $_SERVER['SCRIPT_FILENAME']:
if (realpath(__FILE__) == realpath($_SERVER['SCRIPT_FILENAME'])) {
//this one was requested; not in include
}
By "it should do nothing special" do you mean it shouldn't redirect?
So the Q is really if user accesses a URL for a PHP file directly, it should redirect, if thru AJAX, process as normal?
(to really clarify, you mean thru a URL and not thru a include statement, right?)
Answer: You can't. Artefacto mentions the HTTP_X_REQUESTED_WITH header - sure, but that can be faked.
Is it really so bad is the user accesses the URL directly?
If the answer is "OMG Yes!" then maybe there is something wrong with how the system is designed.
Redesign it until the answer is "Actually, I suppose it wouldn't really hurt."
If you really don't want someone accessing /site/page.php, you should consider moving /site/page.php outside of your web root. Then make your index.php load it as needed:
<?php
$includes = "/path/to/includes"; // specified in a config file somewhere
if ($_GET["view"] == "page") {
require_once(path_join($includes, "page.php"));
DoStuffInPageDotPHP();
}
else {
DoSomethingElse();
}
?>

Categories