从CTF中学习PHP反序列化的各种利用方式
字数 1673 2025-08-20 18:17:53

PHP反序列化漏洞全面解析与利用技术

前言

PHP反序列化漏洞是CTF比赛中常见的高频考点,也是实际Web应用中需要重点防范的安全问题。本文将从多个维度深入剖析PHP反序列化的各种利用方式,包括魔术方法绕过、session反序列化、phar反序列化、字符串逃逸、对象逃逸、POP链构造等高级技术。

__wakeup()绕过漏洞

漏洞概述

  • CVE编号: CVE-2016-7124
  • 影响版本: PHP5.6.25之前和7.0.10之前的7.x版本
  • 漏洞原理: 当对象的属性数量大于实际个数时,可以绕过__wakeup()魔术方法的执行

示例分析

class convent{
    var $warn = "No hacker.";
    function __destruct(){
        eval($this->warn);  // 存在代码执行风险
    }
    function __wakeup(){
        foreach(get_object_vars($this) as $k => $v) {
            $this->$k = null;  // 正常情况下会清空所有属性
        }
    }
}

利用方式:构造序列化字符串时,修改对象属性数量使其大于实际数量,例如:

O:7:"convent":2:{s:4:"warn";s:10:"phpinfo();";}

(实际只有1个属性warn,但声明为2个属性)

PHP Session反序列化漏洞

Session存储机制

PHP session有三种序列化处理器:

  1. php(默认): 格式为键名|序列化值

    • 示例: name|s:6:"1FonlY";
  2. php_serialize: 完整序列化格式

    • 示例: a:1:{s:4:"name";s:6:"1FonlY";}
  3. php_binary: 键名长度(ASCII) + 键名 + 序列化值

    • 示例: EOTnames:6:"1FonlY"; (EOT是ASCII码4)

漏洞利用条件

当序列化与反序列化使用的处理器不一致时,可能造成注入漏洞。

攻击场景

  1. 使用php_serialize序列化:a:1:{s:4:"name";s:31:"|O:7:"_1FonlY":1:{s:3:"cmd";N;}";}
  2. 使用php处理器反序列化时,会将|后的内容当作单独的对象解析

PHAR反序列化漏洞

PHAR文件结构

PHAR(PHP Archive)文件包含序列化的元数据(metadata),当通过phar://协议访问时自动反序列化。

生成PHAR示例

class TestObject {}
$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetadata(new TestObject()); // 序列化存储
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();

利用条件

  1. 能够上传PHAR文件(可伪装为GIF/JPG等)
  2. 存在文件操作函数且参数可控
  3. 有可用的魔术方法作为"跳板"

可利用的函数

  • file_exists()
  • is_dir()
  • file_get_contents()
  • 等文件系统函数

绕过技巧

  1. 伪装文件类型
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");
  1. 协议嵌套
compress.zlib://phar://phar.phar/test.txt

字符串逃逸技术

原理

通过控制序列化字符串长度,使后续内容被解析为新属性。

典型案例:[0CTF 2016 piapiapia]

  1. 构造payload闭合前部分序列化:
    ";}s:5:"photo";s:10:"config.php";}
  2. 利用过滤规则增加字符数(如where→hacker多1字符)
  3. 计算需要增加的字符数,插入相应数量的触发词

对象逃逸技术

通过覆盖或构造特定对象属性,使反序列化后执行非预期操作。

关键点

  • 利用__toString()等魔术方法
  • 控制对象属性间的引用关系
  • 通过数组操作等方式绕过过滤

POP链构造

POP(Property-Oriented Programming)链通过串联多个类的魔术方法和普通方法实现攻击。

构造步骤

  1. 寻找起点(如__destruct())
  2. 分析类方法调用关系
  3. 寻找敏感函数调用
  4. 构造属性控制执行流程

示例:[MRCTF 2020 Easy pop]

  1. Show::__toString()Test::__get()Modifier::__invoke()
  2. 最终触发文件包含读取flag

其他利用方式

SoapClient + 反序列化 → SSRF

$url = "http://127.0.0.1/flag.php";
$b = new SoapClient(null, array('uri'=>$url, 'location'=>$url));

Exception类 → XSS

