PHP & cron: security issues - php

Whats the best way to ensure that only CRON executes PHP scripts, and not someone else who stumbled upon your php scripts..
I was thinking a Password Variable.... but is this a legal CRON command? :
/usr/local/bin/php -f /home/mysite/public_html/dir/script?password=12345
This way people cannot be able to execute the same commands when visiting the PHP script via HTTP (unless they know the password)
Thanks.

You should keep this file outside of public_html
/usr/local/bin/php -f /home/mysite/script
// is secure from public access

Suppose if u don't want anybody to run the file via http then set the cron by using php command as you are doing and add htacess to cron folder to block http request to the folder
by adding
deny from all to htacess
Suppose if u want the cron folder to be password protected then it can be done as mentioned in the URl
http://www.elated.com/articles/password-protecting-your-pages-with-htaccess/

Don't put the script inside your public_html (or anywhere under your document root) directory if you only need to execute it from cron. It really is that simple.

You can send params to a PHP file via the command line. Just not like you are thinking.
http://www.php.net/manual/en/reserved.variables.argc.php
However, you also want to keep this out of the public html folder, like the others are saying. So you CAN'T surf to them. PHP run from command line doesn't need to be in any kind of webserver watch folder.

Or you can block execution by IP
do something like this:
($_SERVER['REMOTE_ADDR'] == "127.0.0.1") or die('NO ACCESS');

Having a password could work, but :
Writing a password in your crontab is a bad idea because other local users might be able to read it
Your syntax won't work (it would try to run the script "script?password=12345". Parameters can't be named in shell script, so you would have to run "script.php 12345"
A valid solution would be to check in your PHP script, that the current environment looks like the one provided by cron when launching commands. Cron specific environment variables might help you ensure your script is being run fby cron and not a user.

Related

SSH from python script which is triggered by PHP backend code

I am trying to call a python script from php (Using xamp).
The python script internally calls a shell script and the shell script has an ssh and scp command.
On executing the PHP back-end code using exec I observe the following errors in xamp log file.
The python script works fine through command line
Could not create directory '/sbin/.ssh'.^M
Failed to add the host to the list of known hosts (/sbin/.ssh/known_hosts).^M
Permission denied, please try again.^M
Permission denied, please try again.^M
Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).^M
Could not create directory '/sbin/.ssh'.^M
Host key verification failed.^M
Presumably, the python script is being run by a different user when it's called by PHP than when you run it by hand, which does not have appropriate permissions to do whatever actions the script is trying to perform. So you'll need to tweak permissions / user groups for the various things the script is going to be trying to do in order for it to run successfully.
Looking at this question is probably a good starting point:
How to check what user php is running as?
Once you identify the user that is actually running the script, you can try running the script as that user and then fixing problems as they come up.
I couldn't say for sure without seeing the Python script, but this probably has something to do with what the working directory is when the php user calls the script. You should either use absolute paths in your code or use
os.chdir(<path>)
to make sure you're using the correct working directory. Note if you do this, you'll probably run into permissions errors as mentioned in the other answer since .ssh and files in it are usually accessible only to the user whose directory it's in.

PHP Script as Cron doesn't work, but does from CLI

I have a php script that triggers some magento actions, and I set it to a cron of:
cd /home/dir/public_html; php -f file.php;
This starts the script, however it does not finish executing for some reason, the cron runs as the user "user", and when I run the command from the terminal as root it works perfectly. All the files it uses are chowned to user however. I thought it was an issue with paths which is why I added the CD command to the front of it, however that wasn't it.
I'm thinking this may be an issue with the creation of a lock file, I have it create a lock file, run the script, then delete the lock file in order to prevent it from running if it already is. The lock file is generated but never deleted, my knowledge is if it creates it as user "user" then it should be able to delete it as that user as well.
Any thoughts? Much appreciated.
Try to put the full path of PHP, or define the PATH variable in the first lines of crontab:
PATH=/usr/local/bin:/usr/bin:/bin:/usr/games:/sbin:/usr/sbin
Edit : moreover, you can log your script like that :
* * * * * cd /home/dir/public_html; /usr/bin/php -f file.php; &>/tmp/file.log
Instead of calling the php from within the cronjob, call a shell script which is calling the php file then.
You can then change the environment the script is running in w/o the need to change the cronjob and you can easier test-drive the cron command (as you can just call the shell-script).
You can then, in the shell script, change the directory where the php-script expects to be in which will most certainly solve your issue.
Additionally you can change ini directives, handle logging and shell error handling, like piping STDERR to a file etc.
This is not exactly your problem, but the information given in this question might solve your issue: How can I force PHP Version for Command Line?.

exec() runs via command line but not web

