数据库中间件不提供可靠的SQL注入防护,真正防护需在驱动层或业务逻辑层实现;MyCat的sqlFilter仅简单匹配关键词,ShardingSphere的SQL解析器默认不拦截,唯一可行策略是强制参数化语句并拒绝裸字符串。

数据库中间件(如 MyCat、ShardingSphere)本身不提供开箱即用的 SQL 注入防护能力,直接依赖它们做“过滤”是危险的误判。真正的防护必须下沉到驱动层或业务逻辑层,中间件只能辅助审计、限流或拦截明显恶意模式——但这类规则极易被绕过。
MyCat 的 sqlFilter 配置根本不可信
MyCat 1.6+ 提供了 server.xml 中的 sqlFilter 开关和白名单机制,但它只匹配 SQL 字符串开头是否为允许类型(如 SELECT、INSERT),不解析语法树,也不校验参数绑定状态。
- 攻击者用
SELECT/*comment*/+1 FROM users就能绕过关键词检测 -
sqlFilter="true"不会阻止SELECT * FROM users WHERE name = 'admin' OR '1'='1'这类已拼接完成的恶意语句 - 它对
UNION SELECT的检测基于正则,而UNI/**/ON SEL/**/ECT可轻松逃逸 - 开启后仍需手动维护
whiteList,但表名、列名等动态部分无法穷举,一加就卡死业务
ShardingSphere 的 SQLParserEngine 不等于防注入
ShardingSphere-Proxy 5.3+ 内置 SQLParserEngine,能解析 SQL 类型、提取表名、识别参数占位符,但它默认不启用拦截,且解析结果不参与执行决策。
- 你不能靠它自动拒绝含
@variable或字符串拼接的语句——那是业务代码该干的事 - 它的
sql-comment-parse-cache和sql-show是调试用的,不是安全开关 - 若强行在
SQLFederationRouter阶段 throw 异常,会导致分片路由失败,而非阻断注入 - 真正起作用的是你在
org.apache.shardingsphere.driver.jdbc.core.statement.ShardingSpherePreparedStatement上做的增强,但这已脱离中间件范畴,进入驱动封装层
中间件唯一靠谱的防御动作:只放行参数化语句 + 拒绝裸字符串
如果你坚持在中间件层设防,唯一可落地的策略是:让中间件拒绝所有未使用占位符的 SQL 请求,并强制要求客户端使用 ? 或 $1 占位符。但这需要配套改造客户端行为。
- MyCat 需配合自定义
SQLInterceptor,检查SQLStatement是否含LiteralExpression(即字面量字符串),有则throw new RuntimeException("Raw string interpolation forbidden") - ShardingSphere 需在
SQLParseResult中遍历ParameterMarkerExpressionSegment,确认每个值都来自参数而非字符串拼接;否则返回400 Bad Request并记录sql原文 - 注意:MySQL 协议层无法区分
SELECT * FROM t WHERE id = ?和SELECT * FROM t WHERE id = 123,所以必须在中间件解析 SQL 后、转发前完成判断 - 该策略会破坏所有使用
String.format构建 SQL 的旧代码,上线前必须全量扫描.executeUpdate(、.executeQuery(等调用点
最易被忽略的一点:MyCat 和 ShardingSphere 都不处理存储过程内部的动态 SQL。如果业务用了 CALL proc_search(?),而 proc_search 内部是 EXEC('SELECT * FROM '+@table),中间件完全看不见——防护必须延伸到数据库侧的存储过程审查和权限收紧。











