为什么向sudoers文件添加PHP脚本不起作用?
向sudoers文件添加PHP脚本似乎没有效果,而添加bash脚本则允许您以root用户身份运行它。为什么向sudoers文件添加PHP脚本不起作用?,php,bash,nginx,permissions,ubuntu-18.04,Php,Bash,Nginx,Permissions,Ubuntu 18.04,向sudoers文件添加PHP脚本似乎没有效果,而添加bash脚本则允许您以root用户身份运行它。 为了证明这一点,假设我们有以下三个脚本: /var/www/literal.php exec('sudo whoami', $output, $return_var); var_dump($output, $return_var); exec('sudo /var/www/script.sh', $output, $return_var); var_dump($output, $return_
为了证明这一点,假设我们有以下三个脚本: /var/www/literal.php
exec('sudo whoami', $output, $return_var);
var_dump($output, $return_var);
exec('sudo /var/www/script.sh', $output, $return_var);
var_dump($output, $return_var);
if (PHP_SAPI !== "cli") {
exec('sudo /usr/bin/php /var/www/control.php param1 param2', $output, $return_var);
echo '<pre>';
var_dump(PHP_SAPI, $output, $return_var);
exit();
}
exec('whoami', $output, $return_var);
var_dump(PHP_SAPI, $argv, $output, $return_var);
/var/www/indirect.php
exec('sudo whoami', $output, $return_var);
var_dump($output, $return_var);
exec('sudo /var/www/script.sh', $output, $return_var);
var_dump($output, $return_var);
if (PHP_SAPI !== "cli") {
exec('sudo /usr/bin/php /var/www/control.php param1 param2', $output, $return_var);
echo '<pre>';
var_dump(PHP_SAPI, $output, $return_var);
exit();
}
exec('whoami', $output, $return_var);
var_dump(PHP_SAPI, $argv, $output, $return_var);
/var/www/script.sh
#!/bin/bash
echo "$(whoami)"
还假设我们在sudoers文件中有以下行(当然是通过visudo添加的):
浏览到http://localhost/literal.php 我们得到:
array(0) { }
int(1)
去http://localhost/indirect.php 然而,我们得到的是:
array(1) {
[0]=> string(4) "root"
}
int(0)
显然,sudoer行适用于shell脚本,但不适用于PHP脚本。这是一个故意的,设计上的限制,还是我有希望让它工作?如果是这样,我应该在哪里查找原因?在sudoers文件中指定要运行的精确命令。所以
/var/www/literal.php
至少应该有一个类似于#的shebang/usr/bin/php
并按原样在shell中启动,方法是键入/var/www/literal.php
,然后输入,以便由sudo
运行
当您“通过浏览器”运行相同的脚本时,不会发生这种情况。相反,PHP-FPM进程正在解释脚本(NGINX将其文件名传递给PHP-FPM)。您可能会说(尽管这并不完全像这样),实际运行的命令或多或少是/sbin/php fpm/var/www/literal.php
,这当然与sudoers文件中的命令不匹配
无论您希望通过PHP脚本以sudo
的形式运行什么命令,您都需要在sudoers中放置前缀为sudo
时运行的命令,例如
www-data ALL=NOPASSWD: /usr/bin/whoami
www-data ALL=NOPASSWD: /var/www/script.sh
然后:
exec('sudo/usr/bin/whoami',$output,$return\u var)
从浏览器访问脚本时将成功运行
这是一个离题,但您不应该以Web服务器用户的身份运行任何内容。www-data
是NGINX/Apache用户。出于安全目的,脚本应在专用的“网站特定”用户下运行。更多信息。根据@DanilaVershinin提供的解释,我认为递归方法可能有效。我试过了,成功了!这就是:
如果我们的PHP脚本检测到正在通过web服务器调用它,它将在CLI中调用自己:
/var/www/control.php
exec('sudo whoami', $output, $return_var);
var_dump($output, $return_var);
exec('sudo /var/www/script.sh', $output, $return_var);
var_dump($output, $return_var);
if (PHP_SAPI !== "cli") {
exec('sudo /usr/bin/php /var/www/control.php param1 param2', $output, $return_var);
echo '<pre>';
var_dump(PHP_SAPI, $output, $return_var);
exit();
}
exec('whoami', $output, $return_var);
var_dump(PHP_SAPI, $argv, $output, $return_var);
我们通过去http://localhost/control.php 显示调用用户是root用户,并且我们已收到参数(sudoers行末尾的*
在我们有参数时仍然匹配。)
这方面的重要问题是安全风险。我将在Github上分享此版本,其中安全风险已得到缓解,并将在此处提供链接。+1谢谢。我担心会是这样。我可以通过一个小测试来证实这一点:当我将shebang添加到literal.php并使用chmod+x/var/www/literal.php
使文件可执行时,我通过在终端中使用sudo/var/www/literal.php
调用它,确实获得了预期的输出。此外,像sudo/var/www/script.sh
这样的调用可以工作;但是运行sudobash/var/www/script.sh
时,会提示输入sudo密码。