PHP 8.2 容器中文件包含防护需三层协同:路径隔离(open_basedir 限定绝对路径)、配置加固(禁用 allow_url_include/allow_url_fopen 及高危函数)、代码约束(白名单映射+realpath 校验),缺一不可。

PHP 8.2 容器环境下限制文件包含读取范围,核心是“路径隔离 + 配置加固 + 代码约束”三层防御,不能只靠某一项。关键不是让 include 绝对安全,而是让它只能碰你允许的那些文件。
设置 open_basedir 限定可访问目录树
这是最直接有效的系统级限制。在容器启动时通过 php.ini 或运行时配置强制生效:
- 在 Dockerfile 中写入: RUN echo "open_basedir = /var/www/html:/tmp" >> /usr/local/etc/php/php.ini
- 或用环境变量方式(适用于 php:fpm-alpine 等镜像): php -d open_basedir="/var/www/html:/tmp" -S 0.0.0.0:8000
- 注意:open_basedir 不支持通配符,必须写明绝对路径;多个路径用冒号分隔(Linux)或分号(Windows);空值或未设置等于完全开放
禁用远程包含与危险伪协议
PHP 8.2 默认已关闭 allow_url_include,但仍需确认并补全其他风险面:
修复 Core bailout 状态损坏安全问题,以及 BZ2、DOM、PDO、Opcache/JIT 内存与执行错误,改进 Unicode 字素处理、URL 解析、TLS 流状态、信号分发及会话错误处理。
- 确保 php.ini 中这两项为 Off:
allow_url_include = Off
allow_url_fopen = Off(后者可防部分日志投毒、data://利用) - 禁用高危流封装器(尤其在非调试环境): disable_functions = phpinfo,system,exec,passthru,shell_exec,proc_open,popen,parse_ini_file,show_source,highlight_file,include,require,include_once,require_once (注意:禁用 include/require 会破坏正常逻辑,仅作参考;更推荐白名单+open_basedir组合)
容器内挂载与工作目录严格收敛
很多 LFI 漏洞能成功,是因为容器把整个宿主机目录挂进来了,或者工作目录太宽:
立即学习“PHP免费学习笔记(深入)”;
- Docker Compose 中只挂载必要路径,避免 - ./:/var/www/html 这类无差别映射;改用精确挂载:
- ./src:/var/www/html/src
- ./config:/var/www/html/config - 在 PHP 启动前显式设置工作目录,防止 getcwd() 返回不可控路径: WORKDIR /var/www/html(Dockerfile 中) + RUN chown -R www-data:www-data /var/www/html
- 检查容器内实际权限:进入容器执行 ls -la /var/www/html 和 pwd,确认无意外符号链接或越权目录
代码层做白名单映射(最可靠的一环)
所有用户可控的 include 参数,必须经过白名单校验,不依赖后缀拼接或字符串过滤:
- 错误示范:$page = $_GET['page']; include($page . '.php');
- 正确做法:
$pages = ['home', 'about', 'contact'];
$page = $_GET['page'] ?? 'home';
if (in_array($page, $pages, true)) {
include __DIR__ . '/pages/' . $page . '.php';
} else {
http_response_code(404);
exit('Page not found');
} - 进阶建议:把页面映射关系抽到配置数组或 JSON 文件中,避免硬编码;使用 realpath() + strpos() 校验真实路径是否落在白名单根目录下


















