一文了解反序列化漏洞
字数 1195 2025-08-12 11:33:45

PHP反序列化漏洞详解

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

1. 序列化概念

序列化是将对象或数组转换为字节序列的过程,类似于游戏中的存档操作。在PHP中,使用serialize()函数实现序列化。

序列化函数语法

string serialize ( mixed $value )

示例

$sites = array('I', 'Like', 'PHP');
echo serialize($sites); 
// 输出: a:3:{i:0;s:1:"I";i:1;s:4:"Like";i:2;s:3:"PHP";}

class man {
    public $name = "xiaocui";
    public $sex = "man";
    private $age = 26;
}
$M = new man();
echo serialize($M);
// 输出: O:3:"man":3:{s:4:"name";s:7:"xiaocui";s:3:"sex";s:3:"man";s:8:"man age";i:26;}

2. 反序列化概念

反序列化是将字节序列恢复为对象的过程,类似于游戏中的读档操作。在PHP中,使用unserialize()函数实现反序列化。

反序列化函数语法

mixed unserialize ( string $str )

示例

$ser = 'a:3:{i:0;s:1:"I";i:1;s:4:"Like";i:2;s:3:"PHP";}';
var_dump(unserialize($ser));
// 输出原始数组

3. 序列化与反序列化的作用

  1. 持久化存储:将对象字节序列永久保存在磁盘中,节省内存空间
  2. 提高传输效率:在网络传输中直接传输字节序列而非对象

二、PHP魔术方法

PHP中以双下划线__开头的方法为魔术方法,在特定情况下自动调用。

1. 常见魔术方法

__construct()

  • 在创建新对象时调用,用于初始化
public function __construct() {
    echo "类被实例化时调用我!";
}

__destruct()

  • 当对象的所有引用被删除或对象被销毁时调用
public function __destruct() {
    echo "对象被销毁时调用我!";
}

__wakeup()

  • 在使用unserialize()时首先调用
public function __wakeup() {
    echo "反序列化时首先调用我!";
}

__toString()

  • 当对象被当作字符串处理时调用
public function __toString() {
    return "对象被当作字符串处理";
}

__sleep()

  • 在使用serialize()时首先调用
public function __sleep() {
    return array("name", "age"); // 必须返回属性数组
}

__invoke()

  • 当尝试以函数方式调用对象时调用
public function __invoke() {
    echo "对象被当作函数调用";
}

__call()

  • 当调用不存在或不可访问的方法时调用
public function __call($method, $args) {
    echo "调用了不存在的方法: $method";
}

__set() / __get()

  • __set(): 给不可访问属性赋值时调用
  • __get(): 读取不可访问属性时调用
public function __set($name, $value) {
    echo "设置不可访问属性: $name";
}

public function __get($name) {
    echo "读取不可访问属性: $name";
}

__isset() / __unset()

  • __isset(): 对不可访问属性调用isset()empty()时调用
  • __unset(): 对不可访问属性调用unset()时调用

三、反序列化漏洞

1. 漏洞利用条件

  1. unserialize()函数的参数可控
  2. 存在可利用的类,且类中有魔术方法

2. 漏洞示例

示例1: XSS漏洞

class demo {
    public $arg1 = "0";
    public function __destruct() {
        echo $this->arg1; // 输出用户可控内容
    }
}

$a = $_GET['arg']; // 用户可控输入
$unser = unserialize($a);

攻击者可构造恶意序列化字符串实现XSS攻击。

示例2: RCE漏洞

class demo {
    public $arg1 = "0";
    public function __destruct() {
        eval($this->arg1); // 执行用户可控代码
    }
}

$a = $_GET['arg'];
$unser = unserialize($a);

攻击者可构造恶意序列化字符串实现远程代码执行。

3. __wakeup()绕过

在PHP版本<=5.6.25或<=7.0.11时,当序列化字符串中对象属性数量大于实际属性数量时,可绕过__wakeup()方法。

