PHP: get_current_user() vs. exec('whoami') - php

Short version of the question:
What's the difference between
get_current_user(); and exec('whoami'); ?
Long version of the question:
I'm on a XAMPP Localhost on a Mac.
I'm using Apache, building a PHP
based website in a folder (let's call it folderxyz) within the
htdocs folder (var/www in some flavors of Linux+Apache).
I was playing around with a database connection,
testing out PDO::ERRMODE_EXCEPTION described here: Link
And I got this error:
file_put_contents(PDOErrors.txt): failed to open stream: Permission
denied...
So I did some sleuthing around and it seems that to fix this I need to change the CHMOD settings of file PDOErrors.txt to 777.
However, my questions are about something else. During this process I realized that I don't clearly understand the concept of user in Apache, PHP, and MySQL.
The PHP manual says that get_current_user() "Gets the name of the owner of the current PHP script" Link
The PHP manual says that exec('whoami') returns "the username that owns the running php/httpd process" Link
When I use get_current_user(), I get my firstnamelastname, which is my account name on my Mac.
When I use exec('whoami'), I get daemon.
So...
What's the relationship between firstnamelastname and daemon ?
What's the relationship between the "the owner of the current PHP script" and "username that owns the running php/httpd process" ?
Who needs permission to write to PDOErrors.txt? Is it firstnamelastname or daemon ?
Who needs permission to write to PDOErrors.txt? Is it Apache or PHP (or both) ?
Does the concept of a unix-like root account factor-in anywhere here ?
Edit: I updated this to reflect that it wasn't the folderxyz that I had to change CHMOD settings for. I had to change the settings for the file PDOErrors.txt
OP here: for future reference, I put up a parallel question for the Linux platform here (with an accompanying intuitive explanation of what's going on): https://stackoverflow.com/questions/31389892/why-is-the-output-www-data-in-one-case-and-root-in-another
Update: That question was deleted as it was deemed to be a duplicate of this one (although that was for the Linux platform, and instead of daemon I was getting www-data after doing echo exec('whoami'); ).
This is what I learned from asking this question in the Linux forum:
the running process is different than the script. Yes, the process emerges from the script, but it's not the same thing. The script is owned by root, but the process is taken over by Apache and is run as www-data.
Overall conclusion: What I learned from this process is that user is supposed to be the Apache daemon (Mac localhost) or www-data (Linux on an internet server) and that I should be using exec('whoami') to determine this, and I shouldn't care too much about get_current_user() (which probably should have been named get_current_owner()).

get_current_user() (should) return the owner of the file, which is firstnamelastname in this case. There have been reported issues that this function is inconsistent between platforms however. As such, I would not trust its output. daemon is the user Apache is running as.
The owner of the PHP script is the user who owns the file itself according to the operating system. You can run ls -la in the directory your scripts are in to find the user and group the file belongs to.
Whichever user you're editing your scripts with needs to be able to write it, so most likely, firstnamelastname (+rw).
For the folder itself, you should have +rx (execute and read) for daemon and for the PHP file, +r (read). On my installation of XAMMP, they've done this by setting everything in htdocs as public readable, thus daemon can read it, but not write to it.
Mac has a root account that typically owns the htdocs or www directory. It fills the role of a traditional unix root user.
Here is some information on the file owners/groups and the process owner:
host:~$ ls -l /Applications/XAMPP/xamppfiles/htdocs
drwxr-xr-x 3 root admin 4096 2015-01-01 00:01 .
drwxr-xr-x 3 root admin 4096 2015-01-01 00:01 ..
-rw-r--r-- 1 firstnamelastname admin 189 2015-01-31 20:45 index.php
host:~$ ps aux | grep httpd | head -n1
daemon 45204 0.0 0.1 2510176 10328 ?? S Tue11AM 0:01.38 /Applications/XAMPP/xamppfiles/bin/httpd -k start -E /Applications/XAMPP/xamppfiles/logs/error_log -DSSL -DPHP
If you wanted to make a file writeable by the daemon user, you can create a new folder and name it as the owner with the group admin (so you can use it too), and give it +rwx for the user and group, with +rx for public:
host:~$ cd /Applications/XAMPP/xamppfiles/htdocs
host:htdocs$ mkdir some_dir
host:htdocs$ chmod 775 some_dir

Related

Force PHP CLI to write files as www-data

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...

File permissions on files created by PHP [duplicate]

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"

Why does file_put_contents have permission issues when run from the browser?

This question has been asked a couple of times up here, but I haven't found a solution yet. I have a Fedora 19 LAMP server and I just want to run the simple command: file_put_contents('test.txt', 'Hello there'); in order to confirm that my web server can use PHP to write data to files. I'm having trouble figuring out a proper permissions scheme. To start, just for development, Apache's document root is /var/www/html. This directory was originally owned by a user and group called www-data, but I changed the directory's group to the primary group of the owner of the httpd process, named apache. It is this owner that is active when PHP runs. I've confirmed this with the following:
As you see, the process owner is apache, the current direcory is /var/www/html/php-console. The directory is owned by www-data and members of the group apache have full access to it.
I have tried the following to get PHP to actually create a file in this location, but to no avail:
chmod 777 /var/www/html/php-console
chown apache /var/www/html/php-console
chgrp apache /var/www/html/php-console
cd /var/www/html; > test.txt; chmod 777 test.txt;
Nothing will work while this script is run from the browser. However, when I use file_put_contents with the PHP CLI, it works just like I would expect, provided that the user I'm entering commands as or its group has write permissions to this directory or test file.
So, from the command line, you see how www-data has read, write, and execute permissions to the folder I'm in. posix_getpwuid and posix_geteuid help you to find the owner of the Apache/PHP process, which in this case is the same as the user logged into the console. file_put_contents succesfully writes 8 bytes to the specified file. If I change the group or owner and group to something else, I get Permission denied, which absolutely makes sense.
If this works on the command line, then why not when I really want it to, i.e., while actually serving web pages???
Because you forgot to read the httpd_selinux(8) man page and give the directory the appropriate file context to allow the web server to write files there.

Delete files outside of Web dir?

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.

Cron job and folders permissions - permission denied

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"

Categories