【问题标题】:Execute root commands via PHP通过 PHP 执行 root 命令
【发布时间】:2012-01-21 20:52:38
【问题描述】:

我有一个 CentOS 5.7 linux 服务器并使用 php5.3.x。

在 pfSense 系统上,您可以使用 php 网页重新启动需要 root 权限的服务。

我正在尝试做类似的事情,我已经编写了一些 php 代码来执行 shell 命令。比如重启sshd服务:

<?php
exec('/sbin/service sshd restart');
?>

我尝试通过 exec 函数执行该命令,但它需要 root 权限,但我们有 apache 用户权限。

我遇到了一些解决方案:

  1. “以 root 用户运行 apache” 真的不安全。我不想那样做。
  2. “apache ALL=NOPASSWD:/sbin/service 到 /etc/sudoers” 我试过了,但还是有问题。

还有其他解决方案吗? 感谢您的回答。


现在.. 这很有趣。我尝试了@refp post,它在我的本地ubuntu服务器上工作。但是当我在我的 cenOS vps 服务器上尝试相同时。它不起作用。那是 apache 的错误日志“rm: cannot remove `/var/lock/subsys/vsftpd': Permission denied”

【问题讨论】:

  • 还有,您尝试过sudoers 解决方案吗?你有什么问题?您是否在exec() 命令中添加了sudo?或者error.log、syslog 或/var/log/auth.log 中的任何有价值的东西?
  • tail /var/log/httpd/error.log "sudo: 抱歉,你必须有一个 tty 才能运行 sudo"
  • Run a linux system command as a superuser, using a python script 的可能重复项(查看最后一个答案)
  • 感谢 mario 的回答,但仍有问题。 "ALL = NOPASSWD: /etc/init.d/postfix" 我已经测试了类似 "apache ALL=NOPASSWD: /sbin/service" 的方法。 . .我不明白为什么 sudoers 文件不使用该行向 apache 用户授予权限。
  • 您可以限制 sudo 执行(为什么 ALL 作为主机规范?localhost 应该足够了!)。此外,如果您的sudoers 有它,请删除Defaults require_tty,因为 Apache 不会在附加 tty 的情况下运行。

标签: php apache permissions root


【解决方案1】:

在尝试之前阅读整篇文章,有很多选择。


使用二进制包装器(带有 suid 位)的解决方案

1) 创建一个脚本(最好是.sh),其中包含您希望以 root 身份运行的内容。

# cat > php_shell.sh <<CONTENT
  #!/bin/sh
  /sbin/service sshd restart
CONTENT

2)这个文件应该归root所有,因为它稍后会以root权限运行,所以确保只有root才有权限写入文件。

# chown root php_shell.sh
# chmod u=rwx,go=xr php_shell.sh

3) 要以 root 身份运行脚本,无论是哪个用户执行它,我们都需要一个二进制包装器。创建一个将执行我们的php_shell.sh

# cat > wrapper.c <<CONTENT
  #include <stdlib.h>
  #include <sys/types.h>
  #include <unistd.h>

  int
  main (int argc, char *argv[])
  {
     setuid (0);

     /* WARNING: Only use an absolute path to the script to execute,
      *          a malicious user might fool the binary and execute
      *          arbitary commands if not.
      * */

     system ("/bin/sh /path/to/php_shell.sh");

     return 0;
   }
CONTENT

4)编译并设置适当的权限,包括suid位(说它应该以root权限运行):

# gcc wrapper.c -o php_root
# chown root php_root
# chmod u=rwx,go=xr,+s php_root

php_root 现在将以 root 权限运行,并执行php_shell.sh 中指定的命令。


如果您不需要轻松更改将要执行的命令的选项,我建议您直接在步骤 4 下的wrapper.c 中编写命令。然后,您不需要让二进制文件执行执行相关命令的外部脚本。

wrapper.c 中,使用system ("your shell command here"); 指定您要执行的命令。

【讨论】:

  • 来自 test.php 的代码。用于执行 bash 脚本。 这里 php_root.sh 代码 #!/bin/bash /sbin/service vsftpd stop,我给你做了 chmod 和 chow 命令。仍然不工作。这是 error.log 输出“rm: cannot remove `/var/lock/subsys/vsftpd': Permission denied”
  • 问题已通过 refp 答案解决。我忘了在 php_shell.sh 中添加 /sbin 路径到命令。非常感谢!
  • @refp 我猜你的帖子“接受”了。感谢您的关注和帮助。我怎样才能给你代表?
  • 我已经完成了上面提到的所有 4 个步骤,但在 CentOS 6 上仍然出现权限被拒绝错误。有人遇到同样的问题吗?
  • 这就像创建一个rootkit 将其放置在您自己的系统中并等待有人查看php 源代码并触发任何命令直接访问您的linux 系统。
