Nginx可通过if指令配合$request_uri与大小写不敏感正则匹配SQL关键字(如select|union等)及编码变体,返回403阻断请求,但仅作外围防护,无法覆盖POST体、高级编码绕过,且存在误杀与性能风险,应结合WAF与应用层加固。

可以通过 Nginx 的 if 指令配合正则匹配,在请求进入后端前直接拒绝包含 SQL 关键字(如 SELECT、UNION、INSERT 等)的 URI,实现基础的 SQL 注入防护。
在 location 块中用 if + $request_uri 匹配关键词
Nginx 不支持在 if 中直接对完整请求行做复杂过滤,但 $request_uri 变量包含原始 URI(含查询参数),适合用于简单关键字扫描。注意:该变量不包含协议、域名和 fragment(# 后内容),且已解码,匹配时需注意大小写。
- 使用
~*进行大小写不敏感正则匹配 - 把高危关键词用
|连接,避免漏掉变体(如空格绕过、编码绕过需额外处理) - 匹配到立即返回 403,阻止请求继续转发
示例配置:
location / {
if ($request_uri ~* "(select|union|insert|update|delete|drop|sleep|benchmark|load_file|outfile)") {
return 403;
}
proxy_pass http://backend;
}增强匹配:覆盖常见绕过手法
攻击者可能用 URL 编码、双写、大小写混用、添加空格或注释符(如 /**/)绕过简单匹配。Nginx 本身不支持多层解码或语法解析,但可叠加几类规则提升覆盖面:
- 匹配 URL 编码形式:如
%73%65%6c%65%63%74(select 小写 hex)、%20(空格)、%2f%2a(/*) - 匹配注释干扰:
/\*\*/、/\*\+\*/、/\*\!12345\*/ - 匹配常见变形:
selecT、unIOn、sel/**/ect、un/**/ion
实际配置中建议合并为一条更健壮的正则(注意性能与可读性平衡):
if ($request_uri ~* "(select|union|insert|update|delete|drop|sleep|benchmark|load_file|outfile|into\s+outfile|handler\s+\w+\s+read)|(%73%65%6c%65%63%74|%75%6e%69%6f%6e|%69%6e%73%65%72%74|%75%70%64%61%74%65|%64%65%6c%65%74%65|%64%72%6f%70|%73%6c%65%65%70|%62%65%6e%63%68%6d%61%72%6b|%6c%6f%61%64_%66%69%6c%65|%6f%75%74%66%69%6c%65)|(/\*\*?/)|(\+\+)|(%20)|(%00)") {
return 403;
}注意事项与局限性
Nginx 的 if 在 location 中虽可用,但属于“危险区域”,过度依赖可能引发意外交互(如与 rewrite、proxy_pass 冲突)。更重要的是,它仅是外围防线,不能替代应用层防护:
- 无法识别 Base64、二次编码、Unicode 归一化等高级绕过
- 无法防御 POST body 中的 SQL 注入(
$request_body在 if 中不可用,且读取会破坏流式转发) - 正则过于宽泛可能导致误杀(如正常路径含 “union” 字样,如
/api/v1/union-list) - 不建议在高并发场景下启用复杂正则,可能影响吞吐量
更可靠的替代方案建议
若需生产级 SQL 注入防护,推荐组合使用:
- Web 应用防火墙(WAF):如 ModSecurity + OWASP CRS,专为语义分析设计
- 应用层加固:使用预编译语句(Prepared Statement)、ORM 参数化查询、输入白名单校验
- 日志联动:将匹配到的恶意 URI 记入 access_log,接入 SIEM 分析高频攻击源
- 动态限速:对触发关键词的 IP 在限流模块中临时封禁(如 limit_req)


