示例

class demo {
    public $arg1 = "0";
    public function __wakeup() {
        $this->arg1 = ''; // 正常情况下会清空arg1
    }
    public function __destruct() {
        eval($this->arg1); // 危险操作
    }
}

// 正常序列化
$normal = 'O:4:"demo":1:{s:4:"arg1";s:10:"phpinfo();";}';
// 绕过序列化
$bypass = 'O:4:"demo":2:{s:4:"arg1";s:10:"phpinfo();";s:4:"arg2";s:1:"1";}';

四、防御措施

  1. 不要反序列化不可信数据
  2. 使用json_encode()/json_decode()替代序列化
  3. 对反序列化操作进行严格的白名单控制
  4. 及时升级PHP版本,修复已知漏洞
  5. 在魔术方法中避免危险操作
  6. 对用户输入进行严格过滤和验证

五、总结

PHP反序列化漏洞是一种严重的安全威胁,攻击者可以利用它实现XSS、RCE等多种攻击。理解序列化/反序列化机制、魔术方法的调用时机以及漏洞利用条件,对于防范此类攻击至关重要。开发者应当遵循安全编码规范,避免直接反序列化用户可控输入,并及时更新PHP版本以修复已知漏洞。

PHP反序列化漏洞详解 一、序列化与反序列化基础 1. 序列化概念 序列化是将对象或数组转换为字节序列的过程,类似于游戏中的存档操作。在PHP中,使用 serialize() 函数实现序列化。 序列化函数语法 : 示例 : 2. 反序列化概念 反序列化是将字节序列恢复为对象的过程,类似于游戏中的读档操作。在PHP中,使用 unserialize() 函数实现反序列化。 反序列化函数语法 : 示例 : 3. 序列化与反序列化的作用 持久化存储:将对象字节序列永久保存在磁盘中,节省内存空间 提高传输效率:在网络传输中直接传输字节序列而非对象 二、PHP魔术方法 PHP中以双下划线 __ 开头的方法为魔术方法,在特定情况下自动调用。 1. 常见魔术方法 __construct() 在创建新对象时调用,用于初始化 __destruct() 当对象的所有引用被删除或对象被销毁时调用 __wakeup() 在使用 unserialize() 时首先调用 __toString() 当对象被当作字符串处理时调用 __sleep() 在使用 serialize() 时首先调用 __invoke() 当尝试以函数方式调用对象时调用 __call() 当调用不存在或不可访问的方法时调用 __set() / __get() __set() : 给不可访问属性赋值时调用 __get() : 读取不可访问属性时调用 __isset() / __unset() __isset() : 对不可访问属性调用 isset() 或 empty() 时调用 __unset() : 对不可访问属性调用 unset() 时调用 三、反序列化漏洞 1. 漏洞利用条件 unserialize() 函数的参数可控 存在可利用的类,且类中有魔术方法 2. 漏洞示例 示例1: XSS漏洞 攻击者可构造恶意序列化字符串实现XSS攻击。 示例2: RCE漏洞 攻击者可构造恶意序列化字符串实现远程代码执行。 3. __wakeup() 绕过 在PHP版本<=5.6.25或<=7.0.11时,当序列化字符串中对象属性数量大于实际属性数量时,可绕过 __wakeup() 方法。 示例 : 四、防御措施 不要反序列化不可信数据 使用 json_encode() / json_decode() 替代序列化 对反序列化操作进行严格的白名单控制 及时升级PHP版本,修复已知漏洞 在魔术方法中避免危险操作 对用户输入进行严格过滤和验证 五、总结 PHP反序列化漏洞是一种严重的安全威胁,攻击者可以利用它实现XSS、RCE等多种攻击。理解序列化/反序列化机制、魔术方法的调用时机以及漏洞利用条件,对于防范此类攻击至关重要。开发者应当遵循安全编码规范,避免直接反序列化用户可控输入,并及时更新PHP版本以修复已知漏洞。