CVE-2023-24163: J2eeFAST SQL 注入漏洞分析
0x00 漏洞背景与详情
- CVE ID: CVE-2023-24163
- 漏洞类型: SQL 注入 (CWE-89)
- 危险等级: 高危 (High)
- 受影响产品: J2eeFAST (JavaEE 开源快速开发平台)
- 受影响版本: v2.5.1 及以下版本
J2eeFAST 是一款基于 SpringBoot + Shiro + Mybatis-Plus 构建的开源快速开发框架。CVE-2023-24163 漏洞存在于其后端的 /sys/role/list 接口中。由于在处理动态 SQL 查询时,未对用户输入的参数进行充分过滤和参数化处理,导致攻击者可以构造恶意的 SQL 语句,绕过身份验证并读取、修改甚至破坏数据库中的数据。
0x01 漏洞原理分析
该漏洞的根本原因在于 MyBatis 中对动态 SQL 的不当使用 以及 自定义过滤器 (SQLFilter) 被绕过。
- MyBatis 拼接风险: 在
SysRoleMapper.xml的查询配置中,针对如roleName这样的字段,代码中使用了${}符号进行字符串拼接,而不是安全的#{}预编译占位符。 - 过滤机制缺陷: 虽然 J2eeFAST 内置了
SQLFilter.java来防御 SQL 注入(通过过滤select,update,delete,truncate等关键字),但这种基于正则或字符串替换的黑名单机制很容易被绕过。例如,利用大小写组合、内联注释/*!50000select*/或者特定的数据库函数(如SLEEP())即可突破限制。 - 参数传递透明化: 框架通常将前端传入的 JSON 或表单参数封装为 Map 传递给后端,若不进行深度的白名单清洗,恶意载荷很容易直达底层数据库引擎。
0x02 POC (Proof of Concept)
攻击者通常利用 时间盲注 (Time-Based Blind) 来确认该漏洞的存在。
验证请求示例
触发表现: 如果服务器端接收请求后,响应时间明显增加了 5 秒左右,则说明 SLEEP(5) 函数在数据库中被成功执行,SQL 注入漏洞存在。
0x03 高级利用姿势与实战场景
在实战渗透中,SQL 注入不仅限于数据窃取,还可以进一步升级为 RCE(远程代码执行)。
1. 数据脱库与后台接管
- 通过
UNION SELECT注入读取sys_user表中的管理员账号、Salt(盐值)以及哈希密码。 - 如果目标系统的 Shiro 配置存在弱密钥问题,还可以进一步结合 SQL 注入读取密钥配置,从而伪造
RememberMeCookie 实现反序列化 RCE。
2. 数据库到系统的跨越 (GetShell)
- Into Outfile 写马: 如果 MySQL 数据库以高权限(如 root)运行,且配置文件中
secure_file_priv未做严格限制,攻击者可以通过注入直接将 JSP WebShell 写入网站的根目录。 - 全局日志写马: 利用 SQL 注入执行
SET GLOBAL general_log=1;,并将general_log_file的路径修改为 Tomcat 容器的 Web 目录下的.jsp文件,然后发起包含 JSP 恶意代码的查询请求,实现日志文件的解析执行。
3. WAF 防御绕过
在目标存在 WAF 的情况下,可使用高级的 SQL 注入绕过技巧:
- 关键字混淆: 利用
seselectlect(防单次替换)、SeLeCt(大小写混淆)。 - 编码绕过: 对 Payload 进行 URL 二次编码、Hex 编码,或使用
CHAR()函数转换恶意字符串。
0x04 应急排查与日志痕迹分析
在遭遇攻击时,应从以下维度排查:
1. Web 访问日志审计
检查 access.log,检索包含 /sys/role/list 路径的 POST 请求。重点关注请求参数(如 roleName)中是否包含 %27 (单引号)、--、SLEEP、UNION、INFORMATION_SCHEMA 等 SQL 注入特征。
2. 数据库层面排查
- 检查 MySQL 的慢查询日志(Slow Query Log),寻找异常长耗时的查询语句(可能正在遭受时间盲注攻击)。
- 检查
general_log(若开启),查看是否有非预期的跨库查询或敏感系统表访问。
3. 文件系统完整性检查
- 排查 Web 根目录是否有新增的、具有可执行权限的
.jsp文件。 - 检查数据库配置相关的配置文件(如
application.yml)是否被恶意读取。
0x05 修复建议与参考资料
修复建议:
- 升级版本: 立即将 J2eeFAST 升级到官方发布的最新修复版本。
- 规范 MyBatis 语法: 全面排查所有 Mapper XML 文件,禁止在
ORDER BY、GROUP BY或模糊查询之外的地方使用${},强制改用#{}。对于模糊查询,应使用数据库原生的拼接函数(如 MySQL 的CONCAT('%', #{value}, '%'))。 - 加固过滤器: 完善
SQLFilter.java的逻辑,采用更严格的黑白名单结合的输入校验机制。
参考资料: