如何使用 SELinux 限制 PHP 脚本?

Mic*_*and 8 php selinux mod-php apache-2.2 rhel6

我想在我的 SL6.4(RHEL 6.4 重建)Web 服务器上划分不同的 PHP 应用程序,以便它们无法访问彼此的数据。SELinux 似乎可以做到这一点,但我不确定细节。我的问题有两个部分:

  1. SElinux如何使用mod_php管理Apache进程中运行的PHP脚本?进程是否在运行 PHP 脚本时以某种方式进入脚本上下文,或者仅当脚本通过 CGI 或 FastCGI 在进程外运行时才有效?如果它转换到脚本上下文来运行 PHP 脚本,是什么阻止了 PHP 错误触发转换回主 httpd 上下文?如果我需要一种替代的 PHP 部署方法,那最好知道。
  2. 如何分离脚本/应用程序,以便 TinyTinyRSS 无法访问 OpenCloud 拥有的内容?它看起来像我应该能够通过关闭要做到这一点httpd_unified,并提供独立的httpd_ttrss_*httpd_opencloud_*环境,平行于套httpd_user_foohttpd_sys_foo。考虑到我可以使用的应用程序数量,我什至可以在没有新上下文的情况下使用 sys/user 区别。但是我还没有找到很多关于关闭的含义的文档httpd_unified,或者如何设置不同的 HTTP 上下文。特别是对于通过mod_php.

我很擅长创建新的 SELinux 策略模块,但需要一些文档来指出我需要什么来使新策略执行以及如何使其与 SELinux 目标策略很好地集成。

如果尝试仅使用 SELinux 进行这种分离是一个失败的原因,并且我需要在不同的上下文中启动单独的 httpds,甚至可能是 LXC 容器,那么这也是一个有用的答案。

Mat*_*Ife 5

实现这种分离级别的最佳方法是不使用类型转换,而是使用类别/MCS 转换。这有点像svirtlibvirt KVM 中的实现。

好的,您需要做的第一件事是下载一个名为mod_selinux. 它在 Fedora 存储库中漂浮了很长一段时间,但不幸的是从未真正进入 EL6 系统。

在任何情况下,您都可以从 Fedora 源重新构建包。我在 Fedora 机器上做了这个,但你可以从镜像下载相同的包。我在运行时使用 F16 作为基础httpd-2.2

yumdownloader --source mod_selinux --releaserver=16
...
mod_selinux-2.2.2454-3.fc15.src.rpm                        |  23 kB   00:00
Run Code Online (Sandbox Code Playgroud)

然后下载后,在您的 EL6 盒子上重建。

rpmbuild --rebuild mod_selinux-2.2.2454-3.fc15.src.rpm
...
Wrote: /home/build/rpmbuild/RPMS/x86_64/mod_selinux-2.2.2454-3.el6.x86_64.rpm
Run Code Online (Sandbox Code Playgroud)

最后安装模块。

rpm -i /home/build/rpmbuild/RPMS/x86_64/mod_selinux-2.2.2454-3.el6.x86_64.rpm
Run Code Online (Sandbox Code Playgroud)

RPM 安装了一个httpd您需要的模块以及一个httpd运行此模块所必需的策略。

此模块的文件安装在/etc/httpd/conf.d/mod_selinux.conf.

此过程的第一阶段是增加主 httpd 进程运行的类别数,以便它可以生成跨越正确范围的子线程。在文件更改中:

selinuxServerDomain     *:s0
Run Code Online (Sandbox Code Playgroud)

selinuxServerDomain     *:s0-s0:c0.c1023
Run Code Online (Sandbox Code Playgroud)

现在,您必须为 apache 中的每个虚拟主机分配一个类别。这是通过添加一行来完成的,例如在下面的示例中称为selinuxDomainVal.

<VirtualHost *:80>
    DocumentRoot /var/www/vhosts/host1
    ServerName host1.virtual
    selinuxDomainVal *:s0:c0
</VirtualHost>

<VirtualHost *:80>
    DocumentRoot /var/www/vhosts/host2
    ServerName host2.virtual
    selinuxDomainVal *:s0:c1
</VirtualHost>
Run Code Online (Sandbox Code Playgroud)

接下来,在每个主机的文档根目录中,将它们的文档根目录重新标记为与 httpd 配置中标记的目录相同的类别。

chcon -R -l s0:c0 /var/www/vhosts/host1
chcon -R -l s0:c1 /var/www/vhosts/host2
Run Code Online (Sandbox Code Playgroud)

如果您想通过系统重新标记使标记获得荣誉,您最好也更新本地策略!

semanage fcontext -a -t httpd_sys_content_t -r s0-s0:c0 '/var/www/vhosts/host1(/.*)?'
semanage fcontext -a -t httpd_sys_content_t -r s0-s0:c1 '/var/www/vhosts/host2(/.*)?'
Run Code Online (Sandbox Code Playgroud)

就是这样!现在不可能离开您的文档根目录并在其他人中进行探索。

  • 请注意,`mod_selinux` 并不能完全防止 PHP 漏洞——如果攻击者在利用具有受限上下文的虚拟主机后可以执行受控的内存损坏,他可能能够将代码注入 Apache 进程以在默认的 httpd 中运行上下文,或者为由同一工作进程处理的后续请求关闭 `mod_selinux`。像 APC 这样的缓存也将在所有虚拟主机之间共享。如果这是一个问题,则需要完整的进程分离(对 PHP 使用 CGI 或 FastCGI,如果您也想防止 httpd 错误,甚至可以单独的 httpd 实例)。 (2认同)