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.
Related
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.
I have a situation where I want to protect a file from public access, but enable read and write from php. The file contains sensitive information like passwords.
The problem is that
I cannot put the file outside the web root (server security restriction on access from php)
I would like to avoid mysql database.
Also I would try to avoid .htacess files.
So if I make a folder, say private, in the web root, and do
chmod 700 private
Then, if the file to protect is private/data, I do
chmod 700 private/file
will this be a safe setup? So now I can read and write to the file from php but it is not accessible for the public?
Is this a safe setup?
PHP runs as the same user as the webserver so if PHP can read it, so can your webserver (and vice versa).
If you don't want to use .htaccess there is another trick: save the file as a .php file. Even if someone accesses the file from the web they can't see the source, they might just get a white page or maybe an error depending on what exactly is in the file.
If you're running suPHP or fastCGI php, you can use a setup similar to what you've described to limit access to files. Otherwise, PHP will use the same user as the web server, and any file PHP can access is also accessible via url.
If want to keep the restrictions stipulated (which are rather strange), and as (i guess) you do not wish/have access to apache config directives, consider adding PHP to some group and give the group only rights to the file, ie. apache cannot read (if its not in root/wheel).
Or make it a valid .php file (so only php would be invoker when the file is requested) which returns nothing or redirects when invoked with php. or just cipher it.
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.
In php, I need to read a file that has no read access (the file permissions are -rw-r-----).
Changing the file's permissions isn't possible. The file sits on a local server.
Various methods I've tried in PHP don't work (file_get_contents, fopen, and curl) and maybe that's to be expected if that last read bit isn't set. Is that because the web server is being blocked access?
If that's the case then why is it that Firefox can read the file directly (using file://) as does curl from a shell? About to write an external python script that can read the file... what am I missing here?
It depends what user owns the file, and what user PHP/Apache is running as. You could check it by running whoami from PHP. If you can't change any part of the permissions/owner on the file, nor the Apache user, then, well, you're stuffed sorry.
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)