JAVA代码审计之jshERP
字数 1433 2025-09-01 11:26:11
JshERP代码审计报告与安全教学
1. 项目概述
JshERP(原名华夏ERP)是一款基于SpringBoot框架和SaaS模式的开源ERP软件,主要面向中小企业,提供以下功能模块:
- 零售管理
- 采购管理
- 销售管理
- 仓库管理
- 财务管理
- 报表查询
- 系统管理
特色功能包括:预付款、收入支出、仓库调拨、组装拆卸、订单管理等,采用多租户架构设计。
2. 环境搭建
- 下载源代码:
https://github.com/jishenghua/jshERP - 使用IDEA打开工程
- 根据配置文件中的数据库凭据创建数据库
- 导入
doc/目录下的数据库文件 - 启动项目
3. 安全漏洞分析
3.1 硬编码凭证
问题描述:
- 配置文件中存在明文存储的数据库凭据和Redis凭据
风险等级:高危
修复建议:
- 使用Nacos配置中心
- 使用jasypt等加密库对敏感配置进行加密
3.2 Log4j组件风险
问题描述:
- 使用了风险版本的log4j(1.2.17之前版本)
利用条件:
- Apache Log4j开启socket端口暴露
- 项目中存在可利用的Gadget
实际风险:
- 第一个条件不满足,无法直接利用
3.3 RestFul API未授权访问
问题描述:
- 应用自动启动的后端API服务暴露
doc.html文档 - 过滤器对包含
/doc.html的请求直接放行
访问方式:
http://[ip]:[port]/jshERP-boot/doc.html
风险:
- 暴露所有API接口和参数说明,可能被攻击者利用
3.4 任意用户密码重置
位置:UserController
问题描述:
- 仅根据UID进行密码重置
- 默认密码硬编码为"123456"
- 使用不安全的MD5哈希处理
代码分析:
// 重置密码逻辑
String defaultPassword = "123456"; // 硬编码弱口令
String md5Password = MD5Util.getMD5(defaultPassword); // 不安全哈希
userService.resetPwd(uid, md5Password); // 仅根据UID重置
多租户设计缺陷:
- 应在"租户ID+用户ID"维度进行密码重置
- 或使用"租户ID+租户管理权限+用户ID"方式
3.5 租户间水平越权
典型位置:
- 用户列表接口
- 用户删除接口
问题描述:
- 仅根据UID进行数据查询和操作
- 未考虑租户隔离
- 导致租户间可互相访问/修改数据
示例代码:
// 用户查询逻辑
public User getUser(Long uid) {
return userMapper.selectByPrimaryKey(uid); // 仅基于UID查询
}
3.6 普通租户到系统管理员垂直越权
位置:TenantController
问题描述:
- 接口未做角色层面的过滤器拦截
- 操作仅基于ID维度
- 缺少管理员权限校验
风险:
- 普通租户可执行系统管理员操作
3.7 任意文件上传(防御成功案例)
位置:文件上传统一处理方法
防御措施:
- 检查文件路径中的"../"和"/"
- 校验Token凭证(X-Access-Token)
- 验证租户信息
- 文件白名单校验
剩余风险:
- 虽然无法直接getshell,但可利用PDF XSS漏洞攻击其他租户用户
4. 多租户安全设计建议
-
鉴权体系:
- 实现严格的租户隔离
- 基于"租户ID+用户ID+角色权限"进行访问控制
-
数据隔离:
- 考虑分库分表存储方案
- 明确物理隔离与逻辑隔离的应用场景
-
租户管理:
- 实现租户内角色划分
- 租户管理员只能管理本租户数据
- 系统管理员需特殊权限控制
-
API安全:
- 所有接口需进行租户级鉴权
- 敏感操作需二次确认
5. 总结
JshERP作为多租户ERP系统,在安全设计上存在多个关键问题,主要集中在:
- 缺乏严格的租户隔离
- 权限控制不完善
- 敏感信息处理不当
- 接口访问控制缺失
修复建议应从多租户架构的安全设计入手,建立完善的租户隔离和权限体系,同时对现有漏洞进行针对性修复。