CDN 与 WAF 精讲教程 / 第07章 WAF 规则详解
第07章 WAF 规则详解
本章深入 WAF 规则的设计与管理,涵盖正则规则编写、自定义规则开发、规则优先级体系和白名单管理策略。
7.1 规则分类体系
7.1.1 WAF 规则分层
┌──────────────────────────────────────────────────────────────┐
│ WAF 规则分层体系 │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Layer 1: 基础防护规则 (默认开启) │ │
│ │ ├── 已知漏洞利用签名 │ │
│ │ ├── OWASP CRS 核心规则 │ │
│ │ └── 基础 DDoS 防护 │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Layer 2: 增强防护规则 (按需开启) │ │
│ │ ├── 严格输入验证 │ │
│ │ ├── 敏感数据泄露防护 │ │
│ │ └── 高级 Bot 检测 │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Layer 3: 自定义规则 (业务相关) │ │
│ │ ├── 业务逻辑防护 │ │
│ │ ├── API 特定规则 │ │
│ │ └── 虚拟补丁 │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Layer 4: 白名单规则 (覆盖/豁免) │ │
│ │ ├── IP 白名单 │ │
│ │ ├── URL 白名单 │ │
│ │ └── 规则 ID 豁免 │ │
│ └──────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
7.1.2 规则类型分类
| 类型 | 说明 | 示例 |
|---|---|---|
| 签名规则 | 匹配已知攻击模式 | SQL 关键字、XSS 标签 |
| 正则规则 | 正则表达式匹配 | 复杂注入模式 |
| 语义规则 | 语法分析 | SQL 语法树、HTML DOM |
| 行为规则 | 频率/模式分析 | 异常请求频率 |
| 评分规则 | 累计异常评分 | 多条低分规则叠加触发 |
| 复合规则 | AND/OR 条件组合 | 特定路径 + 特定参数 |
7.2 正则规则编写
7.2.1 常用正则模式
# 注入攻击检测正则模式
# SQL 注入基础模式
SQL_INJECTION_PATTERNS:
- '(?i)(union\s+select)' # UNION SELECT
- '(?i)(select\s+.*\s+from)' # SELECT ... FROM
- '(?i)(insert\s+into\s+.*\s+values)' # INSERT INTO
- '(?i)(delete\s+from)' # DELETE FROM
- '(?i)(drop\s+(table|database))' # DROP TABLE/DATABASE
- '(?i)(or\s+\d+\s*=\s*\d+)' # OR 1=1
- '(?i)(\'\s*(or|and)\s+\'?\w)' # ' OR 'a'='a
- '(?i)(;\s*(drop|alter|create)\s)' # ; DROP / ; ALTER
- '(?i)(/\*.*\*/)' # SQL 注释
- '(?i)(--\s|#\s)' # SQL 注释
# XSS 攻击检测模式
XSS_PATTERNS:
- '(?i)<\s*script' # <script 标签
- '(?i)javascript\s*:' # javascript: 协议
- '(?i)on(load|error|click|mouse|focus|blur)\s*=' # JS 事件处理器
- '(?i)<\s*(img|iframe|embed|object|svg)\s' # 危险 HTML 标签
- '(?i)expression\s*\(' # CSS expression()
- '(?i)vbscript\s*:' # vbscript: 协议
- 'document\.(cookie|write|location)' # DOM 操作
- '(?i)eval\s*\(' # eval()
- '(?i)<\s*svg\s+on\w+' # SVG 事件
# 路径遍历
PATH_TRAVERSAL_PATTERNS:
- '\.\./' # ../
- '\.\.\\' # ..\
- '(?i)%2e%2e[/\\]' # 编码的 ../
- '(?i)(etc|proc|var|usr)[/\\](passwd|shadow|log)' # 敏感路径
# 命令注入
COMMAND_INJECTION_PATTERNS:
- '[;&|`$]\s*(cat|ls|id|whoami|uname|curl|wget)' # 命令拼接
- '(?i)\$\(.*\)' # $(command)
- '(?i)`.*`' # `command`
7.2.2 正则编写最佳实践
# ❌ 错误示例:过于宽泛的正则
r"select" # 会误报 "select your country"
# ❌ 错误示例:过于复杂的正则(灾难性回溯)
r"(a+)+b" # 正则表达式拒绝服务 (ReDoS)
# ✅ 正确示例:精确匹配
r"(?i)union\s+(all\s+)?select\s+" # 匹配 UNION [ALL] SELECT 后跟空格
# ✅ 正确示例:使用边界限定
r"(?i)\bunion\b.*\bselect\b" # 使用单词边界
# ✅ 正确示例:限定长度防止 ReDoS
r"(?i)union\s+select\s+.{1,200}from" # 限定中间内容长度
7.2.3 正则性能优化
| 策略 | 说明 | 效果 |
|---|---|---|
| 使用固定字符串前缀 | 先做字符串匹配再做正则 | 减少正则引擎调用 |
| 避免回溯 | 使用原子组 (?>) 或占有量词 | 防止 ReDoS |
| 限定匹配长度 | .{1,1000} 而非 .* | 控制最大回溯量 |
| 预编译正则 | 编译时生成 DFA/NFA | 运行时零编译开销 |
| 使用 Aho-Corasick | 多模式字符串匹配 | O(n) 时间复杂度 |
7.3 自定义规则开发
7.3.1 ModSecurity 自定义规则
# 自定义规则示例
# 规则1: 拦截特定恶意 IP 段访问 /api/payment
SecRule REMOTE_ADDR "@ipMatch 192.168.100.0/24" \
"id:10001,\
phase:1,\
chain,\
block,\
msg:'Blocked malicious IP accessing payment API',\
severity:'CRITICAL'"
SecRule REQUEST_URI "@beginsWith /api/payment" ""
# 规则2: 拦截请求体过大的 POST 请求(CC 攻击特征)
SecRule REQUEST_METHOD "@streq POST" \
"id:10002,\
phase:1,\
chain,\
block,\
msg:'POST request with abnormal body size'"
SecRule REQUEST_HEADERS:Content-Length "@gt 10485760" ""
# 规则3: 检测 JSON 参数中的 SQL 注入
SecRule REQUEST_HEADERS:Content-Type "@contains application/json" \
"id:10003,\
phase:2,\
chain,\
block,\
msg:'SQL injection in JSON body'"
SecRule REQUEST_BODY "@rx (?i)(union\s+select|drop\s+table)" ""
# 规则4: 防止敏感文件访问
SecRule REQUEST_URI "@rx (?i)\.(git|svn|env|bak|sql|log)$" \
"id:10004,\
phase:1,\
block,\
msg:'Access to sensitive file blocked',\
severity:'HIGH',\
tag:'data-leakage'"
# 规则5: 拦截空 User-Agent(爬虫特征)
SecRule REQUEST_HEADERS:User-Agent "@streq ''" \
"id:10005,\
phase:1,\
block,\
msg:'Empty User-Agent blocked',\
severity:'WARNING'"
# 规则6: 速率限制 - 同一 IP 每分钟最多 100 次请求
SecAction \
"id:10006,\
phase:1,\
nolog,\
pass,\
setvar:ip.req_counter=+1,\
expirevar:ip.req_counter=60"
SecRule IP:REQ_COUNTER "@gt 100" \
"id:10007,\
phase:1,\
block,\
msg:'Rate limit exceeded: %{REMOTE_ADDR}',\
severity:'WARNING'"
7.3.2 Cloudflare 自定义规则 (Custom Rules)
# Cloudflare 规则表达式语法 (Wire Filter 语法)
# 规则1: 拦截非预期 HTTP 方法
(http.request.method in {"PUT" "DELETE" "PATCH"}) and
(not http.request.uri.path contains "/api/")
→ Block
# 规则2: 拦截包含 SQL 注入特征的请求
(http.request.uri.query contains "union" and http.request.uri.query contains "select")
or
(http.request.uri.query matches "(?i)'\\s*(or|and)\\s+\\d+\\s*=\\s*\\d+")
→ Block
# 规则3: 管理后台仅允许办公 IP
(http.request.uri.path contains "/admin") and
(not ip.src in {203.0.113.0/24 198.51.100.0/24})
→ Block
# 规则4: 敏感文件访问
(http.request.uri.path matches "\\.(env|git|svn|bak|sql|log)$")
→ Block
# 规则5: API 速率限制
(http.request.uri.path matches "^/api/v\\d+/") and
(rate(1m) > 120)
→ Managed Challenge
# 规则6: 地域封锁
(http.request.uri.path contains "/api/v1/") and
(ip.geoip.country in {"KP" "IR" "SY"})
→ Block
7.3.3 规则开发流程
规则开发生命周期:
┌──────────────┐
│ 1. 需求分析 │ 识别威胁 / 分析攻击日志
└──────┬───────┘
▼
┌──────────────┐
│ 2. 规则编写 │ 正则/条件表达式
└──────┬───────┘
▼
┌──────────────┐
│ 3. 测试验证 │ 测试攻击向量 + 正常请求
│ │ 确保零误报
└──────┬───────┘
▼
┌──────────────┐
│ 4. 监控模式 │ 上线但不拦截(1-2 周)
│ (Log Only) │ 观察误报和漏报
└──────┬───────┘
▼
┌──────────────┐
│ 5. 拦截模式 │ 确认无误报后启用拦截
└──────┬───────┘
▼
┌──────────────┐
│ 6. 持续优化 │ 根据新攻击向量迭代
└──────────────┘
7.4 规则优先级
7.4.1 优先级体系
规则执行顺序(从高到低):
┌──────────────────────────────────────────┐
│ 优先级 1: 全局白名单 (IP/ASN 级) │ 最先执行,直接放行
├──────────────────────────────────────────┤
│ 优先级 2: 路径白名单 (/health, /ping) │ 健康检查等免检路径
├──────────────────────────────────────────┤
│ 优先级 3: 规则 ID 白名单 │ 特定规则豁免
├──────────────────────────────────────────┤
│ 优先级 4: 速率限制规则 │ CC 防护、暴力破解
├──────────────────────────────────────────┤
│ 优先级 5: 基础攻击检测 (CRS) │ SQL 注入、XSS 等
├──────────────────────────────────────────┤
│ 优先级 6: 增强攻击检测 │ 复杂绕过、编码攻击
├──────────────────────────────────────────┤
│ 优先级 7: 自定义业务规则 │ 业务逻辑防护
├──────────────────────────────────────────┤
│ 优先级 8: 行为分析规则 │ ML/异常检测
├──────────────────────────────────────────┤
│ 优先级 9: 默认放行 │ 兜底策略
└──────────────────────────────────────────┘
7.4.2 规则评分机制
ModSecurity CRS 评分机制:
单条规则触发时记录评分,累计超过阈值才拦截。
示例:
┌──────────────────────────────────────────────────────┐
│ 请求: GET /search?q=<script>alert(1)</script>&id=1' │
│ │
│ 规则 941100 (XSS): +5 分 │
│ 规则 942100 (SQLi): +5 分 │
│ 总分: 10 分 │
│ 阈值: 5 分 │
│ │
│ 判定: 10 > 5 → 拦截 ✅ │
└──────────────────────────────────────────────────────┘
优势:
- 单个低分规则不拦截(减少误报)
- 多个低分组合触发拦截(检测复杂攻击)
- 可按业务调整阈值
7.4.3 评分配置示例
# ModSecurity CRS 评分阈值配置
# 入侵检测评分阈值
SecAction "id:900110,phase:1,pass,t:none,setvar:tx.inbound_anomaly_score_threshold=5"
SecAction "id:900110,phase:1,pass,t:none,setvar:tx.outbound_anomaly_score_threshold=4"
# 各攻击类别评分
# SQL 注入: 严重度 critical → 5 分
SecRule ARGS "@detectSQLi" "id:942100,setvar:'tx.sql_injection_score=+%{tx.critical_anomaly_score}'"
# XSS: 严重度 critical → 5 分
SecRule ARGS "@detectXSS" "id:941100,setvar:'tx.xss_score=+%{tx.critical_anomaly_score}'"
# 路径遍历: 严重度 critical → 5 分
SecRule REQUEST_URI "@rx \.\./" "id:930100,setvar:'tx.anomaly_score=+%{tx.critical_anomaly_score}'"
7.5 白名单管理
7.5.1 白名单类型
| 类型 | 范围 | 风险 | 适用场景 |
|---|---|---|---|
| IP 白名单 | 特定 IP/段 | 中 | 办公网、合作伙伴 |
| URL 白名单 | 特定路径 | 低 | 健康检查、Webhook |
| 规则 ID 白名单 | 跳过特定规则 | 中 | 已知误报处理 |
| 参数白名单 | 特定参数名/值 | 高 | 业务特殊参数 |
| UA 白名单 | 特定 User-Agent | 高 | 搜索引擎爬虫 |
| ASN 白名单 | 特定 AS 号 | 低 | CDN 回源、API 合作方 |
7.5.2 白名单配置
# ModSecurity 白名单
# IP 白名单
SecRule REMOTE_ADDR "@ipMatch 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16" \
"id:10000,phase:1,pass,nolog,ctl:ruleEngine=Off"
# URL 白名单 - 健康检查端点
SecRule REQUEST_URI "@streq /health" \
"id:10001,phase:1,pass,nolog,ctl:ruleEngine=Off"
# 规则 ID 白名单 - 跳过特定规则(已知误报)
SecRule REMOTE_ADDR "@ipMatch 198.51.100.0/24" \
"id:10002,phase:1,pass,nolog,ctl:ruleRemoveById=941100"
# 搜索引擎爬虫白名单
SecRule REQUEST_HEADERS:User-Agent "@pm Googlebot Bingbot" \
"id:10003,phase:1,pass,nolog,ctl:ruleEngine=DetectionOnly"
7.5.3 白名单安全审计
白名单审计清单:
✅ 白名单有明确的业务理由
✅ 白名单范围尽可能小(最小权限原则)
✅ 定期审查白名单(至少每季度一次)
✅ 记录白名单变更日志
✅ IP 白名单使用 CIDR 而非单个 IP
✅ 临时白名单有自动过期机制
✅ 不在白名单中硬编码 IP(使用变量/配置文件)
❌ 常见错误:
├── 对整个 0.0.0.0/0 放行
├── 白名单无文档、无审查
├── 临时白名单变成永久
├── 白名单范围过大(如 /16 段)
└── 基于 User-Agent 的白名单(易伪造)
7.6 规则管理工具
7.6.1 开源工具
| 工具 | 用途 | 地址 |
|---|---|---|
| OWASP CRS | 标准 WAF 规则集 | github.com/coreruleset/coreruleset |
| CRS Paranoia Mode | 分级严格度 | 4 级(PL0-PL3) |
| ftw | 规则测试框架 | github.com/coreruleset/ftw |
| go-ftw | 规则测试(Go 版) | github.com/coreruleset/go-ftw |
| Coraza | Go 语言 WAF 引擎 | github.com/corazawaf/coraza |
7.6.2 CRS Paranoia 模式
| 级别 | 规则数量 | 误报率 | 适用场景 |
|---|---|---|---|
| PL0 | ~100 条 | 极低 | 最基础防护 |
| PL1 | ~200 条 | 低 | 一般网站(推荐) |
| PL2 | ~350 条 | 中 | 安全敏感业务 |
| PL3 | ~500 条 | 高 | 高安全要求(需细调白名单) |
7.7 注意事项
⚠️ 正则性能:复杂正则可能导致 ReDoS(正则拒绝服务),上线前需用 recheck 等工具测试性能。
⚠️ 编码绕过:攻击者使用 URL 编码、Unicode、Base64 等方式绕过 WAF。规则应覆盖多种编码形式。
⚠️ 规则冲突:多条规则可能对同一请求产生矛盾的结论。应建立明确的优先级体系。
⚠️ 规则变更管理:所有规则变更应有审批流程、版本控制和回滚计划。
7.8 扩展阅读
- OWASP CRS Documentation — CRS 官方文档
- ModSecurity Handbook — ModSecurity 权威指南
- Regular Expression Denial of Service — ReDoS 攻击详解
- Cloudflare Ruleset Engine — Cloudflare 规则引擎
本章小结
| 主题 | 核心要点 |
|---|---|
| 规则分类 | 基础 → 增强 → 自定义 → 白名单,四层体系 |
| 正则规则 | 精确匹配 + 边界限定 + 防 ReDoS |
| 自定义规则 | 需求分析 → 编写 → 测试 → 监控 → 拦截 |
| 优先级 | 白名单 > 速率限制 > 攻击检测 > 行为分析 |
| 白名单 | 最小范围 + 定期审计 + 文档记录 |
下一章:第08章 Bot 管理 →