代码之家  ›  专栏  ›  技术社区  ›  miken32 Amit D

proc_open的权限问题

  •  0
  • miken32 Amit D  · 技术社区  · 2 年前

    我在运行以下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;
    }
    

    如果 /tmp/foo.bar 不存在,或由root用户所有。但是,如果所有权被更改为另一用户, 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用户,组权限也应该允许我完全访问该文件。那怎么回事?

    2 回复  |  直到 2 年前
        1
  •  2
  •   miken32 Amit D    2 年前

    这是由于对的权限 /tmp 目录当PHP试图打开文件进行编写时,它会得到 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() .

        2
  •  1
  •   miken32 Amit D    2 年前

    好的,我在不同的目录中尝试过 /tmp ,正如评论中所建议的那样,它如预期的那样发挥了作用。用它来完善我的搜索词,我很快就能找到 this U&L answer 。从内核4.19开始 fs.protected_regular 内核参数可用。此参数:

    不允许在世界可写粘性目录中打开FIFOs或非用户所有的常规文件,除非所有者与目录的所有者相同,或者打开文件时没有O_CREAT标志。其目的是使数据欺骗攻击更加困难。

    显然,它是默认启用的。所以是因为 /tmp 是世界上可写的和粘性的,即使我是root用户,我也不能触摸不是我的文件。为了记录在案,如果我必须禁用此功能:

    sysctl fs.protected_regular=0
    echo 'fs.protected_regular=0' > /etc/sysctl.d/90-writabletemp.conf
    

    但我最好尝试以某种方式在代码中解决它。