php本地文件包含(lfi)漏洞防御核心是禁止用户输入未经约束进入include/require函数,需代码逻辑、路径控制与环境配置协同:首选白名单校验,其次realpath路径约束与open_basedir限制,再关闭allow_url_include等危险配置,最后杜绝直接拼接用户输入的开发习惯。

PHP本地文件包含(LFI)漏洞的防御核心是:**不让用户输入直接、未经约束地进入 include/require 函数**。这不是靠一层过滤就能解决的问题,而需要代码逻辑、路径控制和环境配置三者协同。
用白名单代替动态拼接
这是最有效、最推荐的第一道防线。不要让用户决定“包含什么”,而是由开发者预先定义合法选项。
- 把所有允许被包含的文件列成一个关联数组,键为安全标识(如 'home'、'about'),值为对应的真实绝对路径
- 接收用户参数后,只把它当作数组键去查找;如果键不存在,直接报错或跳转默认页,不执行任何包含操作
- 示例:避免
include($_GET['page'] . '.php');;改用$pages = ['home' => '/var/www/inc/home.php', 'about' => '/var/www/inc/about.php']; $file = $_GET['page'] ?? ''; if (isset($pages[$file])) { include $pages[$file]; }
强制路径规范化与目录限制
即使必须处理用户输入,也要确保最终路径落在可控范围内,且无法跳出指定目录。
- 使用
basename()提取参数中的文件名部分,剥离所有路径符号(如../、/etc/passwd) - 拼接前缀目录后,调用
realpath()获取真实路径,再用strpos()或str_starts_with()检查是否仍在预期根目录下 - 在 php.ini 中设置
open_basedir,例如open_basedir = "/var/www/html:/tmp",从系统层禁止访问范围外的文件
关闭危险协议与远程包含能力
很多LFI升级为RCE的关键跳板是伪协议(如 php://filter、data://),这些在绝大多数业务场景中完全不需要。
- 在 php.ini 中明确关闭:
allow_url_include = Off(禁用远程包含) - 考虑在
disable_functions中加入getcwd,scandir,ini_get等辅助函数,增加攻击者探测环境的难度 - 如果项目不用日志注入、Session包含等高级利用,可将日志目录、session 存储路径设为不可读,或启用
session.save_handler = files并限制权限
从开发习惯上杜绝风险源头
很多LFI漏洞其实在写第一行代码时就埋下了——关键不是“怎么修”,而是“为什么会出现”。
- 禁止在 include/require 中直接拼接任何用户输入(GET、POST、Cookie、Header、上传文件名等)
- 删除所有形如
include($user_input)、require($dir . '/' . $name)的写法;模板加载、语言包、配置加载等统一走静态引入或自动加载机制(如 PSR-4) - 上线前做代码审计,搜索关键词
include(、require(、include_once(、require_once(,逐个确认参数来源是否可信
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











