通过 php 调用时不允许 setresuid 操作

通过 php 调用时不允许 setresuid 操作

我遇到了以下问题:我的 Apache 和 PHP 脚本以用户 www-data 身份运行。

我想调用一个只能以 root 身份执行的脚本,因此我向 /etc/sudoers.d 添加了一个新文件,以允许 www-data 用户执行此命令:

echo390:/var/www/html# cat /etc/sudoers.d/iptables
www-data ALL= NOPASSWD: /sbin/iptables

我的PHP脚本如下:

<?php
$command = '"/usr/bin/sudo" "/sbin/iptables" -L  -v -n | grep "220.177.198.43"';
echo 'Benutzer: '.exec('whoami').'<br/>';
echo 'Command: '.$command.'<br/>';
$result = array();
exec($command,$result);
print_r($result);
?>

如果我通过以下方式从命令行调用脚本:sudo -u www-data /usr/bin/php test.php 一切都会按预期运行,但是当我通过 Apache 调用脚本时,我在 apache2/error.log 中收到以下错误:

sudo: PERM_ROOT: setresuid(0, -1, -1): Operation not permitted

我已经将 Ubuntu 从 12.02 升级到 14.04。同样的脚本在 Ubuntu 12.02 中运行没有任何问题。有人能帮我吗?错误在哪里?

www-data 的群组:
echo390:~$ groups www-data
显示
www-data : www-data

作为信息:
我使用Apache-mpm-itk 模块 这样每个 Apache 虚拟主机都在单独的用户 ID 下运行。那么如何允许特定 Apache 用户以 root 权限执行特定 shell 脚本(在 php 等中)?

提前致谢并致以亲切的问候 Ravermeister

答案1

修复apache2.4并将mpm-itk
其放置在/etc/apache2/conf-enabled/security.conf

<IfModule mpm_itk_module>
    LimitUIDRange 0 6000
    LimitGIDRange 0 6000
</IfModule>

然后重新启动apache

这不是必需的,apache2.2但是一旦我升级到apache2.4正在使用的 PHP 脚本,shell_exec它就会sudo停止工作。

答案2

我发现建议禁用 mpm-itk 相当奇怪,因为实际使用它可能有原因。

我们将 mpm-itk(版本 2.4.7-02)与 apache 2.4 结合使用,效果非常好。这里唯一需要考虑的是新的配置指令

LimitUIDRange

LimitGIDRange

这些指令定义 mpm-itk 可以使用哪些 UID 和 GID(通过 setuid/setguid)。由于您显然希望它能够成为 root,因此您的下限范围必须是 ID 0。以下配置将在此处起作用:

<IfModule mpm_itk_module>
    LimitUIDRange 0 6000
    LimitGIDRange 0 6000
</IfModule>

请注意,上边界应该包括您想要通过 AssignUserID 在配置中使用的所有用户 UID/GID 组合。

请注意,您可以为每个虚拟主机配置此功能。还请注意,您需要 Linux 内核 3.5.0 或更高版本才能实现此功能。

答案3

您的 sudoers 配置是正确的,事实上当您执行:

  sudo -u www-data /usr/bin/php test.php

它按预期工作。

在正常运行中,您的阿帕奇运行为并使用mpm-itk模块。这就是问题所在。

根据mpm-itk 文档

由于 mpm-itk 必须能够设置用户标识(),它以 root 身份运行(尽管在可能的情况下受到 POSIX 功能和 seccomp v2 的限制),直到请求被解析并且 vhost 确定。

和:

mpm-itk 基于传统的 prefork MPM,这意味着它是非线程化的;... 您还会比 prefork 承受额外的性能损失,因为每个请求都有一个额外的 fork。

这意味着mpm-itk阿帕奇处理并使用 setuid() 以便为每个虚拟主机分配所需的用户。

根据setuid 手册

setuid() 函数检查调用者的有效用户 ID,如果是超级用户,则所有与进程相关的用户 ID 都设置为 uid。发生这种情况后,程序将无法重新获得 root 权限。

这已经可以解释,但不相信,我下载了源代码mpm-itk我注意到它发生了变化能力允许并限制uid范围从1到UINT_MAX。

如果线程从其允许集中删除一项能力,则它永远无法重新获得该能力

我的结论是,通过使用mpm-itk你的 php 脚本无法获得 root 权限。

如果有机会,你可以检查是否正在运行阿帕奇作为www-数据并禁用mpm-itk模块你的测试.php作品。

相关内容