首页/安全/漏洞与攻击面速查/文件包含(LFI/RFI)原理与防护
Web 漏洞原理与防护55 条

文件包含(LFI/RFI)原理与防护

文件包含问题出现在动态加载场景:用户输入影响 include 路径时可读取本地文件(LFI),若允许远程加载则可能引入外部内容(RFI);防护是用固定映射表替代自由路径拼接。

漏洞与攻击面速查安全更新于 2026-10-13

文件包含漏洞是什么

文件包含指程序在运行期根据输入拼接路径去加载文件。当这个输入由用户可控时,就可能出现两类问题:本地文件包含(LFI)让攻击者读取服务器上的任意可读文件,远程文件包含(RFI)则允许加载外部地址的内容,直接演变为代码执行。RFI 依赖 allow_url_include 这类开关,现代 PHP 默认关闭,但 LFI 依然常见,配合日志文件、会话文件与 phar 包装器可以进一步升级危害。

基本信息

常见载体PHP 的 include/require、模板引擎动态路径、插件与模块加载
类型LFI 本地文件包含、RFI 远程文件包含
危害读取配置与凭据文件、加载可执行内容、配合包装器升级
根治思路用固定映射表替代自由路径拼接,关闭远程包含能力

典型使用场景

  • 重构遗留代码:把 page=xxx 形式的动态包含改为白名单映射
  • 代码评审时搜索存在路径拼接的包含语句,检查输入来源
  • 模板引擎配置审查:确认模板路径不含用户可控成分
  • 插件与模块加载机制评估:第三方插件目录是否可被写入
  • 上线前确认远程包含与危险包装器均处于关闭状态

安全改造示例(PHP)

安全改造示例(PHP)
$pages = ['home' => 'home.php', 'about' => 'about.php'];
$key = $_GET['page'] ?? 'home';

// 白名单校验:不在映射表中的键一律拒绝
if (!isset($pages[$key])) {
    http_response_code(404);
    exit;
}

// 只拼接映射表中的固定值,用户输入不进入路径
include __DIR__ . '/pages/' . $pages[$key];

防护手段对比

手段有效性说明
黑名单过滤 ../ 与 http://低编码变形与包装器可绕过
映射表白名单高输入只用于查表,不进入路径
关闭 allow_url_include中只挡住远程包含这一类
目录权限收敛辅助降低被包含文件的危害上限
现代 PHP 默认关闭 allow_url_include,远程包含已较少见;但仍要关注 phar://、data:// 等包装器与日志包含链路,它们能把单纯的读取升级为代码执行。
用黑名单过滤 ../ 与协议前缀的写法容易被编码与包装器绕过,改造时优先换成映射表,而不是继续加固过滤规则。

易错点

  • 用黑名单过滤 ../ 与 http:// 的写法容易被编码与包装器绕过,应改为映射表方式
  • 只限制了相对路径未限制绝对路径:输入直接给出 /etc/passwd 形式的路径仍可读取
  • 包含路径可控且应用目录可写:攻击者先上传文件再包含执行,读取问题升级为代码执行
  • 自研模板引擎未做路径校验,模板名直接来自请求参数

数据来源与参考

  • PHP 手册(include 与 allow_url_include 配置)
  • OWASP WSTG File Inclusion 测试章节
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