modsecurity深度防护依赖自定义规则链而非默认配置,需结合请求生命周期、变量定位、多阶段匹配与动作组合;例如电商下单接口通过chain串联uri、参数格式、敏感词及ip频次检查,并利用t转换函数和持久化变量实现精准防御。

ModSecurity 本身不提供“开箱即用”的业务防护,真正实现深度过滤靠的是自定义规则链(SecRule + chain),而不是简单开关或套用默认 CRS。关键在于理解请求生命周期、精准定位变量、分阶段匹配并组合动作。
明确业务特征,找准切入变量
自定义防护链的前提是清楚你要保护的接口行为。比如电商下单接口 /api/order/submit 要求:
-
参数必须含
user_id(整数)、product_ids[](逗号分隔数字列表)、total_amount(正浮点数) -
禁止出现
script、select.*from、union all select等敏感模式 - IP 频次限制:5 秒内同一 IP 提交超 3 次即临时封禁
对应需锁定的变量包括:REQUEST_URI、ARGS:user_id、ARGS:product_ids、ARGS:total_amount、REMOTE_ADDR,以及请求体(REQUEST_BODY)——若用 JSON 提交,还需开启 SecRequestBodyAccess On 和 JSON 解析支持。
用 chain 构建多条件串联规则
单条规则只能查一个变量,而真实攻击常分散在多个字段中。用 chain 可把多个检查串成一条逻辑链,全部满足才触发动作。例如防恶意订单构造:
SecRule REQUEST_URI "@streq /api/order/submit" "id:1002,phase:2,pass,nolog,chain"
SecRule ARGS:user_id "!@rx ^\d+$" "t:none,msg:'Invalid user_id format'"
SecRule ARGS:total_amount "!@rx ^\d+(\.\d{1,2})?$" "t:none,msg:'Invalid amount format'"
SecRule ARGS:product_ids "!@rx ^\d+(,\d+)*$" "t:none,msg:'Invalid product_ids list'"
这条规则含义是:只有当 URI 是提交路径 且 user_id 不是纯数字 且 金额格式非法 且 商品 ID 列表含非数字字符时,整条链才命中,并记录告警。注意 phase:2 表示在请求体解析后执行,确保能读取 POST 数据。
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
结合变量转换与上下文判断
原始参数常被编码或混淆,直接匹配易漏报。ModSecurity 提供 t: 转换函数还原语义。例如防御 URL 编码绕过:
-
t:urlDecodeUni:解码 Unicode 编码(如%u003cscript%u003e→<script></script>) -
t:htmlEntityDecode:解码 HTML 实体(如<script>→<script></script>) -
t:lowercase:统一转小写,避免大小写绕过
实际规则示例(防 XSS 注入):
SecRule REQUEST_URI "@streq /api/comment/post" "id:1003,phase:2,deny,status:403,msg:'XSS attempt detected',log,tag:xss,chain"
SecRule ARGS:content "@rx ]*>" "t:urlDecodeUni,t:htmlEntityDecode,t:lowercase"
这里先对 content 参数做三重清洗,再用正则检测标签结构,比单纯查 <script></script> 更可靠。
动态状态控制与临时封禁
针对高频异常行为,不能只 deny 当前请求,还要标记客户端并短期阻断。利用 ModSecurity 的持久化变量(ip、session、global)实现:
# 统计 5 秒内同一 IP 的异常提交次数
SecRule REQUEST_URI "@streq /api/order/submit" "id:1004,phase:2,pass,nolog,tag:abuse,chain"
SecRule TX:anomaly_score "@gt 0" "t:none,setvar:ip.block_counter=+1,expirevar:ip.block_counter=5"
<h1>若计数 ≥3,则拒绝后续请求</h1><p>SecRule IP:BLOCK_COUNTER "@ge 3" "id:1005,phase:1,deny,status:429,msg:'Rate limit exceeded',log"
</p>
注意:expirevar 设定变量自动过期时间(秒),phase:1 在请求头阶段就拦截,节省资源。这类策略需配合 SecDataDir(如 /var/cache/modsecurity)启用持久化存储。










