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

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.

Related

How do I get a PHP file to automatically run itself?

I have a PHP file, x.php, that outputs b.xml every time it is run. The way I do this is by using crontab to run the x.php file. The problem is that due to the server's settings, the new file has permissions of 400. So I also have another crontab line to change file b.xml permissions to 777 so that x.php can run over it next time.
I feel like I am making this too complicated. Is there any way to make this a bit simpler?
Quick Answer
You'll need to chmod the file to be 777 in the x.php script.
After b.xml has been created, run this line:
chmod('path/b.xml', 0777);
Note you should always specify octals when using chmod.
A better way?
When you run a cron job, you should take special note of the user that is running the cronjob.
Generally on a shared server you will have your own login and thus the cron job runs as that user. My question to you - is that user the same as your web server? often php runs as "apache" and cron might be running as "tanner". In that case, setting b.xml to be owned by tanner, and having a permissions 400 means that only tanner can change the file.
To solve this, if you don't have access to umask, one way would be to change your cron job to run as the webserver:
su -c "php /home/jonathan/public_html/b.php" apache
This may or may not work depending if you are allowed to switch to apache as the user. do not forget to switch apache to the actual web servers username.
Now, if that doesn't work, then the alternative is to go for the 777 permissions. Keep in mind on a shared server this means anyone on that server could potentially get to that file if they knew the path.
Another way as suggested by OP:
0,10,20,30,40,50 * * * * /usr/bin/wget http://example.com/user/x.php
This way will always run as the apache (or whatever) user that apache runs as, ensuring the next time it is accessed, the file will be useable.
Ask the server admin to create a new user who owns the folder where the script writes the xml file.
Run your php script through your cron job as such user. If you run your script as the folder's owner you might change the permissions through your php script.
This should work:
// set permission
chmod('path/to/b.xml', 777);
// do other stuff
To solve this issue, I ended up just creating a cronjob such as this:
0,10,20,30,40,50 * * * * /usr/bin/wget http://example.com/user/x.php
This executed the file which created b.xml and since the user who executed the script was public, the permissions remained public as well.

Using crontab from php

I am having troubles with setting up a server which would allow me to manage cron jobs from PHP scripts.
The idea is: users can create as many tasks as they want with possibility to set alarm(s) for each. After alarm is saved into MySQL database, I want to create a cronjob for that entry on user specified time.
The logic is pretty simple but I am getting frustrated over unix user/file permissions. The problem is, user "www-data" has no permissions to run crontab, thus I cannot use it to manage cronjobs via shell_exec invocation in php scripts. I have read a lot of tutorial/threads on similar issues but without any luck. The closest I could get was that I should make sure www-data user has permissions to run crontab (which I am pretty positive it does not have). However, I put "www-data" user into "crontab" group, I created "cron.allow" file in "/etc/cron.d" directory, but still nothing.
Btw, I am using $output = shell_exec("crontab -u www-data -l") to see if it's working or not (if $output == null then there was an error).
What should I do to make this working? Or should I use a bit different approach (maybe I could have some file writeable by www-data and set somewhere in crontab configuration that it should check for cronjobs in there as well, but I dont know how to do that neither)?
Edit: You could put a modified file into /etc/cron.d which is also read for cron comamnds.
Disclaimer: I've not done this (though I'll be damned if I can remember how I did this last time at all)
It seems that system my app is running on is handling cron.allow/cron.deny files very oddly (at least to my understanding of these files). I deleted /etc/cron.allow file and suddenly www-data user can use crontab command in php scripts. I have no idea why it didn't work with having www-data user stated in cron.allow file, but it looks like it works now.

How do I make the php script work as a superuser

I've assumed that if my php script has permissions set to root, the script would be able to execute commands as a root user. But apparently, it's not the case. I noticed that I cannot write anything outside of www and when I want to write a text file at /test.txt, it won't create a file because of permissions at / saying that non-root users only can access but not create or delete but the script itself has the root permission. If I change permissions at / then it works fine. Why can't my php script, set to have root permissions, write to the / directory?
And what can I do to enable the php script to be executed as a superuser?
I want to use the exec() and I cannot seem to get it to work. I want to be able to create a crontab and it doesn't work. I wrote a code like this:
exec("crontab -l > test.txt; echo '* * * * * echo hi! > /root/Desktop/hi.txt'>> test.txt; crontab test.txt");
But it won't work. If I copy the string into terminal, it works as expected.
Setting the permissions on the script file itself does not affect who the script is run as. it affects who can access the script.
To run the script as root, it depends on the context. Are you running it in a web server or is this a CLI script? If the later, then you must run it while logged in as the root user or with the sudo command. If its in a web-server as apache, then you must configure apache to run as as root but this is highly discouraged as it opens up a lot of security risks.
The permissions/ownership of a script have no bearing on which user that script runs as. It will run as whichever user executes it, assuming it has permission to do so. Sometimes you can use the setuid 'sticky bit' permission to do things like this, but most systems do not allow it, and the least offensive term I can think of to describe allowing it is "inadvisable".
I noticed that I cannot write anything outside of www
Because apache is configured properly. Ideally it will run as a non-root users [usually www] and any scripts will run as that user as well. Instead of telling you how to configure apache to be less secure why not just grant the apache user access to the file/directory that you want to access/modify?

PHP & cron: security issues

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.

php - changing file permissions

I have a PHP script which changes file permissions on my server using chmod. I'd like to be able to run the script both via the browser (as nobody) and via a cron job (as username).
Is it correct that only the owner of the file can change the permissions? I.e. if I create a file via a cron job and set the permissions, I can't then change those permissions when running the script from the browser?
Are there any ways round this please? Delete (unlink) and re-create the file as whatever user the script is running as? Or is there a way of running a php script via a cron job as nobody? / via the browser as username?
The aim is to be able to make images publicly viewable or not by changing the file permissions.
Solution 1: Create a group for both the user and the cron user, add each user to your new group, and give both users access to read and write to the file (chmod g+rw filename). (safer then the next solution).
Solution 2: The simplest way to do this is to make the file readable and writable by everybody (chmod a+rw filename) would have this effect.
I would not recommend this for production usage though.
You can do this without putting a username or password in your script.
In your crontab have sudo execute the script as the user that your web server runs as. Following your example, I'll use the nobody user.
0 12 * * * (sudo -u nobody php ./yourscript.php)
Note that the "nobody" user (as well as users like "apache") do not normally have login privileges. This may require you to allow sudo to execute scripts without a tty. You'll know this if you receive an error like: "sudo: sorry, you must have a tty to run sudo"
Allowing this can be done by commenting out the "Defaults requiretty" line using the visudo command. As with any change to sudo, you may want to search for any side-effects this change may come with.
Yes, only the owner of the file can do this. Your options depend on what kind of control you have over the server.
If you have enough control over the server, you can use SuPHP instead of Apache's mod_php. That way, the PHP scripts will be run as the user who owns the script, and any files created by a PHP script will be owned by the same user.
If you don't have that much control (common shared web hosting, for example), you could use something like Joomla's FTP approach. When FTP support is turned on in Joomla, it does all file manipulation using FTP. That way, it can create or manipulate files with the same permissions as the FTP user.
Something like this (error handling ommitted):
$ftp = ftp_connect('localhost');
ftp_login($ftp, 'username', 'password');
ftp_chdir($ftp, '/root/to/website');
ftp_chmod($ftp, 0644, 'filename.ext');
ftp_close($ftp);
Only the owner of the file can do this, I would recommend running the cronjob as 'nobody' instead.
Usually only the owner or the super-user (or equivalent)

Categories