我可以将 PHP include() 限制为特定的目录树吗?

信息安全 php
2021-08-19 18:00:33

我知道我可以使用 php.iniopen_basedir指令来限制 PHP 可以打开文件的目录树。

但是在这样的目录结构中:

├── application
│   ├── index.php
│   └── www
├── logs
└── uploads
    └── malicious.php.jpg

有什么方法可以防止恶意.php.jpg 被评估为 PHP,如果它是在 中指定的include(),而不阻止 PHP 读取/写入上传到/从该目录上传?

编辑:我可能应该指定我对基于配置或权限的解决方案感兴趣。

3个回答

根据您的设置,您可能能够使用强制访问控制来获得接近您想要的东西。例如,考虑一个使用 apparmor 运行 linux 的系统。通过使用 apparmor,您可以限制允许哪些脚本访问上传目录。不是一个完美的解决方案,因为几个脚本仍然能够“包含”这些文件,但是您可以限制可以包含的脚本数量。

例如,您可以允许upload.php 访问uploads 目录,但拒绝index.php 访问该目录,即使它们以同一用户身份运行。

我假设你可以用 SELinux 等其他 MAC 系统做类似的事情。

include()如果不通过编辑 PHP 源代码并编译您自己的二进制文件来修改函数系列的默认行为,就无法做到这一点。但是,老实说,这有点毫无意义。为了malicious.php.jpginclud编辑,您的代码中需要一个文件包含漏洞,例如include($_GET['file']).

下一个最好的事情是使用运行某些输入验证的全局包含函数完成所有包含。该功能可以控制可以访问哪些目录。

不,不是。这样做的唯一方法是在操作系统级别限制 PHP 可以读取的文件。即使您设法以某种方式限制可以使用include()or读取的路径require(),您仍然不会阻止执行:脚本可以很容易地使用普通fopen()功能来读取文件,然后只是读取文件,eval()效果完全相同。

但是,如果代码可以自由地执行所有这些操作,那么文件包含是您最不关心的问题。事实上,如果您正确编写代码,甚至不应该包含恶意文件。如果名称来自用户输入,那么您永远不应该(不真的,永远)包含或执行文件。如果你这样做,我可以断然说你做错了。

但是,如果您想限制可包含/可执行/可读文件的范围,那chroot就是它所在的位置。设置起来有点繁琐,但提供了所需的保护级别。