WAF拦截SQL注入只是临时止血,不是修复;它依赖规则匹配已知特征,对编码绕过、注释变形、JSON body、协议解析差异等场景失效,真正防御须靠应用层参数化查询与白名单校验。

WAF拦截SQL注入只是临时止血,不是修复
WAF(如云WAF、ModSecurity、阿里云WAF)在请求到达应用前匹配union select、sleep(、1=1等特征做阻断,能拦住基础扫描器和脚本小子,但对真实攻击几乎无效。因为:
- 攻击者用十六进制编码绕过:0x556e696f6e2053656c656374(union select 的 hex)
- 用注释符截断检测逻辑:id=1/*!UNION*/+SELECT+1,2,3
- 利用宽字节(如 GBK 编码下 %A1%AA)让转义失效,WAF 解析和后端不一致
- 多层 URL 编码、大小写混用、内联注释(/**/)均可绕过规则库
WAF 层面的规则更新永远滞后于新型 payload,它本质是“识别已知坏”,而 SQL 注入的变体近乎无限。
哪些场景下 WAF 拦截确实有用
WAF 不该被弃用,但在明确边界下才值得依赖:
- 应急响应阶段:确认漏洞存在但代码无法立即上线时,加一条 SecRule ARGS "@rx (union\s+select|sleep\()" 可快速压低攻击成功率
- 只读接口的暴力探测防护:比如公开的搜索页、商品列表页,用户输入仅用于 WHERE name LIKE '%?%' 类查询,且无登录态,WAF 可过滤高频异常 pattern
- 日志审计增强:开启 WAF 的 SQLi 规则并记录原始请求,可反向定位未覆盖的拼接点(如某个 /api/v1/report?sort= 参数从未走参数化)
- 非标准端口或协议流量:比如管理后台走 HTTP 而非 HTTPS,WAF 是唯一能统一拦截的网关节点
WAF 配置最容易踩的三个坑
很多团队开了 WAF 却以为高枕无忧,实际因配置不当导致:
- 规则作用域错误:把 SQLi 规则只加在 /login 路径,却漏掉 /api/user/profile?uid= 这类带参 GET 接口
- 误杀正常业务字符:启用严格模式后,用户昵称含单引号(如 O'Connor)或订单号含 AND(如 ORD-2024-AND-001)被直接拦截,引发客诉
- 忽略 POST body 解析:WAF 默认只检查 URL 和 Cookie,若业务用 JSON 提交({"query": "admin' OR 1=1--"}),需显式开启 SecRequestBodyAccess On 并配置 JSON 解析器,否则形同虚设
真正要盯死的,是 WAF 日志里反复出现的“漏网请求”
WAF 拦不住的请求,恰恰暴露了代码最脆弱的部分:
- 查看 WAF 日志中被放行但含可疑 pattern 的请求(如 id=1%20OR%201=1),提取其完整 URL 和参数名,立刻去代码里搜 $_GET['id'] 或 request.args.get('id')
- 如果某参数名(如 sort_field)频繁出现在绕过记录里,基本可断定它被拼进了 ORDER BY 子句——这无法参数化,必须上白名单校验
- 所有被 WAF 放行的 UNION SELECT 请求,如果返回了数据库错误(如 MySQL error: Unknown column 'xxx' in 'field list'),说明后端没做任何输入过滤,且错误信息未关闭,这是双重风险点
WAF 不是补丁,它是镜子。照出哪里没修好,比它拦住多少次更重要。

















