I have a php script which updates a database. I want to be sure that no one else can call my script remotely and execute it.
I tried this code but it did not work, the refer was always empty because I use https connection.
if (strpos($_SERVER['HTTPS_REFERER'], 'linkedfilm.com') == false)
{
exit();
}
The server is Apache server.
Thanks.
Hello Daina Hodges,
You got a few options to secure this .php script.
You can secure this script by moving it into another directory outside of your DOCUMENT_ROOT
You can add the .htaccess
You can allow only local ip
You could use .htaccess and put your script in a password protected directory.
Or you could use some sort of login and authentication routines on your site so you can login and access that script.
Or you could pass a 'secret' key with you call to the script, quick and dirty
if( $_GET['secret'] != "mysecret" ) exit();
Related
i have some cron files. And it was in under httpdocs. But i decided to move under cron folder. And i change the script.
config.php to ../config.php
When i call script from browser every thing works fine. But when i call from ssh i got en error undefined index : SERVER_NAME
I couldn't run cronjob. What can i do that ?
stock.php file
include_once '../config.php';
require_once CLASS_PATH.'class.product.php';
include_once INC_PATH.'functions.php';
....
config.php file
if ( !defined('ABSPATH') ) {
define('ABSPATH', dirname(__FILE__).'/');
}
define('PROTOCOL',(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') ? 'https' : 'http');
define('HOST', PROTOCOL.'://'.$_SERVER['SERVER_NAME']);
define('CLASS_PATH',ABSPATH.'includes/class/');
define('INC_PATH',ABSPATH.'includes/');
//if (isset($_SERVER['SERVER_NAME'])){
define('PRODUCT_IMG_PATH', 'images/product/');
//}
define('HEAD_META',ABSPATH.'view/head-meta.php');
define('NAVBAR', ABSPATH.'view/navbar.php');
define('HEADER', ABSPATH.'view/header.php');
define('FOOTER', ABSPATH.'view/footer.php');
The reason is that when you are running through ssh or command line you are in CLI mode, therefore none of those CGI variables can be used. It's recommended to use getenv() command instead which supports some of defined variables in CLI mode. However you need to configure and define them in you php.ini
You may need to look at Command line usage documentation for more details
How are you running it from cron? It seems that the server variables aren't being found when you run from terminal - which would make sense if you were php-running the file on the server. The SERVER-variables in php are set by the webserver - i.e. what answers a request over port 80 to the files in a specific location.
Here's php's documentation on server variables.
http://www.php.net/manual/en/reserved.variables.server.php
You web server is the one who fills the php $_SERVER array. I quote from the manual (http://www.php.net/manual/en/reserved.variables.server.php):
The entries in this array are created by the web server. There is no
guarantee that every web server will provide any of these; servers may
omit some, or provide others not listed here.
Obviously, if you call your script from the command line, there's no web servers to fill the $_SERVER array, and that's the reason of your problem.
To solve it, you can modify your config.php to load predefined values to the variables you need in case they don't exist. It would be something like this for every undef var:
if (!isset($_SERVER['SERVER_NAME'])) $_SERVER['SERVER_NAME']="localhost";
Is it possible to hack website by sending PHP variable from another host? For instance:
I have a file secure_content.php:
<?php
if($fgmembersite->Login()) //placed at the top to avoid the warning: headers already sent
{
$login = TRUE;
}
//intentionally removed {else $login === FALSE}
// echo some contents
if ($login === TRUE)
{
//echo secure data
}
else
{
echo "You are not authorised to view this content";
}
?>
And an attacker have a file in his webserver named: hack.php
<?php
$login = TRUE;
require_once "http://mywebsite.com/secure_content.php";
?>
Is it possible the hacker to view the secure content?
How to avoid processing our scripts using include/require from other webserver?
No, it isn't possible to process your scripts from another webserver.
Your server will not give the entire PHP source code to the remote server, rather it will give the output of running your script.
No worries here.
You cannot avoid processing your scripts using include from other webserver, because that is not possible in the first place. So there is nothing to prevent.
As Denis said, though I want to add few interesting caveouts from personal experience administrating sites.
People often rename their php scripts into something like secure_content.php.back while editting the file - fear it. As then, the attacker can download your PHP script accessing (secure_content.php.back). Having source-code is not enough to hijack variables, but is already a vulnerability. It will get amplified, if your secure_content.php.back has some configuration variables like $database_password
Also, if you are to uninstall PHP from your web-server, Apache (or whatever) will serve your secure_content.php as a text file - is also a risk. Just keep in mind when you are to tinker with your PHP engine.
No. Your server will run the script and then send the results to the evil server.
A similar thing to what you mention can occur in older versions of PHP if register_globals is on. This would allow someone to call http://mywebsite.com/secure_content.php?login=true.
This would cause $login to be set to true at the start of the script. Thankfully register_globals is now off by default and is deprecated in 5.3 and removed in 5.4. See here.
I want to prevent users from running my cron job manually. Apart from using an unpredictable filename I want to have some sort of check in code.
Obviously using any clientside headers is a waste of time so I thought the easiest way around this would be to detect the presence of $_SERVER['SERVER_NAME'] which as far as I know is not set in CLI.
Are there better ways of doing this?
Have a look at php_sapi_name. It returns the type of interface between web server and PHP.
Example:
<?php
if(php_sapi_name() == 'cli') {
// CLI
}
else {
// HTTP
}
For more information, and additional examples, have a look at http://www.electrictoolbox.com/determine-php-run-via-http-or-cli/.
in your .htaccess
Options -Indexes
order allow deny
deny from all
allow from YOUR SERVER IP ADDRESS ONLY
Check for IP address, if its local, or server ip then run it, otherwise return.
$ip = getenv('REMOTE_ADDR');
My cron jobs are in a folder that is password protected using htpasswd. You can set an easy password and be sure nobody will lose his time trying to access it. I don't use any IP-based techniques because this is a server dependency I don't want to have.
Is it possible to configure my local setup (running Wampserver) so that my PHP application thinks HTTPS is enabled locally? The application requires HTTPS (by checking $_SERVER['HTTPS']) before doing stuff, but I don't want to go through the hassle of a full HTTPS setup locally. Thanks.
Edit: I should mention this isn't an application I wrote, just one I am tasked with maintaining. This check is performed in many places (50-100) around the server.
You can mock up this variable in your init file by adding:
$_SERVER['HTTPS'] = true;
Shouldn't be too hard. Even though it is a superglobal, you can still redefine it like any other variable. Do this at the top of your code, and when it gets to the check, it should still recognize it as true.
$_SERVER['HTTPS'] = true;
Move the check into an object
class Request
{
function isHttps()
{
// check for local site here,
// or better still, use a DevRequest class or a Mock to pass
// your local requirements
}
}
and then use
if($request->isHttps()) {...}
I have Wamp (server called emerald) running and Mamp running on my Mac. People register on Mamp. Emerald is basically file hosting.
Emerald connects to Mamp's mysql database, to login users. However, I want to create a directories for new registrations on Emerald using PHP.
How can I do this? I have tried using this code:
$thisdir = "192.168.1.71";
$name = "Ryan-Hart";
if(mkdir($thisdir ."/documents/$name" , 0777))
{
echo "Directory has been created successfully...";
}
But had no luck. It basically needs to connect the other server and create a directory, in the name of the user.
I hope this is clear.
You can't create directories through http. You need a filesystem connection to the remote location (a local hard disk, or a network share for example).
The easiest way that doesn't require setting up FTP, SSH or a network share would be to put a PHP script on Emerald:
<?php
// Skipping sanitation because it's only going to be called
// from a friendly script. If "dir" is user input, you need to sanitize
$dirname = $_GET["dir"];
$secret_token = "10210343943202393403";
if ($_GET["token"] != $secret_token) die ("Access denied");
// Alternatively, you could restrict access to one IP
error_reporting(0); // Turn on to see mkdir's error messages
$success = mkdir("/home/www/htdocs/docs/".$dirname);
if ($success) echo "OK"; else echo "FAIL";
and call it from the other server:
$success = file_get_contents("http://192.168.1.71/create_script.php?token=10210343943202393403&dir=HelloWorld");
echo $success; // "OK" or "FAIL"
Create a script on another server that creates the dir and call it remotely.
Make sure you have security check (+a simple password at least)
There is no generic method to access remote server filesystems. You have to use a file transfer protocol and server software to do so. One option would be SSH, which however requires some setup.
$thisdir = "ssh2.sftp://user:pass#192.168.1.71/directory/";
On Windows you might get FTP working more easily, so using an ftp:// url as directory might work.
As last alternative you could enable WebDAV (the PUT method alone works for file transfers, not creating directories) on your WAMP webserver. (But then you probably can't use the raw PHP file functions, probably needs a wrapper class or curl to utilize it.)
I know this is old but i think this might me useful, in my experience:
if(mkdir($thisdir ."/documents/name" , 0777))
doesn't work, i need to do it:
mkdir($thisdir, 0777);
mkdir($thisdir ."/documents" , 0777);
mkdir($thisdir ."/documents/name" , 0777));
hope it helps :)