Nginx 正则拦截 SQL 注入仅能基于 $args 和 $request_uri 过滤明文特征,无法解析语义或读取 POST 体;应使用 b 边界匹配、编码字符如 %20OR%20,并避免 if 误配、rewrite 替代 return 403 等常见错误;根本防护需 PDO 预处理、最小权限账号及禁用危险函数。
直接在 Nginx 配置中加正则规则拦截 SQL 注入,只能拦住 URL 和查询参数里“明摆着”的攻击特征(比如 union select、' or '1'='1),不能解析 SQL 语义,也看不到 POST 请求体里的内容。它不是万能盾,而是最外层的一道轻量筛子。
Nginx 默认拿不到 $request_body,所以所有规则必须基于以下两个变量设计:
id=1%20or%201=1 → 匹配 or 1=1)/api?id=1%20union%20select → 要匹配 %20union%20select 或 union[[:space:]]+select)别写 if ($request_body ~ ...) —— 普通配置下它为空,规则无效。
放在 server 或具体 location 块内,用 return 403 终止请求:
if ($args ~* "(%27)|(')|(--)|(%23)|(#)|b(select|union|insert|update|delete|drop|exec|declare)b") { return 403; }if ($request_uri ~* "(%20OR%20|%20AND%20|/*|*/|;s*(select|union)s+from)") { return 403; }关键点:
• 用 b 匹配单词边界,避免误伤 user_id 这类字段
• %20OR%20 比 OR 更可靠,因空格常被编码
• 不匹配 order by、limit 等合法关键词
这些错误会让规则形同虚设:
if 写在 http 块顶层,没限定作用域,导致规则不生效或重复触发location ~ .php$ 里写规则,但攻击请求走的是 /index.php?id=...,$args 已解码,而正则却按 raw 字符匹配rewrite ... break 替代 return 403,可能被重定向绕过比折腾 Nginx 规则更有效、更根本的防护:
bindValue() 绑定,杜绝拼接 SQLSELECT, INSERT),禁用 DROP、EXEC 等高危操作eval()、system()、exec()、passthru()
不复杂但容易忽略