12

我目前在 CentOS 机器上托管Drupal 6 站点。Drupal ( CMS ) 配置包含几十个第三方模块,它们不应该作为一般的最佳编码实践进行分叉。但是,其中一些模块使用phpexec命令才能正常运行。

该站点允许管理员通过 UI 配置在任何页面中嵌入 php 代码片段,前提是他们有权访问 php 代码输入格式。我需要让管理员可以使用这种输入格式,因为有几个节点(页面)和面板窗格使用小的、无害的 php 代码片段,例如将特定表单嵌入到内容区域中。

问题是,如果有人要破坏管理员帐户,那么他们可以在站点上运行任意 php 代码,从而通过 php 的exec,passthru等运行 shell 命令。有没有办法从操作系统级别限制什么 shell命令php可以传递给机器吗?这可以通过限制来自 php 的某些程序的文件权限来完成吗?

注意:我不能使用 php.ini disable_functions指令,因为exec在许多情况下我仍然需要正常运行,其中模块使用某些 shell 命令,例如视频编码。

4

5 回答 5

10

如果您的管理员帐户被黑客入侵,您就完蛋了。你试图减少注定的命运,但这不会奏效。

禁用 exec()

这只是能够调用系统的所有函数的一小部分。还有更多,例如passthru(), shell_exec(), popen(), proc_open(), 反引号运算符等等。不会有帮助。

限制可用的可执行文件

只有当攻击者不能带来他自己的可执行文件时才会起作用。但file_put_contents()将能够将可执行文件写入硬盘,然后可以调用它。也不会帮忙。

PHP 本身不会造成任何伤害,不是吗?

错误的。在服务器上执行东西exec()似乎是最好的主意,但 PHP 本身功能强大,足以对您的服务器以及与之连接的任何东西造成严重破坏。

我认为唯一真正的解决方案是:

不要让您的管理员帐户被黑客入侵。

如果他们被黑客入侵,可以立即知道。能够将攻击追溯到管理员。能够知道攻击者对您的机器做了什么,以便您可以撤消它。一个非常重要的部分是您实现了一个审计跟踪记录器,它将其数据保存在不同的机器上。

而且您可能首先对谁可以以管理员身份登录实施更严格的限制。例如,如果您确定某个管理员总是使用其本地 ISP 的 IP 范围工作,则可能不需要允许整个世界的 IP 范围登录。至少,敲响铃并通知其他人,如果这不是预期的(除非您在中国经营:-)),正在从中国登录。

并且有两个因素身份验证。您可以使用额外的登录代码向电话号码发送短信。或者,您可以通过实施 Google 或 Facebook 身份验证来完全外包登录。这些参与者已经拥有支持这一点的基础设施。

此外,您对内部工作的抵抗力更高。人们确实比雇主的登录更重视他们的个人社交网络登录。获取某人的 facebook 密码平均需要 30 美元,但公司登录已经共享 8 美元。去搞清楚...

于 2013-04-03T23:14:49.227 回答
7

回答您的问题:理论上,如果您使用 PHP 可以运行命令的极其受限的帐户创建用户帐户,您可以调整您的安装以更安全。然而,真正的问题是管理员用户能够执行任意命令。如果发生这种情况,您将面临更大的问题。

这里真正的解决方案是:

  • 从 Drupal 中提交和运行任意代码的能力是一个重大风险,您可以通过不这样做来减轻风险。我强烈建议重新设计那些“无害”的代码,因为它们会导致妥协;任意代码执行只是一种利用方式,还有很多其他需要担心的。
  • 需要运行 shell 命令的模块也是重大的安全漏洞。在某些情况下,我已经能够对执行命令的模块进行 fork/patch 或替换为不执行命令的模块,但在某些情况下(例如视频编码),这是无法避免的。在这种情况下,我会设置一个非常受限的后端服务,前端可以与之通信。这将您的关注点分开,并让 Drupal 做它打算做的事情:管理和提供内容。
于 2013-03-30T04:05:54.317 回答
2

