modsecurity 需显式启用模块加载、secrequestbodyaccess、secruleengine on 及 deny 动作才能拦截 sql 注入;缺一即失效,调试须优先验证 nginx -v、请求体透传与规则引擎配置。

ModSecurity 本身不拦截 SQL 注入,CRS 规则集默认只记录不阻断;必须显式启用请求体解析、透传、规则引擎和 deny 动作,缺一即失效。
确认 nginx 真正加载了 ModSecurity 模块
很多配置看似正确却完全不生效,根源是模块压根没加载成功。
- 执行
nginx -V 2>&1 | grep -o modsecurity,必须有非空输出(如--add-dynamic-module=../nginx-modsecurity),否则所有SecRule指令都会报unknown directive -
ldd $(which nginx) | grep modsecurity无输出,说明动态链接失败,load_module路径写错或 so 文件权限不对 - 常见错误:路径写成
modules/ngx_http_modsecurity_module.so,但实际在/usr/lib/nginx/modules/ngx_http_modsecurity_module.so,少一个斜杠就静默失败
必须开启 SecRequestBodyAccess 并透传原始 body
OWASP CRS 的 REQUEST-942-APPLICATION-ATTACK-SQLI.conf 默认检查 REQUEST_BODY 和 ARGS_POST,而 Nginx 默认不读取也不转发 POST body。
-
SecRequestBodyAccess On必须写在modsecurity.conf全局配置中,不能只放在location块里 - 后端是 PHP-FPM:对应
location ~ \.php$中加fastcgi_pass_request_body on; - 后端是 proxy_pass(如 Node.js):对应
location中加proxy_pass_request_body on; - 对
multipart/form-data请求,Nginx connector 解析不完整,建议加兜底规则:SecRule REQUEST_BODY "@rx (?i)(union\s+select|select\s+.*\s+from)" "id:1002,phase:2,deny,status:403,msg:'Raw SQLi in body'"
规则引擎与动作必须设为阻断模式
CRS 默认策略是 SecRuleEngine DetectionOnly,日志里全是匹配记录,但请求照常通过。
-
SecRuleEngine On必须写在server或location块内,不能只放在http{}顶层(否则不生效) - 检查 CRS 规则文件中是否含
deny,status:403,例如REQUEST-942-APPLICATION-ATTACK-SQLI.conf中的id:942100规则末尾必须带该动作 - 首次上线务必先用
DetectionOnly运行 3–5 天,观察modsec_audit.log:正常order by id、limit 10都可能触发误报 - 若业务大量用
LIKE '%xxx%',需临时禁用id:942100(LIKE 检测规则),否则搜索功能全 403
绕过防御的常见手法及补救
真实攻击者不会发 union select,而是用大小写、注释、URL 编码等组合绕过——只靠 CRS 默认正则远远不够。
- 正则必须启用转换链:
t:urlDecodeUni,t:lowercase,否则sel%65ct或UNI/**/ON SEL/**/ECT直接漏过 - 不要只写
union\s+select,应覆盖空格、制表符、换行、注释符:(?i)union[\s%09%0a%0b%0c%0d\xA0](?:/\*\*\/|--+|#)?\s+select - 加一层
map快速兜底:map $args $sql_flag { ~*[\"'`;\(\)\/\*%00] 1; ~*(select|union|insert|update|delete|drop|sleep|benchmark) 1; default 0; },再用if ($sql_flag = 1) { return 403; } -
map只能匹配 GET 参数,POST body 仍依赖前面的SecRequestBodyAccess配置,两者缺一不可
最易被忽略的点:规则生效依赖完整的请求处理链路——从模块加载、请求体读取、变量注入、转换函数执行,到最终动作触发。任何一个环节断开,防御就形同虚设。调试时别只盯着规则内容,先确认 nginx -V、SecRequestBodyAccess、fastcgi_pass_request_body 三者是否全部到位。











