提问人:miken32 提问时间:12/15/2022 更新时间:12/15/2022 访问量:280
proc_open权限问题
Permissions problems with proc_open
问:
以 root 身份运行以下 PHP 脚本时遇到权限问题:
#!/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;
}
如果不存在,或者由 root 拥有,脚本本身可以正常运行。但是,如果所有权更改为其他用户,则无论对文件的权限如何,都将失败。/tmp/foo.bar
proc_open
SELinux 已禁用,我们没有使用 ACL。我在 Alma Linux 9.1 上使用 PHP 7.4.33(我知道它很旧且不受支持,但这是 FreePBX 的要求)。
输出:
$ ./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
即使不考虑我是 root 的事实,组权限也应该允许我对文件进行完全访问。那么这是怎么回事呢?
答:
这是由于目录上的权限。当 PHP 尝试打开文件进行写入时,它会出现错误。从文档:/tmp
EACCES
open(2)
EACCES
如果指定了O_CREAT,则启用protected_fifos或protected_regular sysctl,文件已存在并且是 FIFO 或常规文件,文件的所有者既不是当前用户也不是包含目录的所有者,并且包含目录既是全局可写目录又是组可写且具有粘性。有关详细信息,请参见 和 中的说明。/proc/sys/fs/protected_fifos
/proc/sys/fs/protected_regular
proc(5)
/tmp
设置了粘滞位,以便任何人都可以在那里创建文件,但用户只能删除自己的文件。虽然可以绕过此删除限制,但无法绕过上述签入。root
open()
评论
好的,我在不同的目录中尝试了这个,而不是 ,正如评论中建议的那样,它按预期工作。用它来磨练我的搜索词,我很快就能找到这个 U&L 答案。从内核 4.19 开始,内核参数可用。此参数:/tmp
fs.protected_regular
不允许在世界可写粘滞目录中打开不属于用户的 FIFO 或常规文件,除非所有者与目录的所有者相同,或者打开文件时没有 O_CREAT 标志。目的是使数据欺骗攻击更加困难。
显然,默认情况下它是启用的。因此,由于它是全局可写的和粘性的,我不能触摸不属于我的文件——即使我是 root。作为记录,如果我必须禁用此功能:/tmp
sysctl fs.protected_regular=0
echo 'fs.protected_regular=0' > /etc/sysctl.d/90-writabletemp.conf
但是我最好尝试以某种方式在代码中解决它。
评论
/tmp
mktemp()
评论
'w'
'a'
tmpfile(php)
拥有自己的文件,如果这是您要找的。IIRC proc_open 也接受流句柄。/tmp