这不在操作系统级别,但在 Drupal 核心内部有一个名为 PHP 的模块。您可以使用它作为基础并创建一个自定义模块来扩展此模块的功能,然后只需启用此模块而不是 Drupal 6 核心模块。然而,最大的问题在于禁用 Drupal 6 核心模块,然后启用新模块。我会在开发安装上对其进行测试,以确保没有删除以前的内容并且新模块正确解析存储的 PHP 输入。应该没问题,因为模块安装只有一个禁用钩子警告,针对现在以纯文本显示的 PHP 内容。

至于扩展核心模块,这是一个非常简单的模块。您可以在允许或不允许执行的命令列表中进行硬编码。然后,您可以根据此列表检查带有已解析变量的 exec 语句,并执行任何适当的操作。与简单地阻塞在操作系统级别的程序本身相比,这并不是完美的匹配,但总比没有好。要对列表进行硬编码,您只需修改模块文件底部的 php_filter 钩子,然后在执行 drupal_eval 之前进行测试。

您还可以扩展此模块以在 Drupal 管理界面中进行配置,以创建该列表而不是对其进行硬编码。希望这个想法有所帮助。

于 2013-04-05T15:09:25.193 回答
2

另一种方法:

我们认为,我们需要创建一个只能访问系统的测试用户,以便对网络上的另一台机器执行 telnet。由于我们只需要运行 telnet,因此需要限制标准 bash 会话中可用的其他命令。让我们一步一步地配置一切。

1)我们创建用户测试

这将是系统的普通用户,我们作为普通用户也应该如此。唯一的特点是我们更改了该用户的外壳。默认通常是/bin/bash,我们将设置/bin/rbash。rbash 实际上是 bash 的副本,但它确实是“受限制的 bash”。

shell> adduser --shell /bin/test rbash

2)我们创建文件。bash_profile

我们必须在已创建的用户家中创建此文件,并且我们要为其应用权限。文件内容如下,

if [-f ~/.bashrc]; then
    . ~/.bashrc
fi

PATH = $HOME/apps
export PATH

3)我们避免改变

创建文件后,我们将阻止任何人对文件进行更改。

shell> chattr +i /home/test/.bash_profile

4)我们创建应用程序目录并安装程序“访问”

现在,一旦您完成了所有设置并且只需要创建应用程序并在其中创建一个链接,该链接将指向您希望用户拥有权限的程序。应用程序中的所有程序,用户都可以运行,但是不行。

shell> mkdir apps
shell> ln-s /usr/bin/telnet /home/test/apps/

5)我们发现可行

现在您可以访问系统并验证它是否正常工作。

shell> ssh test@remote
test@remote password:

shell@remote> ls
-rbash: ls: command not found
shell@remote> cd
-rbash: cd: command not found
shell@remote> telnet
telnet>
于 2013-04-05T20:42:15.457 回答
0

团队:

这是我的方法......

我创建了一个包含已接受命令列表的小脚本,根据命令,将控制执行以避免出现问题。我不确定它是否在问题的范围内。示例代码在 Windows 中具有命令,但您也可以在 Linux 中使用它...

<?php
ini_set('display_errors',1); 
error_reporting(E_ALL);

function executeCommand($my_command){
    $commandExclusions = array ('format', 'del');

    if (in_array(strtolower($my_command),$commandExclusions)) {
        echo "Sorry, <strong>".$my_command." </strong> command is not allowed";
        exit();
    }
    else{
        echo exec($my_command, $result, $errorCode);
        implode("n", $result);
    }
}
echo "<h3>Is it possible to restrict what commands php can pass through exec at an OS level?</h3><br>";
echo "********************************<br>";
//test of an accepted command
echo "test of an accepted command:<br>";
executeCommand("dir");
echo "<br>********************************<br>";
echo "test of an unaccepted command:<br>";
//test of an unaccepted command
executeCommand("format");
echo "<br>********************************<br>";
?>

输出:

是否可以在操作系统级别限制 php 可以通过 exec 传递的命令?


接受命令的测试:117 Dir(s) 11,937,468,416 字节空闲


测试未接受的命令:对不起,格式命令是不允许的

于 2013-04-05T15:22:24.330 回答