ThinkPHP是什么
ThinkPHP是 是一个快速、简洁、轻量级的 PHP 开发框架,由中国开发者团队开发和维护。它旨在简化 PHP 应用程序的开发流程,提供丰富的功能和工具,帮助开发者高效构建 Web 应用程序、API 服务等。
ThinkPHP 的特点
- 简单易用:ThinkPHP 的设计理念是“大道至简”,提供了直观的 API 和文档,适合初学者和高级开发者。 
- 高性能:框架经过优化,运行效率高,适合处理高并发场景。 
- 模块化设计:支持模块化开发,方便项目的组织和扩展。 
- 丰富的功能 - 数据库操作(支持多种数据库,如 MySQL、PostgreSQL、SQLite 等)。
- 路由系统(支持 RESTful 路由)。
- 模板引擎(内置模板引擎,支持视图渲染)。
- 缓存机制(支持多种缓存方式,如文件缓存、Redis、Memcached 等)。
- 安全性(提供 CSRF 防护、XSS 过滤等安全机制)。
 
- 跨平台:支持 Windows、Linux、macOS 等操作系统。 
- 社区活跃:拥有庞大的中文开发者社区,文档和教程丰富。 
而**ThinkPHP (8.1.2)**是官方在2025年1月发布的改进版本,现被发现存在反序列化漏洞,然后我这里跟着文章去复现一下
参考文章:最新版 ThinkPHP (8.1.2) 反序列化漏洞挖掘
环境搭建
既然是8.1.2的版本出现的漏洞,那么肯定需要拉源码下来分析了
当前PHP版本:8.1.2
ThinkPHP 版本: 8.1.2, 官网 Github: https://github.com/top-think/framework/releases/tag/v8.1.2, 这里使用composer进行安装即可
| 1 | composer create-project topthink/think=8.1.2 my-project | 
- topthink/think:ThinkPHP 的 Composer 包名称。
- 8.1.2:指定安装的版本。
- my-project:项目目录名称,可以自定义。
我是在vps的web目录下安装的,安装完成后直接访问就行

然后在Windows物理机拉一下源码然后放phpstorm进行分析
先看看大致的目录内容

随后我们创建\app\controller\Wang.php文件, 内容如下(当作控制器)
| 1 | 
 | 
然后我们访问index方法

漏洞分析
任意文件读写
既然需要触发反序列化,那么就需要一个能触发的口子,也就是__destruct方法,所以我们全局搜索__destruct

发现vendor/league/flysystem-cached-adapter/src/Storage/AbstractCache这个类存在一个save方法调用, 但它是抽象类, 不允许反序列化, 我们找一下它的子类中的save方法
| 1 | public function save() | 
在107行用了getForStorage()方法
| 1 | public function getForStorage() | 
| 1 | //cleanContents方法 | 
分析一下代码
在getForStorage方法中,会对内容进行一定的清理,并返回一个json串,而成员属性是可控的, 所以这里$contents的最终结果是部分可控的, 因为返回了一个具体的JSON串.
然后继续看save方法,有write调用,大致意思就是如果文件存在则update更新文件的内容,不存在则写入文件
由于write方法名就像是写入文件操作, 所以这里全局搜索write方法的定义, 看一下是否存在一些文件写入等功能模块的调用
在vendor/league/flysystem/src/Adapter/Local.php中有write的方法,并且在原来的调用中可以看到这个write的第一个参数和第二个参数是可控的,而第三个参数是$config = new Config();
| 1 | public function write($path, $contents, Config $config) | 
这里存在一个文件写入操作,那我们尝试着去写链子
| 1 | vendor/league/flysystem-cached-adapter/src/Storage/AbstractCache::__destruct->vendor/League\Flysystem\Cached\Storage\Adapter::save->vendor/league/flysystem/src/Adapter/Local::write | 
那我们的poc就是
| 1 | 
 | 
把poc写在public目录下,因为在public目录下的文件才能对外访问到
我们访问poc.php
