Folder permissions when telling PHP to save a file to that folder? - php

I'm trying to use this Dagon Design PHP form to help a local non-profit publication enable their readers to submit photos. I've got the "mailer" part working -- the notifications work fine -- but the "saving a file to a folder" part isn't functioning.
On the form page, the author says "the directory must have write permissions," but I'm not sure "who" is writing to that folder -- is this PHP script considered "Owner" when it saves something on my site? Or do I need to allow save permissions for Owner, Group and Others?
I'm not sure why the script isn't saving the photos, but this seems like a good place to start. I've tried looking around on Stack for answers, but most questions seem to have to do with folder creation/permissions.
The page I'm clumsily trying to build is here, if that helps.

As Jon has said already, you don't want to allow write access to everyone.
It's also possible (depending on the hosting) that something like suEXEC is being employed - which will cause your PHP script to run as a user other than the webserver's (as reported by Dunhamzzz).
Probably your best approach, in my opinion, is a script calling whoami:
passthru('whoami');
Or alternatively you could try:
var_dump(posix_getpwuid(posix_geteuid()));
Bear in mind, this does give system information away to the world - so delete the script once you've used it!
Then, as you've correctly asserted in your question, it'll likely be the file permissions.
If you do have CLI access, you can update the permissions safely as so (first command gets the group)
id -n -g <username>
chmod 770 <directory>
chown <username>:<group> <directory>
(You may have to pre-pend "sudo" to the "chown" command above, or find other means to run it as "root"..., reply back if you get stuck.)
If you've not got access to run command-line, you'll presumably be doing this via a (S)FTP client or the alike. I'm afraid the options get a little to broad at that point, you'll have to figure it out (or reply back with the client you're using!)
As always, YMMV.
Finally, bear in mind if this is your own code, people will at some point try uploading PHP scripts (or worse). If that directory is accessible via a public URL ... you're opening the hugest of security holes! (.htaccess, or non-document root locations are your friend.)

If you are not sure how is your server configured (and this would influence who's the final file owner) then add write permission to anyone (chmod a+w folder), upload one file and ls -l to see the owner. Then you can adjust permissions to allow write access to certain users only

The PHP script that saves the files is running with the privileges of some user account on the server; the specific account depends on your OS and the web server configuration. On Linux and when PHP is running as an Apache module this user is the same user that Apache runs as.
Solving your problem reduces to determining which user account we are talking about and then ensuring that this user has permission to write to the save directory (either as owner or as a member of the group; giving write access to everyone is not the best idea).

You'll need to set the permissions of the directory to that of the webserver (probably Apache, nginx or similiar), as that's what is executing the PHP.
You can quickly find out the apache user with ps aux | grep apache, then you want to set the permssions of the upload directory to that user, something like this:
chown -R www-data:www-data images/uploads

Related

File permissions for CodeIgniter on Ubuntu web server

I have a CodeIgniter app running in production on Apache 2.2 with PHP 5.3 on Ubuntu 11.10. I am also running PHP5-APC, if that matters. So the app runs as www-data:www-data per the default Apache2 install.
I am trying to figure out what to set my file permission to. Many threads on SO seem to prefer 755 for directories and 644 for files. There is one directory that must allow files to be uploaded to it.
Currently my deployment script does something like this:
wipe old site
copy new site over
chmod -R 000 on the new site
chmod all directories to 500
chmod all files to 400
chmod 700 on the upload directory
Everything seems to work fine. I can upload files and so on.. so, I don't understand why people suggest 644 for files - I have a config file that has passwords and API keys - why would I want 'others' to have read-access to it?
What am I misunderstanding?
Well, mainly the 644 permission is meant for when you have /var/www/site1.com with different user and group set then www-data, because then the 644 would allow other groups and users to read from that file, but will allow to read and write the owner of the file.
As by default the user that uploads files and runs apache's processes is www-data then I honestly think that if it works for you and you have no issues, it's great because means a little more security.
Update
Just a small security issue, is that www-data has become a very common user and group for http services to run their processes. I would much recommend that each site/app have their own user and group.
*44 and *55 just means that the file/folder is readable by others.
This would be good if say, you uploaded files to the web server but they for some reason were owned by someone else (say your own login account), then apache could still read them and it'd be "no fuss". Or if you needed multiple groups to be able to access the files.
If you know you are uploading the files as the apache user, and apache (or whichever programs run under www-data) are all you need to be able to read/write the files, then *00 is completely fine. It can even be argued that it's a little more secure.
For people who don't know what they're doing on the linux command line, 644 and 755 are about the right mix between "convenient" and "safe" (completely debatable, though), so they are what is recommended for a quick fix.
When doing shared hosting, you have user accounts that upload php files via FTP. So, when user "joe" uploads his .php file, it is owned by "joe" and when Apache needs to read it to execute the script, it cannot. Users are usually in "users" group, so even giving privilege to the group would not be enough. That's why you need to give privilege to everyone, so that user "www-data" can read the file uploaded by "joe".
If you run your own server, than of course, you have full control and none of this matters.

Apache permissions, PHP file create, MKDir fail

It seems i cannot create files. When i set permissions to 777 On the folder i am trying to create a folder in then the script works fine. If the folder is set to 755, it fails. I do not know much about linux, but i am suppose to figure this stuff out. I have spent a couple hours trying stuff. Does anyone know how to make it so that apache has high enough permissions.
I know it is a permissions and apache problem, i just do not know how to fix this. I have edited the httpd.conf file, but i really do not know what i am doing... Any help? (I saved backup.)
Please stop suggesting to use 777. You're making your file writeable by everyone, which pretty much means you lose all security that the permission system was designed for. If you suggest this, think about the consequences it may have on a poorly configured webserver: it would become incredibly easy to "hack" the website, by overwriting the files. So, don't.
Michael: there's a perfectly viable reason why your script can't create the directory, the user running PHP (that might be different from Apache) simply doesn't have sufficient permissions to do so. Instead of changing the permissions, I think you should solve the underlying problem, meaning your files have the wrong owner, or Apache or PHP is running under the wrong user.
Now, it seems like you have your own server installed. You can determine which user is running PHP by running a simple script that calls the 'whoami' program installed in most linuxes:
<?php
echo `whoami`;
If all is right, you should see the username PHP is running under. Depending on your OS, this might be 'www-data', 'nobody', 'http', or any variation. If your website is the only website running, this is easy to change by changing the user Apache runs under. If you have Debian, like I tend to, you can edit the file /etc/apache2/envvars (as root), and change the value for APACHE_RUN_USER. Depending on your OS, this variable might be set in a different configuration file, so if you can't find it in /etc/apache2/envvars, try to search for the variable declaration by using:
$ grep -R "APACHE_RUN_USER=" .
From the directory all apache-config files are in.
If you're not the only one on the server, you might want to consider creating user accounts for every website, and using something like Apache2-MPM-ITK to change the RUN_USER depending on which website is called. Also, make sure that the user the PHP process is running under is the owner of the files, and the directories. You can accomplish that by using chown:
% chown theuser:theuser -R /var/www/website/
If PHP is running with it's own user, and is the owner of the files and directories it needs to write in, the permission 700 would be enough. I tend to use 750 for most files myself though, as I generally have multiple users in that group, and they can have reading permissions. So, you can change the permissions:
% chmod 0750 -R /var/www/website/
That should be it. If you having issues, let us know, and please don't ever take up any advice that essentially tells you: if security is bothering you, remove the security.
I have a similar problem but in my case I have SELinux running and it failed even with 0777 permission. Turns out I need to explicitly allow httpd to have write access on the directory using:
chcon -R -t httpd_sys_rw_content_t <PARENT_OF_MKDIR_TARGET>
SELinux Troubleshooter may have more details.
On ubuntu you edit /etc/apache2/envvars as Berry suggested.
When you change the Apache user, beware of unintended consequences. One of them is the PHP sessions that may be stored in /var/lib/php5. You may need to change the ownership of that folder too.

How can I allow php to create files with the same ownership as the files that created them?

PHP creates files with apache:apache ownership which seems to be causing issues with other php scripts accessing the file.
How can I allow php to create files with the same ownership as the files that created them?
I've read elsewhere that having safe_mode turned on can affect this but I've turned it off and reuploaded the files and i still get the same issue.
I'm sure this will be a simple question for someone more familiar with apache but I've failed to find the solution by searching around.
Thanks
If ownership matters and multiple users / projects are on the same server, you might want to look into SuExec in Apache: PHP files will then be run by the user indicated in the settings, so default ownership of files is automatically taken care of. It saves a lot of chown/chmod'ing, and the processes run by the user are more easily restricted.
Otherwise, I normally create a group with both the owner & apache, and set the default umask to 007.
If you are using a Windows OS you can start Apache as a service and allow apache to use your own account's permissions when starting.
Try using fileowner ( http://www.php.net/manual/en/function.fileowner.php ) to get the id of the owner of the current script, posix-getpwuid to get the username for that id ( http://www.php.net/manual/en/function.posix-getpwuid.php ) and chown ( http://php.net/manual/en/function.chown.php ) to set the user for the files.
Why go through all the programatic hassle to change the owner? apache.apache is a very insecure owner anyway. Why not just chmod 0777 the file providing read, write, and execute to all owners. This will eliminate the issue.
If you are still having troubles, then you may need to check if open_basedir is on. If that is the case, it is not file ownership or permissions, but location. This basically means you need to put the file in a location that apache/php already has included in their path.
A.M. mentioned chown() above, please be aware that generally chown() can only be used by root and your webserver running account is highly unlikely to be root, that's a very bad idea.
It is possible to setup sudo to allow chown by other users in specific areas and only to specific users. Just have to create a suitable entry in /etc/sudoers, usually by using the visudo program. If you do not have root access yourself, then your hosting provider will have to do this for you, if they will.
For more information: http://www.sudo.ws/sudo/sudo.html

CHMOD a linux directory using PHP on an apache server

Has anyone ever used PHP (proven and successful) to CHMOD a directory through a Web Browser?
My roadblocks are:
(a) PHP script runs as "nobody" from the browser
(b) directory above the one I want to CHMOD is owned by the ftp user and "nobody" does not have write permissions to it
So when I try to chmod 0666 /usr/www/dirOwnedbyFTPuser/dirIamTryingToCHMOD/ I get Permission denied
If you have ever written and successfully run a script to do this, can you share the snipit of code with me? Thanks...been at this for months.
Yes it is possible to do this via php. Usual linux permissions rules apply however so as you are looking to chmod scripts not owned by the apache user (nobody) and the apache user does not have write permissions then one method is to give apache permission to use sudo
Be warned - this is potentially a massive security hole!!!
You can give apache permission to use sudo by editing the sudoers file. It is recommended that you do not edit this file directly as an error can leave you completely screwed so on my (Ubuntu) system I type
sudo visudo
Then you need to add a line for your "nobody" user. You can restrict sudo permissions to a particular script or folder so i would recommend writing a shell script to change the permissions and then placing this in a folder away from any other scripts. That way apache doesn't have complete root privileges on your system (which is a pretty scary thought). You can also put some code in the shell script to restrict which files can be changed.
You also need to allow apache to sudo without a password as you have no way of entering the password through php. So the line you would add is something like
nobody ALL=(ALL)NOPASSWD:/path/to/my/script
Then in php you just prefix the command with sudo
passthru ("sudo /path/to/my/script ...");
(there are a few other functions you can use instead of passthru(), was just the first that came to mind)
As I said before, this is potentially very dangerous and whilst the above will work, I have only used it on my own private system before, never on a public production server. I'm sure plenty of people will have comments on the security of this so I would be interested to hear what other potential pitfalls and security holes there could be with this method. I know a similar thing can be done using SuExec but am not so familiar with it so if anyone has any pros or cons of SuExec over this method I would be interested to hear them.
Final note: I would change the apache user from nobody to something like 'apache' or 'www' - probably just being silly but I don't like the idea of giving root permissions to a user called nobody!!!
Hope this helps!
Yes, you can chmod from php via a web browser. (yes we all know it can be a bad idea)..
But - you can only chmod files that the php script has permission to use! if your web server runs PHP as nobody, then you can chmod any files owned by "nobody"...
http://www.php.net/ftp
You could have php log in as the ftp user and do it.

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