I have a PHP script involving exec() that will run fine from the command line but not in a web context. The script is simply this:
<?php exec('echo "wee" > /home/jason/wee.txt');
If I call this script wee.php and run php wee.php, it works fine and wee.txt gets written.
If I go to http://mysite.com/wee.php, the script pretends to run fine but wee.txt doesn't actually get written.
Any idea why this is happening?
The web server runs as a different user, and that user does not have permission to write to your home directory.
The other posters are correct to suggest the web server user doesn't have rights to write to your home directory. To see if they are right try modifying the code to write to /tmp/wee.txt. That should be world writable.
Another possibility is that php can be configured to disable calling exec(). See http://www.cyberciti.biz/faq/linux-unix-apache-lighttpd-phpini-disable-functions/
Your web server probably (correctly) doesn't have the appropriate permissions to write to a home directory.
Noticed you are writing to /home/jason. Note that apache will be the one running this command (i.e. www-data user if using Ubunut or Debian). Does the process have the correect rights to write to that folder?

Ensure a PHP script is only ever run as a cron job?

How can I ensure a user can not run a PHP script and that it is only ever run as part of a cron job?
You can set an environment variable in your crontab. A line like IS_CRON=1 can be placed at the beginning of your crontab, then check in your php program for get_env("IS_CRON") == 1.
Of course, you should also use file permissions as they're not so easily bypassed. If this is run as part of root's cron, chown root:root yourscript.php and chown 700 yourscript.php.
As ircmaxell says, it'd be better to run as a user other than root assuming you don't need root permissions for what you're doing. I was just taking a guess about your setup.
How about having your PHP script check if $_SERVER['REMOTE_ADDR'] is empty, and if it is not, then have the script exit without doing anything further.
There are probably a number of ways to do this. Off the top of my head, I would say that placing it in a directory owned by root, and only readable by root might get close to achieving the effect you are looking for.
Are there any processes you are looking specifically to restrict it from? If so, using permissions, make it not readable to any of those processes.
I would suggest setting an environment variable within your crontab and then checking for this within your PHP script
Create a user for cron jobs, and set permissions of the script so it can only be run as this user. Of course you then need to put the script in that user's crontab, which you can do by logging in as that user and running crontab. Just don't give that user's password to just any other user...
At first I was also thinking of setting an environment variable which would prevent running this script from the web... But just not putting the script in the space where the web server looks for pages for websites, would do the same.
And nothing is stopping a random user from first setting the environment variable and then running the script.

Set php file permissions so only my server's curl can run

I have a PHP script that I don't want anyone to be able to run through their browser.
It sends emails and is called via curl by my server's cron, yet needs to be in the public www directory. What permissions or owner do I need to set the file to to allow only my server's curl to execute (or do I mean read) the file?
I'm on centos.
Thanks!
You could either limit access to the files by placing a .htaccess file with appropriate access limitations in the directory or by implementing a basic password check at the beginning of your php file like this:
<?php
$password = $_GET['password'];
hash = '40bd001563085fc35165329ea1ff5c5ecbdbbeef'; //precalculated sha1 hash of your password
if (sha1($password) != $hash) {
die('Forget it!');
}
For added security this could be further refined, but you get the idea ...
If you can, I would recommend doing it a different way: Running the script through the CLI (calling php -f in the cron job) and having the PHP script check how it is run. You can find out whether the script is called from the Command Line Interface using php_sapi_name(), and terminate when it's being called from the web. That would be the most secure solution as far as I can see.
If you really need to get it through curl, use Josh's solution or define a passkey that needs to be added to the script as a get parameter:
curl domain.com/script.php?password=123456
not terribly secure as the passkey will be visible in the crontab, but should provide decent protection against access from the outside, especially if you combine it with checking $_SERVER["REMOTE_ADDR"] and making sure it is 127.0.0.1.
Why not just use php-cli to run it from the command line instead of through curl?
If you really have to host it you can do something like this in your .htaccess
<Directory /your/path/>
Order allow,deny
Allow from 192.168.1.0/24
Allow from 127
</Directory>
This is impossible, as phrased. From what I can tell, I think there are a number of options that you could use to address your problem:
You can chown root or another user and then chmod 700, and then call the script from a cronjob using PHP's command line functionality from the owner's crontab file.
If you need to access the file over curl, then you're hitting the web server, and the web server needs to be able to execute/read the script, which would allow anyone to execute the script.
Another option would be to use rule based access control, as described here: http://library.linode.com/web-servers/apache/access-control/rule-based-access to make sure that only connections originating from your server will be able to access the file in question, but this is itself not entirely ideal.
There are other solutions of course, but I hope this is helpful.

Categories