本文目录导读:

针对PHP项目中的文件包含漏洞(File Inclusion Vulnerability),防范措施需要从代码编写、配置、架构设计以及持续检测多个层面入手,以下是一些核心的、经过验证的防范策略:
最根本的措施:避免动态包含
这是最彻底的方法,如果业务逻辑允许,尽量不要使用任何用户输入(如 $_GET、$_POST、$_COOKIE 等)来构建包含路径。
错误示例:
<?php // 危险!直接使用用户输入 include($_GET['page'] . '.php'); ?>
正确思路: 如果必须动态加载不同页面,使用白名单映射或枚举,而不是让用户直接指定文件名。
<?php
$whitelist = [
'home' => 'home.php',
'about' => 'about.php',
'contact' => 'contact.php',
];
$page = $_GET['page'] ?? 'home'; // 默认值
if (isset($whitelist[$page])) {
include($whitelist[$page]); // 只包含白名单中映射的文件
} else {
// 显示错误或重定向到首页
include($whitelist['home']);
}
?>
严格限制文件操作范围
如果无法避免动态包含(例如在某些CMS或框架中),必须将文件访问限制在特定目录内。
禁用可执行远程文件包含(RFI)
PHP的远程文件包含(allow_url_include)是最高危的漏洞之一。在 php.ini 中必须关闭:
allow_url_include = Off allow_url_fopen = Off ; 建议同时关闭,减少攻击面
使用 open_basedir 限制访问范围
在 php.ini 或虚拟主机配置中设置 open_basedir,这会将PHP文件操作限制在指定目录及其子目录内,即使代码试图包含 /etc/passwd 也会被拒绝。
open_basedir = /var/www/html/:/tmp/ ; 只允许访问项目目录和临时目录
对用户输入进行严格的过滤和清理
当必须使用用户输入来构建路径时,必须进行深度清洗。
路径规范化(关键步骤)
使用 realpath() 函数获取文件的真实绝对路径,并检查该路径是否在预期的白名单目录内,这可以有效处理 、 或符号链接等路径遍历攻击。
<?php
$baseDir = '/var/www/html/includes/'; // 绝对路径
$fileName = basename($_GET['file']); // 只取文件名,过滤目录部分
$fullPath = realpath($baseDir . $fileName); // 获取真实路径
// 检查:文件是否存在?且路径是否以 $baseDir 开头?
if ($fullPath !== false && strpos($fullPath, $baseDir) === 0) {
include($fullPath);
} else {
die('无效文件');
}
?>
不信任用户输入,优先使用 basename()
basename() 函数会移除路径中的目录部分,只保留文件名,从而直接防止目录遍历。
系统与配置层面的加固
关闭危险函数(如果非必要)
在PHP的实践中,可以通过 disable_functions 指令在 php.ini 中禁用一些高危但非必需的文件函数。
disable_functions = exec, system, passthru, shell_exec, popen, proc_open,
dl, show_source, highlight_file,
include, require ; 注意:这会禁用所有include/require,仅用于极端高安全环境
注意: include 和 require 是核心函数,一般不要禁用,通常只禁用 exec、system、eval、assert 等。
禁用 register_globals 和 magic_quotes
建议在 php.ini 中确认这些旧功能已关闭(PHP 5.4+ 默认已废弃并移除,但老项目需注意):
register_globals = Off magic_quotes_gpc = Off
新开发项目的架构建议(防患于未然)
- 使用自动加载与现代框架:
- Composer PSR-4自动加载:现代框架(Laravel、Symfony)通过命名空间和自动加载器管理文件,几乎不会依赖用户输入来包含文件。
- 单一入口模式:所有请求通过
index.php,由路由器处理,而非直接包含用户指定的文件。
- 模板引擎:
使用 Twig、Blade 等模板引擎,它们自带沙盒机制,会阻止在模板中直接执行文件包含操作,降低了被攻击的风险。
- 最小权限原则:
- Web目录下,不存储敏感配置文件(如数据库密码)或不应该被直接访问的功能性文件,将敏感文件放在Web根目录之外,并通过
include引用。
- Web目录下,不存储敏感配置文件(如数据库密码)或不应该被直接访问的功能性文件,将敏感文件放在Web根目录之外,并通过
持续检测与应急
- 日志监控:定期审查访问日志和错误日志,寻找异常的
include()参数(如 、%00截断、http://等)。 - 代码审计:使用自动化工具(如 RIPS、SonarQube、PHPStan)扫描代码中不安全的文件操作。
- WAF(Web应用防火墙):部署WAF(如ModSecurity)来拦截包含 、
/etc/passwd、php://input等典型攻击字符串的请求。
总结核心原则(优先级从高到低)
- 不用用户输入来包含文件。
- 如果必须用,使用白名单映射。
- 如果无法避免动态,采用
realpath()+basename()+ 目录前缀检查的多步防御。 - 配置层面:关闭
allow_url_include,设置open_basedir。 - 架构层面:使用现代框架和Composer自动加载代替手写文件包含。
通过以上措施的组合使用,可以显著降低PHP项目文件包含漏洞的风险。