签名验证不能替代sql注入防护,二者必须串联执行:先验签名再扫sql,签名非法直接401拒绝;签名合法但sql检测失败则触发告警,禁止先扫sql再验签以防绕过。

签名验证不能替代SQL注入防护,二者必须串联生效。单独开启签名,攻击者用合法 App 发出 keyword=xxx%27%20UNION%20SELECT%20 这类请求,签名依然校验通过——漏洞就直接打穿到数据库。
为什么“签名+SQL检测”必须串行执行
网关层若把签名验证和 SQL 检测拆成两个独立 Filter,就可能出现“先过签名、再进 SQL 检测”的竞态:一旦 SQL 检测逻辑有 bug 或被绕过(比如没扫描 Cookie、User-Agent),恶意参数就已进入后端。真实防御必须强制要求:
- 所有请求必须携带
timestamp和nonce,且二者参与签名原文拼接(顺序固定、不可省略) -
SignUtil.verify()返回 true 后,**立即**进入 SQL 特征扫描,不得跳过或异步延迟 - 扫描范围必须覆盖
request.getQueryParams()、ServerWebExchange.getFormData()、JSON Body 解析后的所有字符串字段,以及headers.get("Cookie")和headers.get("User-Agent")
Spring Cloud Gateway 中 SQL 扫描的实操要点
默认 GlobalFilter 不解析 JSON Body,容易漏掉 POST /api/search 这类接口。需手动用 Flux<databuffer></databuffer> 异步读取并转为 JsonNode,再递归遍历所有字符串值:
- 匹配规则聚焦高频攻击子串:
'、"、;、--、#、UNION、SELECT、INSERT、EXEC(忽略大小写) - 对布尔盲注特征如
OR\s+'1'\s*=\s*'1',必须用Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE编译正则,否则大小写混写(如uNiOn)会逃逸 - 命中即返回
400 Bad Request,响应体为空,**不记录原始参数到日志明文**(防信息泄露),只存脱敏后的 key 名和长度
签名绕过场景下最危险的三个参数位置
很多团队只扫 query 和 form-data,却忽略以下三处高危入口:
-
Cookie头里的session_id=abc%27%20OR%201%3D1—— 攻击者可复用合法登录态发起注入 -
User-Agent值被拼进审计日志 SQL(如INSERT INTO logs (ua) VALUES ('...')),形成二次注入温床 - URL 路径中的变量,例如
/v1/user/{id},若id直接用于WHERE id = ?之外的动态表名或列名,参数化也救不了
真正难防的不是 ' OR 1=1 这种明文 payload,而是当签名、时间戳、nonce 全部合法,但某个字段在业务层又被二次拼接进 SQL 的情况——这时候网关的 SQL 检测早已结束,漏洞发生在你完全没监控到的代码深处。











