ModSecurity 拦截 SQL 注入需确保请求体解析开启、解码归一化到位、CRS 初始化规则优先加载;应以 CRS 为主,针对性补充自定义规则,并通过日志观察、先 log 后 block、评分机制保障精准拦截。

直接用 ModSecurity 拦截 SQL 注入,关键不是堆规则,而是让规则真正“看得清、判得准、拦得住”。光写几条含 union select 的正则,90% 的真实攻击都会绕过——因为攻击载荷早被 URL 编码、大小写混用、注释分隔、空格替换等手法变形了。
基础配置必须先到位
规则再强,环境没配好也白搭。以下三项不启用,绝大多数 POST 型注入(比如登录框输 admin' OR '1'='1)根本进不了检测逻辑:
-
开启请求体解析:加
SecRequestBodyAccess On,否则 ModSecurity 默认不读 POST 数据,只看 URL 参数 -
启用解码与归一化:在规则中显式调用
t:urlDecodeUni,t:lowercase,确保%27union%20select和UNION SELECT都能被统一匹配 -
加载顺序不能错:CRS 的初始化规则(如
REQUEST-901-INITIALIZATION.conf)必须在 SQLI 规则前加载,否则ARGS、REQUEST_COOKIES等变量为空,规则全失效
优先用 CRS,再补漏点
别从零手写整套规则。OWASP ModSecurity CRS 已覆盖主流注入模式(布尔型、报错型、时间盲注、union-based 等),生产环境应以 CRS 为主干,仅对漏报场景补充自定义规则:
- 确认 CRS 已启用且版本不低于 v3.3(推荐 v4.x),尤其检查
REQUEST-942-APPLICATION-ATTACK-SQLI.conf是否加载 - 针对业务特有参数(如
/api/v2/order?ref_id=xxx)可单独加规则,避免全局规则误杀 - 补充规则示例(放在
custom-sqli.conf中):SecRule ARGS "@rx \b(?:and|or|x?or|not)\b\s+\d+\s*=\s*\d+" "id:1001,phase:2,block,msg:'SQLi: Boolean-based number injection',t:urlDecodeUni,t:lowercase"
应对常见绕过手法
攻击者不会老老实实输 ' or 1=1--,真实流量中这些变形高频出现,规则需主动适配:
-
注释符+换行绕过:如
id=1%23foo%0D%0Aunion%20select(#+ CRLF),规则里要匹配(?:--|%23|/\*)\s*[\r\n\t ]*后接关键字 -
双写/大小写混用:如
unioon selselect或UnIoN SeLeCt,靠t:lowercase统一处理后再匹配 -
空格替换为其他分隔符:如
union%09select(Tab)、union%0aselect(换行),用t:urlDecodeUni解码后,正则中用\s+或[[:space:]]+匹配任意空白
上线前必须做的三件事
规则上线不是“加完就 block”,否则可能大面积误拦截导致业务中断:
-
日志全开:设置
SecAuditLogRelevantStatus "^(?:[4-5]|(?:2|3)[0-9])",确保所有 2xx–5xx 请求都进审计日志 -
先 log 后 block:新规则初期用
log,tag:'sqli-test'替代block,观察一周真实流量匹配情况再切到阻断 - 引入评分机制:单条规则触发只记 3 分,累计 ≥5 分才拦截,避免单一变形触发即封禁正常用户









