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