【解决方案2】:

我不会让 PHP 执行任何 sudo 命令。对我来说,这听起来像是自找麻烦。相反,我会创建两个独立的系统。

第一个系统,在 PHP(Web 层)中,将处理用户请求。当发出需要 sudo 命令的请求时,我会将此请求放在某个队列中。这可能是某种数据库或诸如 ZeroMQ 之类的中间件。

第二个系统(业务层)将从该队列读取或接收消息,并能够执行 sudo 命令,但不在您的网络服务器进程的范围内。

我知道这有点模糊,可以通过各种技术以不同的方式解决,但我认为这是最好和最安全的方法。

【讨论】:

    【解决方案3】:

    允许www-data用户运行程序1和程序2,无需密码:

    sudo visudo
    

    添加到 sudoers 文件的内容:

    User_Alias WWW_USER = www-data
    Cmnd_Alias WWW_COMMANDS = /sbin/program1, /sbin/program2
    WWW_USER ALL = (ALL) NOPASSWD: WWW_COMMANDS
    

    保存。

    来自https://askubuntu.com/questions/76920/call-a-shell-script-from-php-run-as-root

    【讨论】:

    • 我更喜欢这个而不是编译一个可执行文件来做这些事情。如果您有时间进行设置,最好的方法肯定是 SuExec。
    • 这里需要说明一下,使用这种方法时需要在命令的开头加上sudo
    【解决方案4】:

    我最近发布了一个项目,它允许 PHP 获取并与真正的 Bash shell 交互,它可以轻松地为您提供一个以 root 身份登录的 shell。然后,您可以只执行单个 bash 命令,而不是捆绑在脚本中。这样你也可以处理退货。在这里获取:https://github.com/merlinthemagic/MTS

    下载后您只需使用以下代码:

    $shell    = \MTS\Factories::getDevices()->getLocalHost()->getShell('bash', true);
    $return1  = $shell->exeCmd('service sshd restart');
    
    echo $return1;
    
    //On CentOS 7 output would be like: 
    //Redirecting to /bin/systemctl restart  sshd.service
    
    //On CentOS 6 and lower output would be like:
    //Stopping sshd:                                             [  OK  ]
    //Starting sshd:                                             [  OK  ]
    

    【讨论】:

    • 尝试在我的 centos 6.7 服务器上运行它时出现很多错误。修复了其中的几个,然后决定放弃。
    • 前往 github 并打开一个记录您遇到的错误的新问题。
    【解决方案5】:

    使用二进制包装器(带有 suid 位)的解决方案Filip Roséen - refp帖子的一些修改。

    执行任何修改过wrapper.c的命令

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <string.h>
    
    int main (int argc, char  **argv)
    {
     setuid (0);
     char cmd[100] = "";
     int i;
     char *p;
     for(i=0; i < argc; i++) {
        if(i != 0){
       strcat(cmd, *(argv+i));
       strcat(cmd, " ");
        }
     }
    
     system (cmd);
    
     return 0;
     }
    

    编译并设置适当的权限;

      gcc wrapper.c -o php_root     # php_root can be any name.
      chown root php_root
      chmod u=rwx,go=xr,+s php_root
    

    现在从 PHP 调用。执行任何命令。

     shell_exec('./php_root '.$cmd);//execute from wrapper
    

    【讨论】:

    • 这是非常危险的。这个二进制包装器将允许以 root 权限执行任何系统命令。如果有人设法未经授权访问您的网站,他们将拥有对您整个服务器的完全 root 访问权限。从安全角度来看,这和在shell_exec('echo &lt;root_password&gt; | sudo -S &lt;cmd&gt;');987654325@等php脚本中以纯文本形式写入root密码是一样的
    【解决方案6】:
    setenforce 0
    

    在终端中写入此命令此命令将禁用 SELinux。 这不是一个好习惯

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-09-01
      • 2018-11-21
      • 2015-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多