允许 PHP 以 root 权限执行 bash 脚本

发布于 2024-10-02 22:28:28 字数 389 浏览 5 评论 0原文

如何让PHP脚本以root权限执行bash脚本?

假设有一个 PHP 脚本...

<?php
// location: /var/www/script.php
exec("bash /var/scripts/test.sh"); // "sudo bash ..." does not work
?>

和一个 bash 脚本...

#!/bin/bash
# location: /var/scripts/test.sh
sudo mkdir /test

当然 PHP 和 Apache 不应该以 root 身份运行,最多只能使用 root 权限执行脚本。有什么想法吗?

此致, 金宝

how to allow a PHP script to execute a bash script with root permissions?

Let's say there is a PHP script...

<?php
// location: /var/www/script.php
exec("bash /var/scripts/test.sh"); // "sudo bash ..." does not work
?>

and a bash script ...

#!/bin/bash
# location: /var/scripts/test.sh
sudo mkdir /test

Of course PHP and Apache should not run as root and at best only the script can be executed with root permissions. Any ideas?

Best regards,
Jimbo

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

别理我 2024-10-09 22:28:28

任何在链的某个点授予 root 权限的基于 PHP 的解决方案都是危险的:有权访问 PHP 用户的攻击者可能会获得对 root 用户的访问权限,从安全角度来看,这是不可接受的。

我自己从未实现过这个,但我会建议我的建议 这里:有一个具有 root 权限的脚本/cron 作业经常扫描 PHP 脚本中某个位置以获取要完成作业的标志 - 例如,一个文件具有特定名称或作业数据库中的条目。

如果发现该文件存在,根脚本就会执行其操作,并再次删除该文件。

如果您的 PHP 脚本不需要根脚本的直接响应,我认为这将是最好的方法。 (当然,根脚本将状态消息写入文件也可以促进响应)。

只要您严格限制 PHP 可以为 root 脚本编写的作业类型,这就是一个无懈可击的解决方案,因为它不会让 root 用户参与 PHP 的业务。

Any PHP-based solution that gives root rights at some point of the chain is dangerous: An attacker with access to the PHP user could gain access to the root user, and that is unacceptable from a security point of view.

I have never implemented this myself, but I'll suggest what I suggested here: Have a script/cron job with root rights frequently scan some location for a sign from the PHP script that a job is to be done - for example, a file with a certain name, or an entry in a jobs database.

If that file is found to exist, the root script does its thing, and removes the file again.

If your PHP script doesn't need direct response from the root script, I think this would be the best way to go. (A response could also be facilitated by the root script writing a status message into the file, of course).

As long as you closely limit what kinds of jobs PHP can write for the root script to do, this is a watertight solution, as it doesn't get the root user into PHP's business.

人事已非 2024-10-09 22:28:28

如果不想等待 cron,这里有一个简单的 C 包装器,您可以从 php 调用它。

#include <unistd.h>
#include <errno.h>
#define WEBUID 500
main( int argc, char ** argv, char ** envp ) {
    if( getuid() != WEBUID ) exit(1);
    /* some more security checks */
    if( setuid(geteuid()) ) perror( "setuid error" );
    envp = 0; /* don't want environment - security problem */
    system( "/hardcoded/path/to/script.bash", argv, envp );
}

此编译的包装器应由 root、组“www”拥有,并且应具有“s-bit”。
chwon root.www 包装器; chmod 4440 包装器,因此

  • 当执行时,他的有效 UID 将是 root
  • 执行它只能组 www(网络服务器的组),
  • 并且当调用者的 UID 不是网络服务器时将退出

If don't want wait for cron, here is a simple wrapper in C, what you will call from php.

#include <unistd.h>
#include <errno.h>
#define WEBUID 500
main( int argc, char ** argv, char ** envp ) {
    if( getuid() != WEBUID ) exit(1);
    /* some more security checks */
    if( setuid(geteuid()) ) perror( "setuid error" );
    envp = 0; /* don't want environment - security problem */
    system( "/hardcoded/path/to/script.bash", argv, envp );
}

