必须使用 nginx-modsecurity(modsecurity v3 connector)动态模块并正确配置,否则 secrule 指令报错;需启用 secrequestbodyaccess on 及 fastcgi_pass_request_body/proxy_pass_request_body;推荐 owasp crs 但须调优,先 detectiononly 再启用;可加 map 快速拦截高危 sql 关键字。

不能直接在 Nginx 里照搬 Apache 的 ModSecurity 配置,必须用 nginx-modsecurity(即 ModSecurity v3 connector) 动态模块,并配合正确规则与解析设置,否则连 SecRule 指令都会报错。
确认环境与模块加载
ModSecurity 原生只支持 Apache,Nginx 必须通过官方提供的 v3 connector 编译集成。装完后运行:
-
nginx -V 2>&1 | grep -o modsecurity—— 输出含modsecurity才说明模块已编译进 Nginx - 若看到
unknown directive "SecRule",代表配置写错了位置,或模块根本没加载 - 不要尝试在 Nginx 配置中写
LoadModule security2_module,Nginx 不支持这种语法
启用请求体解析与基础防护
SQL 注入常藏在 POST 请求体中,而默认 Nginx + ModSecurity 不解析 body,导致规则失效:
- 在
modsecurity.conf中必须显式开启:SecRequestBodyAccess On - 若后端是 PHP-FPM,还需在
location ~ \.php$块中加:fastcgi_pass_request_body on; - 若用 proxy_pass,则加:
proxy_pass_request_body on; - 否则 CRS 规则里的
ARGS、REQUEST_BODY全为空,检测形同虚设
加载并调优 OWASP CRS 规则
推荐使用 OWASP ModSecurity Core Rule Set(CRS),但不能直接套用:
- 主防 SQL 注入的规则文件是
REQUEST-942-APPLICATION-ATTACK-SQLI.conf - CRS 默认关闭请求体解析,且对
multipart/form-data支持弱,上传带参数时易漏检 - 务必检查是否启用了异常分数阻断逻辑,例如:
SecRule TX:ANOMALY_SCORE "@gt 5" "id:1000,deny,status:403,msg:'SQLi detected'" - 先用
SecRuleEngine DetectionOnly运行几天,看日志再切到On,避免误杀order by id等合法语句
补充轻量级兜底拦截(防绕过)
ModSecurity 启动慢、压测有延迟(单请求多耗 5–15ms),建议在它前面加一层快速过滤:
- 用
map提前标记高危参数:map $args $sql_flag {<br> ~*[\"'`;\(\)\/\*%00] 1;<br> ~*(select|union|insert|update|delete|drop|sleep|benchmark) 1;<br> default 0;<br> } - 再在
server或location中:if ($sql_flag = 1) { return 403; } - 注意:只匹配
$args和$request_uri,$request_body在普通配置中不可读 - 正则用
~*(忽略大小写),避免漏掉UnIoN SeLeCt这类变形