$s = new Exception("<script>alert(1)</script>");
unserialize(serialize($s)); // 触发XSS

防御措施

  1. 及时更新PHP版本
  2. 避免反序列化用户输入
  3. 使用一致session处理器
  4. 对魔术方法进行安全编码
  5. 禁用不必要的类序列化

总结

PHP反序列化漏洞形式多样,从简单的魔术方法绕过到复杂的POP链构造,理解这些技术有助于开发更安全的代码和更有效的防御措施。在实际应用中,应特别注意对用户可控数据的处理,避免危险函数的直接调用。

PHP反序列化漏洞全面解析与利用技术 前言 PHP反序列化漏洞是CTF比赛中常见的高频考点,也是实际Web应用中需要重点防范的安全问题。本文将从多个维度深入剖析PHP反序列化的各种利用方式,包括魔术方法绕过、session反序列化、phar反序列化、字符串逃逸、对象逃逸、POP链构造等高级技术。 __ wakeup()绕过漏洞 漏洞概述 CVE编号: CVE-2016-7124 影响版本: PHP5.6.25之前和7.0.10之前的7.x版本 漏洞原理: 当对象的属性数量大于实际个数时,可以绕过 __wakeup() 魔术方法的执行 示例分析 利用方式 :构造序列化字符串时,修改对象属性数量使其大于实际数量,例如: (实际只有1个属性warn,但声明为2个属性) PHP Session反序列化漏洞 Session存储机制 PHP session有三种序列化处理器: php (默认): 格式为 键名|序列化值 示例: name|s:6:"1FonlY"; php_ serialize : 完整序列化格式 示例: a:1:{s:4:"name";s:6:"1FonlY";} php_ binary : 键名长度(ASCII) + 键名 + 序列化值 示例: EOTnames:6:"1FonlY"; (EOT是ASCII码4) 漏洞利用条件 当序列化与反序列化使用的处理器不一致时,可能造成注入漏洞。 攻击场景 : 使用php_ serialize序列化: a:1:{s:4:"name";s:31:"|O:7:"_1FonlY":1:{s:3:"cmd";N;}";} 使用php处理器反序列化时,会将 | 后的内容当作单独的对象解析 PHAR反序列化漏洞 PHAR文件结构 PHAR(PHP Archive)文件包含序列化的元数据(metadata),当通过phar://协议访问时自动反序列化。 生成PHAR示例 : 利用条件 能够上传PHAR文件(可伪装为GIF/JPG等) 存在文件操作函数且参数可控 有可用的魔术方法作为"跳板" 可利用的函数 file_ exists() is_ dir() file_ get_ contents() 等文件系统函数 绕过技巧 伪装文件类型 : 协议嵌套 : 字符串逃逸技术 原理 通过控制序列化字符串长度,使后续内容被解析为新属性。 典型案例 :[ 0CTF 2016 piapiapia ] 构造payload闭合前部分序列化: ";}s:5:"photo";s:10:"config.php";} 利用过滤规则增加字符数(如where→hacker多1字符) 计算需要增加的字符数,插入相应数量的触发词 对象逃逸技术 通过覆盖或构造特定对象属性,使反序列化后执行非预期操作。 关键点 : 利用 __toString() 等魔术方法 控制对象属性间的引用关系 通过数组操作等方式绕过过滤 POP链构造 POP(Property-Oriented Programming)链通过串联多个类的魔术方法和普通方法实现攻击。 构造步骤 : 寻找起点(如 __destruct() ) 分析类方法调用关系 寻找敏感函数调用 构造属性控制执行流程 示例 :[ MRCTF 2020 Easy pop ] Show::__toString() → Test::__get() → Modifier::__invoke() 最终触发文件包含读取flag 其他利用方式 SoapClient + 反序列化 → SSRF Exception类 → XSS 防御措施 及时更新PHP版本 避免反序列化用户输入 使用一致session处理器 对魔术方法进行安全编码 禁用不必要的类序列化 总结 PHP反序列化漏洞形式多样,从简单的魔术方法绕过到复杂的POP链构造,理解这些技术有助于开发更安全的代码和更有效的防御措施。在实际应用中,应特别注意对用户可控数据的处理,避免危险函数的直接调用。