数据库安全网关是应用层防御失效时的最后一道拦截,需支持语义级ast解析、部署于数据库统一入口、分等级实施策略。

SQL注入防护不能只靠开发人员写对PreparedStatement
数据库安全网关不是“锦上添花”,而是当应用层防御失效时的最后一道拦截。比如ORM自动拼接的动态SQL、遗留系统里大量String.format或concat拼接的查询、第三方SDK绕过参数绑定——这些场景下,单靠代码层过滤根本拦不住' OR 1=1 --这类载荷。
真实情况是:你没法保证所有接口都用PreparedStatement,更没法让运维同事在凌晨三点去改Java代码修复一个新爆出的MyBatis ${}漏洞。
数据库安全网关必须支持语义级SQL解析,不能只做正则匹配
很多网关用REGEXP匹配UNION SELECT或EXEC xp_cmdshell,这种规则极易被绕过:SEL/**/ECT、unIoN/**/sElEcT、大小写混用、URL编码、宽字节注入都能逃逸。
- 真正有效的网关会把SQL解析成AST(抽象语法树),识别出
WHERE子句中是否出现非绑定变量的布尔表达式 - 它能区分
WHERE id = ?和WHERE id = 1 OR 1=1,哪怕后者藏在Base64里或经过多层注释包裹 - 不支持AST解析的网关,在MySQL 8.0+的CTE递归查询、PostgreSQL的
WITH RECURSIVE等复杂语法面前基本失效
部署位置决定能否拦住所有流量,别让网关变成摆设
如果网关只串在应用服务器和主库之间,但应用还直连从库做报表查询、或者DBA用mysql -h命令行直连、甚至有ETL工具绕过连接池——那网关就只覆盖了不到40%的SQL路径。
- 必须部署在数据库入口统一出口处,比如VIP后、负载均衡器之后、或直接替换数据库监听端口
- 确认所有客户端连接字符串里的
host都指向网关IP,而不是原始DB IP;否则jdbc:mysql://10.1.1.5:3306这种写死地址会彻底绕过 - 注意SSL/TLS透传:某些网关不支持TLS终止,而应用启用了
useSSL=true,会导致握手失败,连接直接拒绝
规则策略要分等级,别把告警当阻断
刚上线就全量阻断高危SQL,大概率会引发业务雪崩。真实环境里,SELECT * FROM user WHERE name LIKE '%${keyword}%'这种模糊搜索天天触发LIKE '%'规则,但它未必是漏洞,可能是合法搜索。
- 第一阶段只开启
log_only模式,持续采集7天真实SQL流量,用sql_id聚类分析哪些规则误报率高 - 对
INSERT/UPDATE/DELETE语句默认强阻断,对SELECT先限流(如单IP每秒最多5次含UNION的查询)再逐步收紧 - 给DBA留个
/* bypass_waf */注释开关——紧急修复时能临时放行,但每次使用都会记录操作人和时间戳
最麻烦的永远不是配置规则,而是厘清哪些SQL是业务刚需、哪些是测试脚本残留、哪些是监控探针发的探测语句。没做过SQL流量画像就开阻断,等于蒙眼踩油门。










