I'm having permissions problems when running the following PHP script as root:
#!/usr/bin/php
<?php
$ph = proc_open('whoami', [['pipe','r'],['pipe','w'],['file','/tmp/foo.bar', 'w']], $fds);
if ($ph) {
echo 'command output: ' . stream_get_contents($fds[1]);
proc_close($ph);
} else {
echo 'proc_open failed' . PHP_EOL;
}
The script itself runs fine if /tmp/foo.bar doesn't exist, or is owned by root. But if ownership is changed to another user, proc_open will fail regardless of permissions on the file.
SELinux is disabled, and we are not using ACLs. I'm using PHP 7.4.33 (I know it's old and unsupported, but it's a requirement for FreePBX) on Alma Linux 9.1.
Output:
$ ./test.php
command output: root
$ ls -lah /tmp/
total 12K
drwxrwxrwt. 18 root root 4.0K Dec 14 16:57 .
dr-xr-xr-x. 18 root root 4.0K Dec 14 16:48 ..
-rw-r--r-- 1 root root 0 Dec 14 16:57 foo.bar
$ chown admin /tmp/foo.bar
$ ./test.php
proc_open failed
$ chmod 777 /tmp/foo.bar
$ ./test.php
proc_open failed
$ ls -lah /tmp/
total 12K
drwxrwxrwt. 18 root root 4.0K Dec 14 16:57 .
dr-xr-xr-x. 18 root root 4.0K Dec 14 16:48 ..
-rwxrwxrwx 1 admin root 0 Dec 14 16:57 foo.bar
$ tail -2 /var/log/php.log
[14-Dec-2022 16:57:17 America/Toronto] PHP Warning: proc_open(/tmp/foo.bar): failed to open stream: Permission denied in /test.php on line 3
[14-Dec-2022 16:57:28 America/Toronto] PHP Warning: proc_open(/tmp/foo.bar): failed to open stream: Permission denied in /test.php on line 3
Even disregarding the fact that I'm root, group permissions should allow me full access to the file. So what's going on?
This is due to the permissions on the /tmp directory. When PHP tries to open the file for writing, it gets the EACCES error. From the documentation of open(2):
EACCES
Where O_CREAT is specified, the protected_fifos or protected_regular sysctl is enabled, the file already exists and is a FIFO or regular file, the owner of the file is neither the current user nor the owner of the containing directory, and the containing directory is both world- or group-writable and sticky. For details, see the descriptions of /proc/sys/fs/protected_fifos and /proc/sys/fs/protected_regular in proc(5).
/tmp has the sticky bit set so that anyone can create files there, but users can only delete their own files. Although root can bypass this deletion restriction, it can't bypass the above check in open().
Ok I tried this in a different directory than /tmp, as suggested in comments, and it worked as expected. Using that to hone my search terms I was able pretty quickly to find this U&L answer. Beginning with kernel 4.19 the fs.protected_regular kernel parameter was made available. This parameter:
Disallows open of FIFOs or regular files not owned by the user in world writable sticky directories, unless the owner is the same as that of the directory or the file is opened without the O_CREAT flag. The purpose is to make data spoofing attacks harder.
Apparently it's enabled by default. So because /tmp is world-writable and sticky, I can't touch files that aren't mine – even if I'm root. For the record, if I have to disable this feature:
sysctl fs.protected_regular=0
echo 'fs.protected_regular=0' > /etc/sysctl.d/90-writabletemp.conf
But I'll be better off trying to work around it in the code somehow.
I have a question about the exec function on PHP 7.0.
I write a shell script to copy/sync the files and log the details into a log file, everything happens in the tmp folder.
# /tmp/data
drwxrwxr-x 4 root www-data 4096 Apr 4 00:00 data
# /tmp/data/data.log
-rwxrwxr-x 1 root www-data 9551 Apr 4 04:19 sync.log
I tried to login as www-data user for testing the shell script, and it works fine via command line but it's not good with PHP exec as below:
exec('sh /var/www/sync.sh');
I tried to dump the data and I am sure that I can touch the .sh file.
Is there anyone have ideas about this issue?
Thanks.
I want to run a PHP script from chromium-browser which will print a file. The file is located in /tmp folder on the Raspberry Pi. The file is copied from the server using SAMBA. The script has shell_exec command which attempts to do something with the file. The script works from the command line but not through the browser (chromium). I run the latest Stretch version of Raspbian.
I suspect it is something to do with permissions but I do not know where the problem is located. I have previous image Jessie with similar setup and functionality and it works. I compared all the permissions on both systems and they are exactly the same but I must be missing something.
Here is the PHP script:
<?php
header("Access-Control-Allow-Origin: *");
shell_exec("sudo lpr -P printerName /tmp/sample.pdf");
shell_exec("rm /tmp/sample.pdf");
?>
Here are related permissions:
drwxrwxrwt 15 root root 4096 Nov 23 16:17 tmp
drwxr-xr-x 12 root root 4096 Nov 3 13:58 var
-rwxrw-rw- 1 nobody nogroup 320855 Nov 23 15:31 sample.pdf
When I try to shell_exec('/home/user/scripts/./script') I get the following error:
terminate called after throwing an instance of 'boost::filesystem3::filesystem_error'
what(): boost::filesystem::create_directory: Permission denied: "/.script"
Aborted (core dumped)
shell_exec('whoami') returns www-data on my web-facing php script.
The permissions to the directory and file are exactly the same:
-rwxrwxr-x 1 user123 group456 8246 Jun 25 06:10 script
drwxrwxr-x 7 user123 group456 4096 Jul 10 14:54 .
In fact I can shell_exec('touch /home/user/scripts/test') and it will create the file with no problem.
$ ls -l /home/user/scripts/test
-rw-r--r-- 1 www-data www-data 0 Jul 10 14:54 test123
This is how my groups are set up for each user:
$ groups user123
user123 : group456
$ groups www-data
www-data : group456
Why am I getting this error?
The script your running has a typo: it's trying to make the folder /.script in the root folder instead of ./script (relative path).
Are you trying to execute script at /home/user/scripts/./script then you should run as shell_exec('sh /home/user/scripts/script')
When you add ./ there on path its interpreted differently.
When you pass ./script - You are referring to filename script in current directory.
Also you are actually getting error from your c program which tells us your system is stopping apache to gain root privileges. You can audit2allow to let apache gain needed privileges.
I'm running as www-data and I'm trying to execute a shell script using shell_exec(/foobar/script/myscript.sh), but I'm getting the following error when the script attempts to write to a log file
cannot create /foobar/foo.log: Permission denied
However, I don't run into any problems if I try running the script directly from the terminal. ie
$ sudo su www-data
$ /foobar/script/myscript.sh
$
Any idea what could be going on here?
I should also add that I added www-data to the group mybar and that this is what's showing up when I list the directory
drwxrwxr-x 3 mybar mybar 4096 May 14 14:18 foobar # ls -l /
-rw-rw-r-- 1 mybar mybar 2824 May 15 09:57 foo.log # ls -l /foobar
I think there can be two options:
web-server and php-fpm are run under different users (by default that should not be). Try echo shell_exec('whoami');
You have added www-data to mybar after php-fpm process had been started so it still "doesn't know" that it is (then I think restart of fpm should help).
This works for me:
sudo chown www-data:www-data -R foobar/
The directory you are trying to create the file in must belong to whoever is executing the command.
You can type:
ls -la
to see who it belongs to.
You should see something like this:
drwxr-xr-x 8 jack jack 4096 Jul 22 11:36 application
When I am logged into my ubuntu machine I am logged in as jack#jack so I can create files in the following directory without issuing the sudo command:
drwxr-xr-x 8 jack jack 4096 Jul 22 11:36 application
because it is owned by the current user.
When you try running a script that is executed by visiting a webpage. www-data is the user that is executing the command so any directory or file that you are trying to create/modify/delete must be owned by www-data.