让PHP执行shell脚本的正确且安全的方法

让PHP执行shell脚本的正确且安全的方法,php,linux,shell,security,permissions,Php,Linux,Shell,Security,Permissions,我正在开发一个应用程序,人们(任何人)都可以上传将在服务器上编译和运行的代码(Java和可能的C++)。这当然是一个巨大的安全风险,所有这些都需要适当的沙盒不过,这个沙箱不在这个问题的范围之内。假设已经解决了这个问题 接下来,系统中将有一些函数依赖于shell命令和PHP的exec()、shell_exec()等函数。需要执行的命令并不多,主要是java(c)、gcc、g++,等等。如果需要的话,列出我们需要的命令是相当容易的。一旦我们决定,用户将不可能执行其他命令。例如,有人上传一些java代

我正在开发一个应用程序,人们(任何人)都可以上传将在服务器上编译和运行的代码(Java和可能的C++)。这当然是一个巨大的安全风险,所有这些都需要适当的沙盒不过,这个沙箱不在这个问题的范围之内。假设已经解决了这个问题

接下来,系统中将有一些函数依赖于shell命令和PHP的exec()、shell_exec()等函数。需要执行的命令并不多,主要是java(c)、gcc、g++,等等。如果需要的话,列出我们需要的命令是相当容易的。一旦我们决定,用户将不可能执行其他命令。例如,有人上传一些java代码并要求服务器编译。然后服务器将运行javac。用户的输入只能更改javac的参数(使用escapeshellarg()转义)

我想知道我还应该采取什么安全预防措施。我计划使用PHP的安全模式,这样只有
safe\u模式\u exec\u dir
中的文件才能执行。我还计划将shell文件的所有权设置为
root:www-data
,这样www-data就不能更改权限或所有权,并且还计划拥有类似
rwxr-xr--
的权限,这样www-data就不能修改该文件。但是,从5.4.0起,PHP中已删除了安全模式。目前做这类事情的方式是什么

让完全不同的用户运行这些shell命令会更安全吗?除了
safe\u mode\u exec\u dir
,这些用户甚至无法访问任何其他目录?那我该怎么做呢

另一种选择是让PHP只维护一个需要完成的事情的列表,并让一个受限制的用户每隔一分钟左右运行一次cronjob,以遍历该列表并执行必要的操作。这是一种更安全的方法吗?由于最多一分钟的延迟,我更愿意直接从PHP执行此操作


我可以完全访问我的服务器,但由于政策的原因,我不允许使用虚拟化。

实际上,当给人们这种自由时,唯一真正安全的步骤是为每个用户会话启动一个新的虚拟实例,并在会话关闭时“烧掉”它。
如果您想要某种持久性,可以对他们的输入进行分类,并在下次他们访问时在新实例上运行它。即使这样,也有很大的利用空间,但对系统的破坏应该是有限的。

在我看来,一个好的简单方法是使用LXC容器来获得一个安全的环境来编译和运行脚本

您说您不能使用虚拟化,但从技术上讲,它只是流程隔离。就像服用类固醇的白痴。我有一个容器主机,它本身就是一个VM,到目前为止我还没有遇到任何问题。实际上,LXC不是虚拟化,应该适合您的需要

以下是一些介绍链接:

例如,您可以为每个游戏创建一个模板容器,其中包含编译和运行上载代码所需的所有库。此模板可以根据您对cpu、ram和磁盘IO的需要进行保护和限制。我认为使用
lxc.network.flag=down
lxc.network.type=empty
关闭网络也是一个好主意

然后,当上传代码时,您可以克隆模板容器,将代码放入其中,让它生成并运行代码

所有这些都可以通过一个从php调用的shell脚本来完成,或者通过一系列php系统调用来完成,但这听起来并不好

对于你想做的事情,使用非特权容器是必须的,因为它提供了额外的安全层

我建议使用Ubuntu14.04作为LXC主机。我认为一个经过调整的busybox模板和适当的工具来编译和运行代码是您可以得到的最轻的容器

以下是我的想法:

// clone the prepared template
lxc-clone -o myTemplate -n newContainer

// put the code archive in the new container
cp path/to/code path/to/container/and/where/you/want

// Start the container as a daemon
lxc-start -n newContainer -d

// Then launch the right script for the type of code in the container
lxc-attach -n newContainer -- su containeruser -c /path/to/script.sh
因此,小任务是创建具有所需LIB的模板。另一项工作是编写最后调用的脚本


祝您的项目好运,我希望这会有所帮助。

您希望创建一个能够编译java程序并启动它们的服务

我不理解你的问题不是关于如何安全地启动那些程序,因为你认为它已经被处理好了

因此,您想知道如何安全地启动shell脚本,在该脚本中,您将给出源代码的名称以及
javac
的参数

首先,你有很多事情要做

您希望使用系统调用的事实意味着您将在整个虚拟主机中允许
exec
。因此,如果您的FTP密码、一个PHP文件或任何东西被泄露,攻击者可以上传脚本、二进制程序并执行。

  • 您必须让PHP在fstab的noexec模式下使用您的网站分区和临时文件夹
  • 您必须使用
    open\u basedir
    限制可以在PHP中访问的文件,这些限制在安全模式结束后仍然存在。然后,您将使用open_basedir允许目录(当然没有noexec标志)
  • 包含您的脚本和脚本的目录将具有root.www-data权限,并且不可由www-data写入
  • 您必须保护传递给脚本的参数(您已使用
    escapeshellarg
    )和java文件名中的任何潜在注入(但我们假设它在传输之前将被重命名,以避免您将收到的不同java文件中的文件名冲突)

  • PHP中的安全模式并不像您想象的那样安全

    Functi