This compiled wrapper should be owned as root, group "www" and should have "s-bit".
chwon root.www wrapper; chmod 4440 wrapper, so

  • when is executed his effective UID will be root
  • execute it can only group www (web-server's group)
  • and when the UID of the caller is not a web-server will exit
往昔成烟 2024-10-09 22:28:28

您需要查看 incron(文件系统事件的 cron)。让 php 写入文件并设置 incron 以在写入文件关闭时启动脚本(incron 非常具体)。您的脚本可能还应该清理输入文件以防止代码注入,并使用 lockfile 命令来防止多个 Web 用户之间出现任何竞争条件。

我有一个迷你 Web 界面,可以使用密码打开匿名 FTP 或其他服务 1 小时。 www 与 www-data(php 用户)一样以正常权限运行,但 incron 以 root 身份调用输入处理脚本。

麦克风

You need to take a look at incron (cron for file system events). Have the php write to a file and set incron to launch your script on closure of the written to file (incron is very specific). Your script should probably also sanitize the input file to prevent code injection and use the lockfile command as well to prevent any race conditions between multiple web users.

I have a mini-web interface where one can turn on anonymous FTP or other services on for 1 hour with a password. www runs with normal privilages as does www-data (the php user) but incron calls the input handling script as root.

Mike

青春有你 2024-10-09 22:28:28

您可能不需要 PHP 或 Apache 以 root 身份运行。如果您可以控制服务器,则可以使用名为 suPHP 的 Apache 模块,并在配置中指定要为 php 脚本运行 Apache 的用户。您可以逐个站点执行此操作,因此您只需为特定域上的脚本运行 suPHP。我缺乏专业知识来建议您如何安装它,但我让我们的专用服务器公司为我做这件事,以允许 github post-receive hook 调用我的开发服务器上的脚本,以触发 git pull 到开发服务器任何有人推送到 github 存储库的时间。我无法让它以任何其他方式工作,因为 Apache 需要作为本地存储库的所有者运行才能工作。

我只是根据这里的其他评论想到了另一种可能的解决方案——您也许可以编写一个简单的 php 脚本来接收来自 github 挂钩的请求,并将一些任意信息写入具有 777 权限的目录中的文件或数据库。然后有一个 cron 作业每分钟检查该文件或数据库以查看它是否已更改,如果已更改,则直接发出 git pull 请求,因为 cron 通常已经以 root 身份运行。您甚至可以仅查看文件的时间戳是否已更改来确定是否执行 git pull。您可以将 cron 脚本 su 到拥有该存储库的任何用户,然后发出 git pull 。这不是真正的实时解决方案,但如果 cron 脚本非常简单,那么每隔一两分钟调用它就不会真正让您的系统陷入困境。希望有帮助。

You may not need PHP or Apache to run as root. If you have control of your server you might be able to use an Apache module called suPHP and specify the user you want to run Apache as for your php scripts in the config. You can do this on a site by site basis so you only need to run suPHP for scripts on a particular domain. I lack the expertise to advise you on how to install it, but I had our dedicated server company do it for me to allow a github post-receive hook to call a script on my dev server to trigger a git pull to the dev server any time someone pushes to the github repos. I was unable to get it to work any other way since Apache needs to run as the owner of the local repos for it to work.

I just thought of another possible solution based on the other comments here -- you might be able to write a simple php script to receives the request from the github hook and write some arbitrary info to a file in a directory with 777 permissions or to the db. Then have a cron job that checks that file or db every minute to see if it has changed and if so, issue the git pull request directly since cron usually runs as root already. You could even just see if the file's timestamp has changed to determine whether to do the git pull. You could have your cron script su to whatever user owned the repos and issue the git pull then. Not a true realtime solution, but if the cron script is very simple it wouldn't really bog down your system to call it every minute or two. Hope that helps.

如梦 2024-10-09 22:28:28

使用以 root 身份运行的守护程序(可能用 C 语言编写),它会为您启动 shell 脚本。要从 PHP 脚本内触发 shell 脚本执行,只需使用 IPC(消息队列)。

看看这里,了解我在说什么: http:// /php.net/manual/en/function.msg-send.php#114831

Use a daemon running as root (maybe written in C), which starts the shell scripts for you. To trigger shell script execution from within the PHP script just use IPC (message queues).

Have a look here to get an idea what I am talking about: http://php.net/manual/en/function.msg-send.php#114831

夕色琉璃 2024-10-09 22:28:28

我最近发布了一个项目,允许 PHP 获取真实的 Bash shell 并与之交互(如果需要,可以作为 root),它解决了 exec() 和 shell_exec() 的限制。在这里获取它: https://github.com/merlinthemagic/MTS

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

$shell    = \MTS\Factories::getDevices()->getLocalHost()->getShell('bash', true);
$return1  = $shell->exeCmd('/my/bash/script.sh');
//the return will be a string containing the return of the command
echo $return1;

就安全性而言,它比以root身份运行apache要好得多。但让 PHP 靠近 root 的位置总是很棘手。

我构建的项目通过以下两种方式之一实现 root bash shell:

1)您允许 apache sudo python 的权利。

或者

2) 每次需要具有 root 设置的 shell 时,都将 root 凭据传递给对象。

选择你的毒药。 :) 阅读文档。

I recently published a project that allows PHP to obtain and interact with a real Bash shell (as root if requested), it solves the limitations of exec() and shell_exec(). Get it here: https://github.com/merlinthemagic/MTS

After downloading you would simply use the following code:

$shell    = \MTS\Factories::getDevices()->getLocalHost()->getShell('bash', true);
$return1  = $shell->exeCmd('/my/bash/script.sh');
//the return will be a string containing the return of the command
echo $return1;

In terms of security it is far better than running apache as root. But letting PHP anywhere near root is always tricky.

The project i built achieves a root bash shell in one of 2 ways:

1) You allow apache the right to sudo python.

OR

2) You pass root credentials to the object every time you need a shell with root setup.

Pick your poison. :) Read the documentation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文