PHP反序列化漏洞分析与CTF实战

📅 2026/7/19 6:27:15
PHP反序列化漏洞分析与CTF实战
1. 题目背景与初步分析piapiapia这道题目来自2016年0CTF比赛是一道经典的Web安全挑战题。作为CTF老手我初次看到这个题目名称时首先想到的是它可能暗示着某种拍手或鼓掌的动作这在Web安全中往往与文件上传、反序列化等需要交互的操作有关。从历史解题记录来看这道题目主要考察了以下几个安全知识点反序列化漏洞PHP对象注入代码审计技巧黑名单绕过技术文件包含漏洞的利用2. 环境搭建与题目复现2.1 获取题目源码由于是历史比赛题目我们可以在各大CTF题库平台找到这道题的镜像。推荐使用以下方式搭建本地测试环境下载题目Docker镜像或源码包配置PHP 5.6环境注意版本兼容性准备MySQL数据库典型的目录结构如下/piapiapia ├── assets ├── config.php ├── index.php ├── profile.php ├── register.php ├── update.php └── upload/2.2 关键文件分析在config.php中我们发现了数据库配置和重要的过滤函数function filter($string) { $escape array(\, \\\\); $escape / . implode(|, $escape) . /; $string preg_replace($escape, _, $string); $safe array(select, insert, update, delete, where); $safe / . implode(|, $safe) . /i; return preg_replace($safe, hacker, $string); }这个过滤函数有几个关键特点将单引号和反斜线替换为下划线将常见SQL关键词替换为hacker但未过滤其他危险字符如union、from等3. 漏洞挖掘过程3.1 反序列化入口点在update.php中发现了可疑的序列化操作$profile[phone] $_POST[phone]; $profile[email] $_POST[email]; $profile[nickname] $_POST[nickname]; $serialized_profile serialize($profile);这段代码直接将用户输入的nickname等字段序列化后存入数据库。而在profile.php中又进行了反序列化$profile unserialize($profile);这就构成了典型的PHP对象注入漏洞。我们需要构造特殊的序列化字符串来触发恶意行为。3.2 黑名单绕过技巧虽然题目有过滤函数但存在几个关键绕过点大小写绕过过滤只处理小写的SQL关键词双写绕过selselectect在被过滤后会变成select注释绕过使用/**/分割关键词通过分析我们发现最有效的payload构造方式是O:8:stdClass:1:{s:3:foo;s:50:union/*...*/select/*...*/1,2,3,4,5,6,7,8,9,10,11,12;}3.3 文件包含利用在代码审计过程中发现了一个关键的文件包含点if (isset($_GET[photo])) { $file /var/www/html/upload/.$_GET[photo]; if (file_exists($file)) { header(Content-Type: image/jpeg); readfile($file); } }结合反序列化漏洞我们可以实现通过SQL注入获取管理员密码上传包含恶意代码的图片文件利用文件包含执行任意代码4. 完整漏洞利用链4.1 步骤一构造恶意序列化数据使用以下PHP代码生成payload?php class Evil { public $cmd system(cat /flag);; } $evil new Evil(); echo serialize($evil); ?生成的payload类似O:4:Evil:1:{s:4:cmd;s:19:system(cat /flag);;}4.2 步骤二绕过过滤注入数据库通过注册功能在nickname字段注入我们的payload。需要注意使用URL编码绕过特殊字符检测分多次注入避免触发长度限制利用update.php的更新机制覆盖原有数据4.3 步骤三触发反序列化访问profile.php页面时服务端会从数据库读取并反序列化我们的恶意对象从而执行系统命令。5. 防御方案与经验总结5.1 安全开发建议永远不要反序列化不可信数据使用安全的替代方案如JSON实施严格的白名单过滤而非黑名单对文件包含操作进行路径校验5.2 CTF解题心得在解决这类题目时我总结出以下经验先全面审计所有PHP文件特别关注serialize/unserialize调用注意过滤函数的缺陷寻找绕过方法尝试将多个漏洞串联形成完整利用链本地测试时使用error_reporting(E_ALL)显示所有错误这道题最巧妙之处在于将反序列化与SQL注入、文件包含等多个漏洞结合考察了选手的综合能力。在实际渗透测试中这种漏洞链的思维同样重要。