Is there a way to make PHP CLI-invoked scripts to fwrite() as www-data?
Currently, if I create a text file and write to it using my own custom script php writeToLogFile.php, the file is created as root, and with very minimal permissions: rw- r-- r--
This means then if I want to write further data to this file in apache (running as www-data), I get permission denied.
This is part of a larger system, so it wouldn't be practical for me to chmod() or chown() each file I create. I also don't want to set the umask() in PHP as this may interfere with other threads.
I should also mention the file is being written to an NFS share on a different server (all servers are Ubuntu). The folder is shared as: /myfolder/logsfiles 01.02.03.04(rw,sync,no_subtree_check,no_root_squash)
Thank you in advance.
php can't change the userid that the process runs as, only privileged (e.g. setuid) programs can do this. You need to run the script as www-data.
sudo -u www-data php writeToLogFile.php
execute sudo su www-data && php writeToLogFile.php this will first switch user and than execute your code as www-data user only...
Related
I want the user to be able to read and edit files in the test folder, these files are always created by a software with read-only properties.
I can't use the chown command manually, so I need a chown command that can work in PHP before the user's read and write commands automatically.
Manual ok:
root#vultr: chown -R nginx /var/www/html/test //run ok, All files in the test folder can be read and written
root#vultr:~# /var/www/html/test/test.sh //run ok, the test.sh file contains the "chown -R nginx command /var/www/html/test"
My php code but not working
shell_exec('./test.sh');
chown('file_webuser', 'nginx');
The chown (change owner) won't work for non-root user. What you really need to do is to grant the user (I assume it's a nginx) full permissions to files.
It can be achieved in few ways. The most secure way is to run PHP (I'm guessing PHP is running as a PHP-FPM) as a nginx user by editing params user and group in your php-fpm.conf file and restarting the PHP service.
In such case, the owner of files will be the same, so no file permission manipulation is needed. You'll need to change ownership of all files generated/uploaded by PHP to nginx once (using root user and chown command).
The second solution is to add the user who's running PHP-FPM to the same group as the nginx user and modify umask so the files are accessible to a group. Let's say that the group would be www-data (you have to add nginx user and the PHP-FPM process owner to that group, for example with usermod command, and edit your php-fpm.conf: set group to www-data). Then in your PHP scripts use umask function to allow all members of group to have full access to files: umask(0007);.
The third, least secure way is to give full access to your files for all users in the system. Use umask function in your PHP file to achieve this: umask(0000);
this is because the root user probably has privileges to manipulate these files created by Nginx or etc.
if PHP is not the owner of that files you can put it on the authorized group that they have desired access to.
Use the exec() in PHP so your code will look like:
exec("chown -R nginx /var/www/html/test");
I have a folder above the webroot that is used to temporarily store user files generated by a php web application. The files may, for example, be PDF's that are going to be attached to emails.
The folder permissions are set to rwxr-xr-x (0755). When executing a procedure from the web application, the files get written to this folder without any issues.
I have now also set up a cron job that calls the php script to execute that exact same procedure as above. However, the PDF cannot be saved into the above folder due to failed permissions - the cron job reports back a permission denied error.
I have tried setting the folder permissions to 0775 and still get a permission denied. However, when the permissions are 0777, then the cron job then works fine.
This seems very strange to me - why does the cron get a permission denied at 0755 but it works fine through the web app?
The probable answer is that the cron job executes under your user - and the directory is owned by apache (or www-data or nobody or whatever user your web server runs as).
To get it to work, you could set up the cron job to run as the web server user.
Something like this:
su -l www-data -c 'crontab -e'
Alternatively, you could change the permissions to 775 (read-write-execute for the owner and group, and read-execute for others) and set the group ownership of the folder to the user running the cron job.
However, you have to make sure that if you're deleting something or descending into folder which is created by apache, you could still run into problems (apache would create a file which it itself owns, and your user cannot delete it then, regardless of the directory permissions.
You could also look at some stuff like suphp or whatever is up to date - where the web server processes are ran under your username, depending on your system architecture.
It depends on which user you have defined the cronjob.
If you're root (not recommended) it should work. If you're the web-user (e.g. www-data on ubuntu) it should work as well.
sudo su - www-data
crontab -e
Permission are given to user-group-everybody. That's what the 3 characters denote.
Your php script runs as a different user&group than the cron job, so they observe different permissions.
Check chown and chgrp, or try to run the cron job with the same user.
if you are using cpanel to run a php, you can try something like this:
"php /home/algo/public_html/testcron.php" ...
just write: php (the rute of the script)/yourscritpt.php"
What is the solution to delete the files outside of web dir? It doesn't delete the files.
Script will be accessed via web browser (only admins).
For example:
PHP located at: /var/www/html/delete_xx_phones.php
-rwxr-xr-x 1 root root 592 Mar 13 17:18 delete_xx_phones.php
delete_xx_phones.php code look something like this:
foreach(glob("/path/004*-phone.cf") as $file) {
unlink($file);
}
Files in /path
-rw-r--r-- 1 root root 346 Mar 13 17:15 004aaaa-phone.cf
-rw-r--r-- 1 root root 346 Mar 13 17:15 004bbaa-phone.cf
PHP scripts often run as user other than root, as they typically are executed by httpd. Since your files are set to have write permissions only for the root user, that's not going to work out.
If you cannot permanently change the ownership or write permission of the files, you could consider writing a very short script and executing it with elevated permissions (using sudo or the suid bit) instead of calling unlink() on PHP.
For the suid approach, write a simple script in Perl (may require perl-suidperl package installed), which deletes the filename passed as an argument:
delete-file.pl:
#!/usr/bin/perl -wT
# This is VERY insecure, so if you use it, make sure you modify it
# to filter the filenames before putting the script on production
# machines
unlink $ARGV[ 0 ];
Make sure the file is owned by root (chown root delete-file.pl) and then run chmod 6711 delete-file.pl to set its SUID bit. After that the file will always execute as root.
Then in your PHP script, you'll just need to run exec( "/path/delete-file.pl $filename" ) (consider shellescapearg() for safety) and your files should start deleting.
(Note that I'm specifically using Perl here because Bash traditionally ignores the suid bit.)
If you feel more comfortable with using sudo, then just write a script similar to what is described above (Bash will work too) and just add it to /etc/sudoers. You can then do something along the lines of: exec( "/usr/bin/sudo /path/to/delete-file-script $filename" ); to run the script with elevated permissions.
The files aren't accessible to PHP because they belong to the root user. PHP usually runs as with the web server's user ID, or if it's running on command line, in the context of the user who called php.
Theoretically, you could do a sudo in your PHP script to forcibly delete those files, but that's very bad practice - you'd have to store the root password in the PHP script for that.
A better way would be to change the files' owner to the user PHP runs as, or chmod ing them so PHP can delete them (although that's also not really elegant because you'd make the file accessible to every user on the machine).
Depending on your situation, a cron script that runs under the root account every couple of minutes and changes the owner of those files might be a workable solution:
chown apache:apache /path/004*-phone.cf
(substitute apache:apache with your PHP user and/or group)
Of course, if you can influence how these files are created, making them the property of the right user straight away would be ideal.
I am currently over ssh on a remote CentOS 5.6 system which runs an Apache webserver. I need to use the poppler pdftohtml binary which, unfortunately, is not currently installed on that machine. So I downloaded the poppler package and built it under my user folder. Since I I am not the system admin, I didn't do
make install
and I have all my compiled files under
/users/myfolder/poppler-0.18.2/
The file that I need to execute through php shell_exec() is
/users/myfolder/poppler-0.18.2/utils/pdftohtml
If I execute it through my ssh bash, I get the correct output. If I, instead, put this line on a php script:
echo shell_exec("/users/myfolder/poppler-0.18.2/utils/pdftohtml");
I get the following output:
sh: /users/myfolder/poppler-0.18.2/utils/pdftohtml: Permission denied
I tried setting to 777 the file permissions, which currently are -rwxrwxrwx. I also noticed that using shell_exec("whoami"); results in "apache". Shouldn't apache be able to execute the script if the file permissions are -rwxrwxrwx?
I also know that installing poppler through make install would solve the problem but since this is for testing purpose, I would like to avoid "contaminating" the system outside my personal folder until the testing is complete.
Thanks to anyone who will help!
Just because a file is executable for a user does not mean that user is actually able to execute the file. The user needs to also be able to 'get to' the file: The user needs execution permission for all 'parent directories', in your case for /users, myfolder, poppler-0.18.2 and utils.
Assuming /users is the same basic thing as /home, everybody should have +x on that. From there, you can set it: simply do chmod o+x /users/myfolder /users/myfolder/poppler-0.18.2 /users/myfolder/poppler-0.18.2/utils
(Note: This will make it possible for everybody to execute this binary, not just Apache.)
If the apache user and you share a group, it would be better to use chown the poppler directory and everything in to be owned by that group, and set g+x instead of o+x.
I have a PHP script that is accepting all emails (wildcard) to my domain, and inserting the data into MySQL.
The beginning of the script has this line:
#!/usr/bin/php -q
It then looks like a regular PHP script. The part that writes the attachments to disk seems to work but the permissions on the new folders where they're stored were created by the 'nobody' user.
How can I edit permissions so that after these files are written to disk, they can be accessed by the webserver/webserver user?
Thanks for the help!
(Fedora 14 Linux server, Postfix)
You can preform your file system operations by FTP so you will have the same permissions as your user.
its better then give all the PHP users on server access to your files.
http://php.net/ftp
What user is PHP running as? PHP does have a chmod function, but you can't elevate privileges higher than what the user PHP is running as.
If that doesn't do the trick, could you chown the attachment directory to be owned by whatever user PHP is running as?
I suggest you do the following:
chown -R apache:apache directory_name
This is because PHP runs as the web server user (I believe this is apache on Fedora). Otherwise, if you are using a different web server, then change the ownership of the files to that web server's user (you are sure to find this in the server's configuration files somewhere).
You need sticky bits on the file server level.
setting the sui/sgid bits