在Virtual Host的server块中配置Nginx拦截SQL注入,核心是用if+~*正则匹配$args和$request_uri并return 403;必须避免使用$request_body和rewrite匹配参数,且规则仅限server块内生效。

在 Virtual Host(即站点 server 块)中配置 Nginx 安全防护规则拦截 SQL 注入,核心是利用 if + 正则匹配对请求参数和 URI 进行实时检查,并返回 403。但要注意:Nginx 本身不是 WAF,它只做前置过滤,且能力受限于编译模块——尤其是 phpEnv 等精简版 Nginx,无法读取请求体($request_body),也不支持 ModSecurity 或 Lua,所以只能靠 if 检查 $args 和 $request_uri。
只在 server 块内添加规则,别放全局 http 块
if 指令在 location 外、server 内才有效;放在 http 块会报错 “nginx: [emerg] ‘if’ directive is not allowed here”。规则必须写在你站点的 vhost 配置里,例如:
C:\phpEnv\nginx\conf\vhost\myapp.conf(Windows)或
/etc/nginx/sites-enabled/myapp(Linux)
用 ~* 匹配大小写不敏感的关键字
攻击者常用大小写混写绕过(如 UnIoN SeLeCt),所以必须用 ~* 而非 ~:
if ($args ~* "(%27)|(\')|(--)|(%23)|(#)|(\b(SELECT|UNION|INSERT|UPDATE|DELETE|DROP|EXEC|CAST|CONVERT)\b)") { return 403; }if ($request_uri ~* "(%27)|(\')|(--)|(%23)|(#)|(\b(SELECT|UNION|INSERT|UPDATE|DELETE|DROP|EXEC|CAST|CONVERT)\b)") { return 403; }
注意:%27 是 URL 编码的单引号,-- 和 # 是 SQL 注释符,\b 保证匹配完整单词(避免误杀 user_select 这类正常词)。
避开常见陷阱:别碰 $request_body 和 rewrite
phpEnv 的 Nginx 不支持 $request_body 变量,写 if ($request_body ~* ...) 永远不生效;
rewrite 也无法匹配问号后的参数(即 ?id=1' and 1=1 中的 '),必须用 if ($args ~*)。
- ❌ 错误:
rewrite ^.*[\'\;\].* /404.html break;→ 只能匹配 URI 路径,漏掉所有 query 参数 - ❌ 错误:
if ($request_body ~* 'union') { return 403; }→ 在 phpEnv/Nginx 精简版中无效 - ✅ 正确:只依赖
$args和$request_uri,两者覆盖绝大多数显性注入入口
补充基础防护:隐藏版本、限制方法、封禁 UA
SQL 注入只是入口之一,建议一并加几条轻量但有效的规则:
- 禁止危险 HTTP 方法:
if ($request_method !~ ^(GET|HEAD|POST|OPTIONS)$) { return 405; } - 屏蔽已知恶意 UA:
if ($http_user_agent ~* "sqlmap|nmap|wget|curl") { return 403; } - 隐藏 Nginx 版本:
server_tokens off;(加在 server 块顶部)
这些不增加性能负担,且能过滤掉大量自动化扫描行为。


















