文件包含漏洞是因include/require等函数直接使用用户可控参数导致的逻辑缺陷,路径穿越(如../)只是其典型利用手法之一;PHP 7.4中虽禁用%00截断,但伪协议、日志包含等绕过方式仍有效,防御需杜绝拼接路径、校验realpath并限定安全根目录。

PHP 7.4 中的文件包含漏洞和路径穿越不是并列的两类漏洞,而是因果关系:路径穿越是文件包含漏洞中最常用、最典型的利用手法之一,属于攻击者为达成文件包含而采取的具体技术手段。
换句话说:
-
文件包含漏洞是“门”——指
include()、require()等函数直接使用了用户可控参数(如$_GET['page']),导致程序可加载任意路径的文件; -
路径穿越(
../)是“开门的钥匙”之一——用来绕过开发者自以为的安全限制(比如固定目录前缀、后缀拼接),从而访问本不该被访问的文件(如/etc/passwd、/var/www/html/config.php)。
文件包含漏洞的核心特征
- 触发点明确:代码中存在类似
include($_GET['file']);或require($user_input . '.php');的写法; - 危害本质:PHP 把指定路径的内容当作 PHP 代码执行(或原样输出),因此不仅能读文件,还能执行任意 PHP 逻辑;
- 不依赖路径穿越也能触发:例如用
php://filter、data://、phar://等伪协议,根本不需要../。
✅ 示例(无需路径穿越):
?page=php://filter/convert.base64-encode/resource=index.php
直接 base64 编码读取源码,连目录都未离开当前路径。
路径穿越的本质与局限
- 是一种路径操控技术,核心是用
../向上跳转目录,突破“白目录”限制; - 常见配合场景:
- 开发者写了
include('pages/' . $_GET['p'] . '.php'),以为加了前缀和后缀就安全; - 攻击者传
p=../../../../etc/passwd%00,在旧环境可能截断.php,最终加载/etc/passwd;
- 开发者写了
- 在 PHP 7.4 中,
%00截断默认已被禁用,所以纯靠../+ 后缀拼接的利用成功率下降,但只要目录结构可预测、目标文件可访问,依然有效(比如日志文件、session 文件、上传临时文件等)。
⚠️ 注意:路径穿越本身不是漏洞,它只是操作系统/文件系统对路径解析的正常行为。危险在于——程序把用户输入的路径直接交给了 include。
关键区别总结
| 维度 | 文件包含漏洞 | 路径穿越 |
|---|---|---|
| 性质 | 代码逻辑缺陷(函数参数可控 + 无校验) | 路径解析机制的正常特性 |
| 是否独立存在 | 是,有漏洞就存在风险 | 否,必须依附于路径拼接类操作(如 include/fopen/file_get_contents) |
| PHP 7.4 下是否仍有效 | 是,伪协议、日志包含、session 包含等手法完全可用 | 是,../ 依然能向上遍历,只是 %00 截断多数失效 |
| 防御重点 | 杜绝用户输入参与 include 参数;用白名单映射绝对路径 |
配合 realpath() + 安全根目录前缀校验,不能只拦 .. 字符 |
实际开发中容易混淆的误区
- ❌ “我用了
basename()就安全了” → 错。basename('../../../etc/passwd')返回passwd,但若拼接在include('files/' . basename($x))中,仍可能被php://filter或其他协议绕过; - ❌ “我加了
.php后缀就防住了路径穿越” → 错。?p=../../config%00在部分配置下仍可截断,且伪协议根本不需要后缀; - ✅ 正确做法:不拼路径、不信任输入、查白名单绝对路径、
realpath()校验后强制限定在$safeRoot下。
不复杂但容易忽略。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











