添加到sudoers.d的脚本没有以root身份执行

4
在一个xubuntu机器上,我有以下脚本让PHP创建由我的用户拥有的目录:
<?php
if(!isset($_REQUEST['path'])) die('No path specified');
$path = $_REQUEST['path'];
$res1 = shell_exec("sudo mkdir -p $path");
$res2 = shell_exec("sudo chown -R majid:majid $path");
var_dump($res1, $res2);
?>

该脚本位于/var/www/path/to/mkdir.php

我还将此文件添加到/etc/sudoers.d/grantmkdir,内容如下:

www-data ALL=(ALL:ALL) NOPASSWD: /var/www/path/to/mkdir.php

我已将文件的chmod更改为0440。从浏览器访问mkdir.php时,变量转储的输出为NULL NULL,并且没有创建任何目录。我做错了什么?


1
你是否已经通过sudo添加了运行mkdir和chown命令的权限?在我看来,你正在不使用sudo运行PHP脚本,然后尝试在其中使用sudo运行命令。这不是它的工作方式,要么使用sudo运行mkdir.php(然后其中的sudo是多余的),要么授予www-data运行mkdir/chown的权限(涉及系统安全时不是一个好主意)。 - user2845360
@SamiLaine 我看到这个方法与大多数PHP sudo的示例不同。在我检查过的示例中,访问的脚本是一个shell脚本而不是PHP源代码。这是问题吗?如果我们想使用一个shell脚本,我们能像使用PHP源代码一样提供路径吗? - Majid Fouladpour
@GerdK,我不明白你的问题。你能再解释一下吗? - Majid Fouladpour
你是否已经验证了在php.ini中disable_functions选项中是否禁用了shell_exec - FuzzyTree
1
@FuzzyTree,情况并非如此。shell_exec未被禁用,并且在同一源代码中的其他行上成功执行(此处未包含)。 - Majid Fouladpour
显示剩余3条评论
1个回答

1
你的设置有点混乱。
当你从浏览器访问这个脚本时,apache会以www-data用户身份启动它。
sudo不会被执行。你不能让apache通过sudo调用你的脚本。你必须将敏感的脚本包装成sudo调用。
例如,这样做:
创建两个脚本。第一个将由apache调用,第二个将通过第一个脚本通过sudo调用。

first.php:

<?php
if(!isset($_REQUEST['path'])) die('No path specified');
$path = $_REQUEST['path'];
// By the way here you should verify the path! Otherwise malicious users can make your system execute whatever they want...
shell_exec("sudo /var/www/path/to/second.php " . $path);
?>

second.php

#!/usr/bin/php
<?php
shell_exec("sudo mkdir -p " . $argv[1]);
shell_exec("sudo chown -R majid:majid " . $argv[1]);
?>

并使 second.php 可以通过 sudo 执行:

/etc/sudoers.d/second

www-data ALL=(ALL:ALL) NOPASSWD: /var/www/path/to/second.php

这样,Apache 将启动 first.php,并使用 sudo 启动 second.php。
您可以通过登录服务器并切换到 www-data(su www-data)来测试 sudo 设置是否正常。然后手动运行脚本。
一些注意事项:
- 检查错误日志可能会很有用(tail /var/log/apache/error_log 或类似的命令)。 - 不要忘记验证输入,否则您的系统将容易受到攻击。有关此问题的详细信息和解决方案,请参见 http://php.net/escapeshellarg。 - NULL NULL 可能是正常的。详情请参见 http://php.net/shell_exec

Note:

This function can return NULL both when an error occurs or the program produces no output. It is not possible to detect execution

failures using this function. exec() should be used when access to the program exit code is required.


那么我们不应该在第一个脚本中使用 shell_exec("sudo php /var/www/path/to/second.php " . $path); 吗?而且第二个脚本不可能是一个 shell 脚本(.sh)并仍然将 path 传递给它吗? - Majid Fouladpour
是的,两种方法都可以。它可以通过php调用。我将“#!/usr/bin/php”添加到第一行,这应该告诉sudo通过php运行脚本。但也可以创建一个shell脚本代替。(也许这更容易。) - Lajos Veres
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Majid Fouladpour

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接