${}不是漏洞本身,但用在用户可控位置且无校验就是高危SQL注入入口;因其始终为字符串拼接,不经过预编译,攻击者可注入恶意SQL片段,如user; DROP TABLE user--或id, (SELECT password FROM admin),而MyBatis 3.5未改变该行为。

直接说结论:${} 不是漏洞本身,但用在用户可控位置且无校验,就是高危 SQL 注入入口。
为什么 ${} 在 MyBatis 3.5 中仍会触发 SQL 注入
MyBatis 3.5 并未改变 ${} 的底层行为——它仍是字符串拼接,不是预编译。框架升级不会自动修复你代码里写的 ${tableName} 或 ${sortField}。只要参数来自 HTTP 请求、JSON body、前端下拉框 value 等不可信源,又没做白名单校验,攻击者就能塞入 user; DROP TABLE user-- 或 id ASC, (SELECT password FROM admin LIMIT 1) 这类 payload。
常见错误现象:
-
WHERE name = '${name}'→ 用户传admin' OR '1'='1,SQL 变成WHERE name = 'admin' OR '1'='1' -
ORDER BY ${field}→ 传created_time, (SELECT @@version),直接拖库或探测数据库版本 -
FROM ${log_table}→ 表名被替换为user_logs UNION SELECT ...,绕过权限限制
哪些地方不得不写 ${},但又最容易翻车
必须用 ${} 的场景极少,集中在 SQL 语法结构层,这些位置 JDBC PreparedStatement 根本不支持参数化:
- 表名:
FROM ${tableName}(#{tableName}会加引号,变成FROM 'user_v2026'报错) - 字段名:
GROUP BY ${groupField}、SELECT ${countExpr} - 排序方向:
ORDER BY created_at ${order}(#{order}会变成ORDER BY created_at 'desc',按字符串字面值排序) - LIMIT 偏移量:
LIMIT ${offset}, #{size}(#{offset}不支持表达式计算)
容易踩的坑:
- 把
${@shard_suffix}当“固定值”用,其实@shard_suffix可能来自配置中心,而配置中心本身已被攻破 - 在
<script>动态 SQL 块里混用${}和#{},视觉上难分辨,review 时漏掉校验 - 认为“只在后台管理接口用,前端不暴露,所以安全”,忽略了攻击者可通过低权限账号+未授权接口篡改配置
怎么校验 ${} 才算真正守住底线
校验必须发生在字符串进入 MyBatis 之前,不是进 DAO 层之后,更不是交给数据库执行时才检查。
- 白名单必须硬编码,例如
List.of("user_logs_2026", "order_events_q3"),禁用从数据库、配置中心、Redis 读取的“可变白名单” - 正则校验要严格:
^[a-z][a-z0-9_]{2,31}$(小写字母开头、3–32 字符、仅字母数字下划线),拒绝..、;、--、空格、大写字母 - 校验失败立即抛
IllegalArgumentException,不 fallback、不默认值、不记录日志后继续执行 - 模糊查询别写
LIKE '%${name}%'——通配符必须拼在 Java 层:param.setSearchPattern("%" + userInput.trim() + "%"),SQL 里只用#{searchPattern}
排查和加固的实操动作
别依赖“我记得都用了 #{}”,真实风险藏在 grep 结果里:
- 全项目搜索:
grep -r '\$\{.*\}' src/main/resources/mapper/ --include="*.xml",把每个${}都拎出来人工过一遍 - 重点盯三类:
${tableName}、${orderBy}、${@xxx}(带@的通常是配置注入点) - 检查是否已有校验逻辑:没有就加;有但校验逻辑在 service 层下游(比如进了 DAO 才 check),就往上提,提至 controller 或 DTO 绑定后立刻校验
- 升级 MyBatis 3.5.x 后注意:
@SelectProvider返回类型更严,原来侥幸跑通的${}错误可能直接报错,这不是 bug,是框架在帮你暴露隐患
最危险的不是找不到修复方法,而是把 ${} 当成“动态语法糖”,忘了它背后是裸字符串拼接——只要输入没锁死,它就是一把没上膛却已对准数据库的枪。

















