nginx用if+return匹配sql注入关键词是最轻量方式,但仅能拦截显性攻击;深度防护需modsecurity解码归一化检测,须编译加载规则并调优,且必须分层防御、严格验证与日志监控。
nginx 里用 ngx_http_rewrite_module 拦截 sql 注入关键词
直接在 location 或 server 块里用 if + return 是最轻量、最可控的方式,适合快速拦截明显恶意请求。nginx 本身不解析 sql,只能靠匹配 url、查询参数、请求头里的典型攻击特征,比如 ' or '1'='1、union select、select.*from 这类固定模式。
常见错误现象:if 写在 location 外但没加 break,导致重写后又进其他规则;或正则里没转义点号、括号,实际没生效。
- 只对
$args(查询参数)和$request_uri做匹配,$request_body在普通配置中不可读,别白费劲 - 正则用
~*(忽略大小写),避免漏掉union select或UnIoN SeLeCt - 匹配到就
return 403,别用rewrite ... break,容易绕过或触发二次处理
示例(放在 server 块内):
if ($args ~* "(%27)|(\')|(--)|(%23)|(#)|(\b(SELECT|INSERT|UPDATE|DELETE|UNION|DROP|CREATE|ALTER|EXEC|EXECUTE|DECLARE|CAST|CONVERT)\b)") {
return 403;
}
用 nginx-mod-security(libmodsecurity)做深度检测
真正想防住变形、编码绕过的 SQL 注入,必须上 ModSecurity,它能解码、归一化、多阶段匹配。但注意:这不是开箱即用的“插件”,而是要编译模块、加载规则集、调优性能——很多团队卡在第一步就放弃了。
使用场景:已有 OWASP CRS 规则集、需要防御 Base64 编码的 payload、或需结合请求体(POST body)分析。
- 必须启用
SecRequestBodyAccess On才能检查 POST 数据,否则只扫 URL 和 headers - OWASP CRS 的
REQUEST-942-SQLI-ATTACKS.conf是主力规则,但默认会误杀order by id这类合法语句,得关掉或调低SecRuleEngine级别先观察日志 - 每条请求多消耗 5–15ms CPU,高并发下务必压测,别上线才发觉 TTFB 翻倍
为什么不能只依赖 Nginx 层 WAF?
因为 Nginx 在七层最前端,看不到应用层逻辑,也做不了上下文判断。比如 /api/user?id=123 是合法查询,但 /api/user?id=123%20OR%201=1 就得拦——可如果后端用的是 ORM,根本不会拼 SQL,这种拦截纯属多余,还可能挡住正常编码参数。
- 规则越激进,误伤率越高;越宽松,漏报越多。没有银弹,只有权衡
- 攻击者早就不硬刚
SELECT * FROM了,改用注释符/**/、宽字节、JSON 字段嵌套绕过,Nginx 正则很难覆盖 - 真正有效的防护是分层:Nginx 拦显性攻击 + 应用层参数绑定 + 数据库最小权限 + 日志审计联动
上线前必须验证的三个点
很多人配完规则就以为万事大吉,结果第二天发现登录接口 403、搜索功能全挂——问题往往出在验证环节太草率。
- 用真实业务流量回放测试,别只拿几个
curl示例跑完就上线 - 检查
error_log里是否高频出现client sent too large header或limit_except相关报错,ModSecurity 启动失败时可能静默降级 - 确认
SecResponseBodyAccess Off(默认),除非你真需要扫描响应体内容,否则开启会拖慢所有响应
复杂点在于:SQL 注入不是独立存在的,它常和 XSS、路径遍历混在一起出现;而规则之间有优先级、执行顺序、变量作用域,调一条可能影响十处。上线后盯三天日志,比写十条规则更重要。










