从CTF中学习PHP反序列化的各种利用方式
字数 1673 2025-08-20 18:17:53
PHP反序列化漏洞全面解析与利用技术
前言
PHP反序列化漏洞是CTF比赛中常见的高频考点,也是实际Web应用中需要重点防范的安全问题。本文将从多个维度深入剖析PHP反序列化的各种利用方式,包括魔术方法绕过、session反序列化、phar反序列化、字符串逃逸、对象逃逸、POP链构造等高级技术。
__wakeup()绕过漏洞
漏洞概述
- CVE编号: CVE-2016-7124
- 影响版本: PHP5.6.25之前和7.0.10之前的7.x版本
- 漏洞原理: 当对象的属性数量大于实际个数时,可以绕过
__wakeup()魔术方法的执行
示例分析
class convent{
var $warn = "No hacker.";
function __destruct(){
eval($this->warn); // 存在代码执行风险
}
function __wakeup(){
foreach(get_object_vars($this) as $k => $v) {
$this->$k = null; // 正常情况下会清空所有属性
}
}
}
利用方式:构造序列化字符串时,修改对象属性数量使其大于实际数量,例如:
O:7:"convent":2:{s:4:"warn";s:10:"phpinfo();";}
(实际只有1个属性warn,但声明为2个属性)
PHP Session反序列化漏洞
Session存储机制
PHP session有三种序列化处理器:
-
php(默认): 格式为
键名|序列化值- 示例:
name|s:6:"1FonlY";
- 示例:
-
php_serialize: 完整序列化格式
- 示例:
a:1:{s:4:"name";s:6:"1FonlY";}
- 示例:
-
php_binary: 键名长度(ASCII) + 键名 + 序列化值
- 示例:
EOTnames:6:"1FonlY";(EOT是ASCII码4)
- 示例:
漏洞利用条件
当序列化与反序列化使用的处理器不一致时,可能造成注入漏洞。
攻击场景:
- 使用php_serialize序列化:
a:1:{s:4:"name";s:31:"|O:7:"_1FonlY":1:{s:3:"cmd";N;}";} - 使用php处理器反序列化时,会将
|后的内容当作单独的对象解析
PHAR反序列化漏洞
PHAR文件结构
PHAR(PHP Archive)文件包含序列化的元数据(metadata),当通过phar://协议访问时自动反序列化。
生成PHAR示例:
class TestObject {}
$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetadata(new TestObject()); // 序列化存储
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
利用条件
- 能够上传PHAR文件(可伪装为GIF/JPG等)
- 存在文件操作函数且参数可控
- 有可用的魔术方法作为"跳板"
可利用的函数
- file_exists()
- is_dir()
- file_get_contents()
- 等文件系统函数
绕过技巧
- 伪装文件类型:
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");
- 协议嵌套:
compress.zlib://phar://phar.phar/test.txt
字符串逃逸技术
原理
通过控制序列化字符串长度,使后续内容被解析为新属性。
典型案例:[0CTF 2016 piapiapia]
- 构造payload闭合前部分序列化:
";}s:5:"photo";s:10:"config.php";} - 利用过滤规则增加字符数(如where→hacker多1字符)
- 计算需要增加的字符数,插入相应数量的触发词
对象逃逸技术
通过覆盖或构造特定对象属性,使反序列化后执行非预期操作。
关键点:
- 利用
__toString()等魔术方法 - 控制对象属性间的引用关系
- 通过数组操作等方式绕过过滤
POP链构造
POP(Property-Oriented Programming)链通过串联多个类的魔术方法和普通方法实现攻击。
构造步骤:
- 寻找起点(如
__destruct()) - 分析类方法调用关系
- 寻找敏感函数调用
- 构造属性控制执行流程
示例:[MRCTF 2020 Easy pop]
Show::__toString()→Test::__get()→Modifier::__invoke()- 最终触发文件包含读取flag
其他利用方式
SoapClient + 反序列化 → SSRF
$url = "http://127.0.0.1/flag.php";
$b = new SoapClient(null, array('uri'=>$url, 'location'=>$url));
Exception类 → XSS
$s = new Exception("<script>alert(1)</script>");
unserialize(serialize($s)); // 触发XSS
防御措施
- 及时更新PHP版本
- 避免反序列化用户输入
- 使用一致session处理器
- 对魔术方法进行安全编码
- 禁用不必要的类序列化
总结
PHP反序列化漏洞形式多样,从简单的魔术方法绕过到复杂的POP链构造,理解这些技术有助于开发更安全的代码和更有效的防御措施。在实际应用中,应特别注意对用户可控数据的处理,避免危险函数的直接调用。