土法炼钢兴趣小组的算法知识备份

【网络工程】WAF 工程:规则设计、误报控制与绕过防御

文章导航

分类入口
network
标签入口
#waf#modsecurity#owasp-crs#web-security#application-firewall

目录

上一篇讲了 DDoS 防御——它解决的是”把流量打到你扛不住”的问题。WAF(Web Application Firewall,Web 应用防火墙)解决的是另一类问题:攻击者的流量不大,但每一个请求都可能携带恶意 payload——SQL 注入、XSS、命令注入、路径遍历。WAF 的核心挑战不是性能,而是精度:怎么在不影响正常业务的前提下拦截恶意请求。

一、WAF 基础概念

1.1 WAF 的工作位置

WAF 工作在 HTTP 层(OSI 第七层),检查 HTTP 请求和响应的内容。它可以部署在不同的位置:

客户端
  │
  ↓
┌─────────────┐
│ CDN / 云 WAF │ ← 位置 1:云端(Cloudflare WAF、AWS WAF)
└──────┬──────┘
       ↓
┌─────────────┐
│ 反向代理 WAF │ ← 位置 2:反向代理(ModSecurity + Nginx)
└──────┬──────┘
       ↓
┌─────────────┐
│  负载均衡器   │ ← 位置 3:嵌入 LB(F5 ASM)
└──────┬──────┘
       ↓
┌─────────────┐
│  应用服务器   │ ← 位置 4:应用内置(RASP)
└─────────────┘

各部署位置的工程权衡

部署位置 优点 缺点
云端 WAF 零运维、全球分布、大规模规则库 依赖第三方、无法深度定制、延迟
反向代理 WAF 灵活定制、开源可控 运维成本高、需要维护规则
嵌入 LB 一体化管理、性能好 厂商锁定、授权费昂贵
RASP 上下文感知强、零误报 侵入应用代码、性能开销

1.2 WAF 的检测模型

WAF 的检测逻辑分为两大类:

正向模型(Allowlist / Positive Model):定义”合法请求长什么样”,不匹配的全部拦截。精度极高但配置复杂——需要为每个 API 端点定义合法参数的类型、长度、字符集。

负向模型(Blocklist / Negative Model):定义”恶意请求长什么样”,匹配签名/规则的拦截。配置简单但容易被绕过——攻击者可以通过编码、混淆等方式绕过规则。

大多数 WAF 以负向模型为主,配合正向模型的辅助检查。OWASP CRS 就是负向模型的代表。

二、OWASP CRS 规则体系

2.1 CRS 概述

OWASP Core Rule Set(CRS)是最广泛使用的开源 WAF 规则集。它为 ModSecurity 引擎设计,但概念适用于所有 WAF。CRS 目前的最新版本为 4.x,包含约 200 条核心规则,覆盖 OWASP Top 10 中的大部分攻击类型。

CRS 的分层结构

CRS 规则编号范围
┌──────────────────────────────────────────────────┐
│ 900xxx  初始化与配置                               │
│ 901xxx  请求初始化                                 │
│ 910xxx  Scanner/Bot 检测                          │
│ 911xxx  Method Enforcement                        │
│ 912xxx  DOS Protection                            │
│ 913xxx  Scanner Detection                         │
│ 920xxx  Protocol Enforcement (请求格式验证)         │
│ 921xxx  Protocol Attack (HTTP 协议攻击)            │
│ 930xxx  Local File Inclusion (LFI)                │
│ 931xxx  Remote File Inclusion (RFI)               │
│ 932xxx  Remote Code Execution (RCE / 命令注入)     │
│ 933xxx  PHP Injection                             │
│ 934xxx  Node.js Injection                         │
│ 941xxx  XSS (跨站脚本)                             │
│ 942xxx  SQL Injection (SQL 注入)                   │
│ 943xxx  Session Fixation                          │
│ 944xxx  Java Attacks                              │
│ 949xxx  Blocking Evaluation                       │
│ 950xxx  Outbound (响应检查)                        │
│ 959xxx  Outbound Blocking                         │
│ 980xxx  Correlation (关联分析)                      │
└──────────────────────────────────────────────────┘

2.2 CRS 的异常评分模型

CRS 使用异常评分(Anomaly Scoring)而非单规则阻断。每条规则匹配时给请求加一个”异常分数”,只有当总分超过阈值时才拦截。这大幅减少了单条规则误报导致的合法请求被拦截:

请求进入
   │
   ├── 规则 942100 匹配 → +5 分(SQL 注入特征)
   ├── 规则 941100 匹配 → +5 分(XSS 特征)
   ├── 规则 920350 匹配 → +2 分(Host 头 IP 格式)
   │
   总分 = 12
   │
   阈值 = 5 → 拦截
   阈值 = 10 → 拦截
   阈值 = 15 → 放行(累积不够)

异常分数级别

严重级别 默认分数 含义
CRITICAL 5 高置信度攻击(SQL 注入核心特征)
ERROR 4 中等置信度(可疑但有误报可能)
WARNING 3 低置信度(异常但可能合法)
NOTICE 2 信息级别(记录但几乎不影响评分)

配置阈值

# ModSecurity CRS 配置
# crs-setup.conf

# 入站异常评分阈值
# PL1 (Paranoia Level 1) = 5:只拦截高置信度攻击
# PL2 = 5:更多规则启用
# PL3 = 5:激进检测
# PL4 = 5:最严格(几乎不可用于生产)
SecAction "id:900110,phase:1,pass,\
    setvar:tx.inbound_anomaly_score_threshold=5,\
    setvar:tx.outbound_anomaly_score_threshold=4"

# Paranoia Level(偏执级别)
# PL1:基础规则,低误报(生产推荐起始值)
# PL2:增加规则,中误报
# PL3:激进检测,高误报
# PL4:研究级别,极高误报
SecAction "id:900000,phase:1,pass,\
    setvar:tx.paranoia_level=1"

2.3 ModSecurity 规则语法

ModSecurity 是最流行的开源 WAF 引擎。理解其规则语法是定制 WAF 策略的基础:

# ModSecurity 规则格式
# SecRule VARIABLES OPERATOR [ACTIONS]

# 示例:检测 SQL 注入
SecRule ARGS "@rx (?i)(union[\s/\*]+select|select[\s/\*]+.*from|insert[\s/\*]+into)" \
    "id:100001,\
     phase:2,\
     deny,\
     status:403,\
     log,\
     msg:'SQL Injection Detected',\
     severity:'CRITICAL',\
     tag:'attack-sqli'"

# 变量(VARIABLES)——检查请求的哪些部分
# ARGS           所有请求参数(GET + POST)
# ARGS_GET       GET 参数
# ARGS_POST      POST 参数
# REQUEST_URI    请求 URI
# REQUEST_BODY   请求体
# REQUEST_HEADERS 请求头
# REQUEST_COOKIES Cookie
# XML            XML 请求体(解析后)
# JSON           JSON 请求体(解析后)

# 操作符(OPERATOR)——怎么匹配
# @rx            正则表达式
# @pm            短语匹配(多关键词)
# @pmFromFile    从文件加载关键词列表
# @eq / @gt / @lt 数值比较
# @ipMatch       IP 地址/CIDR 匹配
# @contains      包含字符串
# @detectSQLi    libinjection SQL 注入检测
# @detectXSS     libinjection XSS 检测

# 动作(ACTIONS)——匹配后做什么
# deny           拦截
# pass           放行(用于记录)
# redirect       重定向
# setvar         设置变量(用于异常评分)
# chain          链式规则(AND 条件)

一个完整的自定义规则示例

# 检测命令注入——匹配请求参数中的 shell 命令字符
SecRule ARGS "@rx (?:;|\||`|\$\()" \
    "id:100010,\
     phase:2,\
     block,\
     capture,\
     t:none,\
     t:urlDecodeUni,\
     t:htmlEntityDecode,\
     t:compressWhiteSpace,\
     log,\
     msg:'Command Injection Attempt: %{MATCHED_VAR}',\
     logdata:'Matched Data: %{TX.0} in %{MATCHED_VAR_NAME}',\
     severity:'CRITICAL',\
     tag:'attack-rce',\
     tag:'OWASP_CRS',\
     setvar:'tx.anomaly_score_pl1=+%{tx.critical_anomaly_score}'"

# 注意 t: 开头的转换函数——它们在匹配前对输入做归一化处理
# urlDecodeUni: URL 解码(含 Unicode)
# htmlEntityDecode: HTML 实体解码
# compressWhiteSpace: 压缩空白字符
# 这些转换是防 WAF 绕过的关键

三、WAF 绕过与防御

WAF 绕过是安全攻防的核心议题。理解攻击者的绕过手法才能写出有效的规则。

3.1 编码绕过

原始 payload:  <script>alert(1)</script>

# URL 编码
%3Cscript%3Ealert(1)%3C%2Fscript%3E

# 双重 URL 编码
%253Cscript%253Ealert(1)%253C%252Fscript%253E

# Unicode 编码
%u003Cscript%u003Ealert(1)%u003C/script%u003E

# HTML 实体编码
&#60;script&#62;alert(1)&#60;/script&#62;

# 混合编码
%3Cscr%69pt%3Ealert(1)%3C/scr%69pt%3E

防御:在正则匹配前先做多层解码(归一化):

# ModSecurity 的多层转换
SecRule ARGS "@rx <script>" \
    "id:100020,\
     phase:2,\
     deny,\
     t:none,\
     t:urlDecodeUni,\          # URL 解码(含 Unicode)
     t:htmlEntityDecode,\      # HTML 实体解码
     t:jsDecode,\              # JavaScript 解码
     t:cssDecode,\             # CSS 解码
     t:utf8toUnicode,\         # UTF-8 转 Unicode
     t:lowercase,\             # 大小写归一化
     t:compressWhiteSpace"     # 空白压缩

3.2 SQL 注入绕过

-- 原始 payload
' OR 1=1 --

-- 注释分割
'/**/OR/**/1=1--

-- 大小写混淆
' oR 1=1 --

-- 等价函数替换
' OR ASCII(SUBSTRING(password,1,1))>64 --

-- 无空格
'OR'1'='1'

-- 科学计数法
' OR 1e0=1e0 --

-- 制表符替代空格
' OR\t1=1\t--

-- 多行注释嵌套
'/*!50000OR*/1=1--

-- JSON/XML 载体(WAF 可能不解析 body 格式)
{"query": "' OR 1=1 --"}

libinjection 防御

# CRS 使用 libinjection 的语义分析替代纯正则
# libinjection 将 SQL 片段标记化为 token 序列
# 例如 ' OR 1=1 -- 被标记为 s&1
# 其中 s=string, &=operator, 1=number

# ModSecurity 调用 libinjection
SecRule ARGS "@detectSQLi" \
    "id:942100,\
     phase:2,\
     block,\
     t:none,\
     t:urlDecodeUni,\
     t:removeNulls,\
     msg:'SQL Injection Attack Detected via libinjection',\
     severity:'CRITICAL'"

libinjection 的优势在于它不依赖正则表达式,而是对 SQL 语法做词法分析——编码和混淆无法改变 token 序列的语义特征。

3.3 XSS 绕过

<!-- 原始 payload -->
<script>alert(1)</script>

<!-- 事件处理器 -->
<img src=x onerror=alert(1)>
<svg onload=alert(1)>
<body onpageshow=alert(1)>

<!-- 不使用尖括号 -->
javascript:alert(1)
data:text/html,<script>alert(1)</script>

<!-- 模板注入 -->
{{constructor.constructor('return this')().alert(1)}}

<!-- 利用 DOM API -->
<a href="javascript:void(0)" onclick="this.href='javascript:alert(1)'">

<!-- SVG 内嵌 -->
<svg><script>alert(1)</script></svg>

<!-- 编码混淆 -->
<script>eval(atob('YWxlcnQoMSk='))</script>

3.4 协议层绕过

WAF 通常在 HTTP 解析后检查内容。如果 WAF 的 HTTP 解析行为与后端服务器不一致,就产生了绕过空间:

# Request Smuggling — WAF 和后端对 Content-Length 和
# Transfer-Encoding 的解析不一致

# CL.TE 攻击(WAF 看 Content-Length,后端看 Transfer-Encoding)
POST / HTTP/1.1
Host: target.com
Content-Length: 6
Transfer-Encoding: chunked

0

G

# WAF 认为 body 是 "0\r\n\r\nG" (6 字节),放行
# 后端按 chunked 解析,"0\r\n\r\n" 是终止标记
# "G" 被解析为下一个请求的开头

防御措施

# 拒绝同时携带 Content-Length 和 Transfer-Encoding 的请求
SecRule REQUEST_HEADERS:Transfer-Encoding "." \
    "chain,\
     id:100030,\
     phase:1,\
     deny"
SecRule REQUEST_HEADERS:Content-Length "." \
    "msg:'Request with both CL and TE headers'"

# 拒绝异常的 Transfer-Encoding 值
SecRule REQUEST_HEADERS:Transfer-Encoding "!@rx ^chunked$" \
    "id:100031,\
     phase:1,\
     deny,\
     msg:'Invalid Transfer-Encoding'"

3.5 WAF 绕过防御总结

绕过类型 攻击手法 防御措施
编码绕过 URL/HTML/Unicode 编码 多层归一化(t:urlDecodeUni + t:htmlEntityDecode)
大小写绕过 SeLeCtScRiPt 小写归一化(t:lowercase)
注释分割 SEL/**/ECT 去注释 + 语义分析(libinjection)
空白替换 Tab、换行替代空格 空白压缩(t:compressWhiteSpace)
等价替换 CHAR(65) 替代 'A' 语义分析 + 函数黑名单
协议走私 CL/TE 不一致 拒绝歧义请求
分块传输 Chunked 拆分 payload 完整重组后再检查
多部分绕过 multipart/form-data 嵌套 完整解析 multipart body

四、误报控制

误报(False Positive)是 WAF 运维中最大的挑战。CRS 在 Paranoia Level 1 下典型误报率约 1–3%,但对于高流量网站,1% 的误报意味着每天数千个合法请求被拦截。

4.1 误报的常见来源

常见误报场景:

1. 富文本编辑器 — 用户输入包含 HTML 标签
   误匹配规则:941xxx (XSS)
   
2. 搜索查询 — 用户搜索 SQL 关键词
   例:"SELECT 语句怎么写"
   误匹配规则:942xxx (SQLi)
   
3. API JSON Body — JSON 值包含特殊字符
   例:{"code": "if (x > 0) { return; }"}
   误匹配规则:941xxx (XSS), 932xxx (RCE)
   
4. 长 URL / 大 Cookie — 正常业务但超出 WAF 默认限制
   误匹配规则:920xxx (Protocol)
   
5. 文件上传 — 上传内容包含可执行代码
   误匹配规则:930xxx (LFI), 932xxx (RCE)

4.2 规则排除策略

ModSecurity 提供三种规则排除方式:

# 方式 1:完全移除规则(简单但粗暴)
# 不推荐:移除整条规则意味着对所有请求都不检查
SecRuleRemoveById 942100

# 方式 2:按 URI 排除(推荐)
# 只对特定路径排除特定规则
SecRule REQUEST_URI "@beginsWith /api/editor" \
    "id:100040,\
     phase:1,\
     pass,\
     ctl:ruleRemoveTargetById=941100;ARGS:content,\
     ctl:ruleRemoveTargetById=941160;ARGS:content"
# 只对 /api/editor 端点的 content 参数排除 XSS 规则
# 其他端点和其他参数仍然受保护

# 方式 3:按参数排除(精确)
# 对特定参数排除特定规则,不限 URI
SecRuleUpdateTargetById 942100 "!ARGS:search_query"
# 所有请求的 search_query 参数不触发 SQL 注入规则 942100

4.3 渐进式部署流程

┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│  阶段 1       │     │  阶段 2       │     │  阶段 3       │
│  Detection   │ ──→ │  Tuning      │ ──→ │  Blocking    │
│  Only        │     │              │     │              │
│              │     │              │     │              │
│ • 只记录     │     │ • 分析日志    │     │ • 开启拦截    │
│ • 不拦截     │     │ • 排除误报    │     │ • 持续监控    │
│ • 收集数据   │     │ • 调整阈值    │     │ • 迭代优化    │
│              │     │              │     │              │
│ 时间:2-4周  │     │ 时间:2-4周   │     │ 持续运维      │
└──────────────┘     └──────────────┘     └──────────────┘

阶段 1:检测模式(Detection Only)

# ModSecurity 检测模式配置
SecRuleEngine DetectionOnly

# 所有规则只记录,不拦截
# 审计日志记录所有触发规则的请求
SecAuditEngine RelevantOnly
SecAuditLogParts ABCDEFHZ
SecAuditLog /var/log/modsec_audit.log
SecAuditLogType Serial

阶段 2:日志分析与误报排除

# 分析 ModSecurity 审计日志
# 统计触发最多的规则 ID
grep -oP 'id "\K\d+' /var/log/modsec_audit.log | \
    sort | uniq -c | sort -rn | head -20

# 统计被标记的 URI
grep -oP 'REQUEST_URI.*' /var/log/modsec_audit.log | \
    sort | uniq -c | sort -rn | head -20

# 查看特定规则的触发详情
grep -A 5 'id "942100"' /var/log/modsec_audit.log | head -50

阶段 3:逐步开启拦截

# 先用高阈值,逐步降低
# 第一周:阈值 20(只拦截明确攻击)
SecAction "id:900110,phase:1,pass,\
    setvar:tx.inbound_anomaly_score_threshold=20"

# 第二周:阈值 10
# 第三周:阈值 5(CRS 推荐值)

# 切换到拦截模式
SecRuleEngine On

4.4 误报率的量化监控

# Prometheus 指标设计
# prometheus-waf-metrics.yml
groups:
  - name: waf_metrics
    rules:
      # WAF 拦截率
      - record: waf:block_rate:5m
        expr: |
          rate(waf_requests_blocked_total[5m])
          / rate(waf_requests_total[5m])
      
      # 误报率(需要人工标注或自动验证)
      - alert: WAFHighBlockRate
        expr: waf:block_rate:5m > 0.05
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "WAF 拦截率超过 5%,可能存在误报问题"

五、正则 WAF vs 语义分析 WAF

5.1 正则 WAF 的局限

正则 WAF(如传统 ModSecurity + CRS)的核心问题:

  1. 正则灾难:复杂正则可能导致 ReDoS(正则拒绝服务),恶意构造的输入让正则引擎陷入指数级回溯
  2. 维护成本:规则库需要不断更新以应对新绕过手法
  3. 上下文缺失:正则不理解语法语义,只做字符串模式匹配
# ReDoS 示例
# 以下正则在处理特定输入时可能导致指数级回溯
# 正则: (a+)+$
# 输入: aaaaaaaaaaaaaaaaaaaX
# 回溯次数随 a 的数量指数增长

# ModSecurity 的缓解措施
# 设置正则匹配的时间限制
SecPcreMatchLimit 500000
SecPcreMatchLimitRecursion 500000

5.2 语义分析 WAF

语义分析 WAF 不使用正则,而是对输入做词法/语法分析,理解其”意图”:

传统正则 WAF:
  输入: "1' OR '1'='1"
  匹配: /OR\s+'.*'='.*'/i → 命中
  绕过: "1' || '1'like'1" → 可能不命中

语义分析 WAF:
  输入: "1' OR '1'='1"
  → SQL 词法分析
  → Token: [NUMBER, QUOTE, OR, QUOTE, NUMBER, QUOTE, EQUALS,
            QUOTE, NUMBER, QUOTE]
  → 语义判断:这是一个永真条件注入 → 拦截

  输入: "1' || '1'like'1"
  → SQL 词法分析
  → Token: [NUMBER, QUOTE, PIPE_PIPE, QUOTE, NUMBER, QUOTE,
            LIKE, QUOTE, NUMBER, QUOTE]
  → 语义判断:等价永真条件 → 拦截

libinjection 是 SQL 注入语义分析的代表:

libinjection 的 fingerprint 机制:
将 SQL 片段标记化为简短的 token 序列

输入                        fingerprint
"1 OR 1=1"                 → "1o1"  (number-or-number)
"admin'--"                 → "s1c"  (string-number-comment)
"' UNION SELECT"           → "sUE"  (string-union-expression)
"1' AND 1=CONVERT(int,@@version)" → "s&1f" (复杂注入)

已知恶意 fingerprint 库 → 匹配即拦截

5.3 对比

维度 正则 WAF 语义分析 WAF
检测准确率 高(规则好的话) 更高(理解语义)
绕过难度 中等(编码/混淆可绕过) 高(需要构造语义等价变换)
性能 正则数量多时 CPU 高 词法分析通常更快
维护成本 需要持续更新规则 语法变化时需更新解析器
误报率 中等
覆盖范围 广(任意模式) 窄(只覆盖已实现的语言)
ReDoS 风险
代表产品 ModSecurity + CRS libinjection, Coraza

实际生产中,最佳实践是组合使用:先用语义分析检测已知注入类型(SQLi、XSS),再用正则规则覆盖语义分析未覆盖的攻击类型(LFI、RCE 等)。

六、Nginx + ModSecurity 部署实战

6.1 安装与配置

# Ubuntu 22.04 安装 ModSecurity v3 + Nginx connector
apt-get install -y libmodsecurity3 libmodsecurity-dev
apt-get install -y nginx libnginx-mod-http-modsecurity

# 或从源码编译(获取最新版本)
# git clone https://github.com/SpiderLabs/ModSecurity.git
# cd ModSecurity && git checkout v3/master
# git submodule init && git submodule update
# ./build.sh && ./configure && make && make install

Nginx 集成配置

# /etc/nginx/nginx.conf 或 sites-available/default
server {
    listen 443 ssl http2;
    server_name example.com;
    
    # 启用 ModSecurity
    modsecurity on;
    modsecurity_rules_file /etc/nginx/modsecurity/main.conf;
    
    location / {
        proxy_pass http://backend;
    }
}
# /etc/nginx/modsecurity/main.conf
Include /etc/nginx/modsecurity/modsecurity.conf
Include /etc/nginx/modsecurity/crs/crs-setup.conf
Include /etc/nginx/modsecurity/crs/rules/*.conf

# 自定义规则(在 CRS 之后加载)
Include /etc/nginx/modsecurity/custom-rules/*.conf

# 白名单规则(在自定义规则之后加载)
Include /etc/nginx/modsecurity/whitelist/*.conf

6.2 CRS 配置优化

# /etc/nginx/modsecurity/crs/crs-setup.conf 关键配置

# 偏执级别(推荐从 1 开始)
SecAction "id:900000,phase:1,pass,\
    setvar:tx.paranoia_level=1,\
    setvar:tx.executing_paranoia_level=1"

# 异常评分阈值
SecAction "id:900110,phase:1,pass,\
    setvar:tx.inbound_anomaly_score_threshold=5,\
    setvar:tx.outbound_anomaly_score_threshold=4"

# 允许的 HTTP 方法
SecAction "id:900200,phase:1,pass,\
    setvar:'tx.allowed_methods=GET HEAD POST PUT DELETE OPTIONS PATCH'"

# 允许的 Content-Type
SecAction "id:900220,phase:1,pass,\
    setvar:'tx.allowed_request_content_type=\
    |application/x-www-form-urlencoded|\
    |multipart/form-data|\
    |multipart/related|\
    |text/xml|\
    |application/xml|\
    |application/soap+xml|\
    |application/json|\
    |application/grpc|'"

# 响应体检查(建议关闭以提高性能)
SecResponseBodyAccess Off

6.3 性能调优

# ModSecurity 性能配置
# /etc/nginx/modsecurity/modsecurity.conf

# 请求体检查上限(大于此值不检查 body)
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072

# PCRE 正则匹配限制(防 ReDoS)
SecPcreMatchLimit 500000
SecPcreMatchLimitRecursion 500000

# 审计日志只记录被标记的请求
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"

# 使用 JSON 格式日志便于分析
SecAuditLogFormat JSON
SecAuditLogType Serial
SecAuditLog /var/log/modsec/audit.json

# 临时文件目录
SecTmpDir /tmp/modsecurity
SecDataDir /tmp/modsecurity_data

性能基准参考

配置 延迟增加 吞吐量下降
CRS PL1,小请求 <1ms <5%
CRS PL2,中请求 1–3ms 5–10%
CRS PL3,大请求 3–10ms 10–20%
CRS PL4,大请求 10–50ms 20–50%
无 body 检查 <0.5ms <3%

七、WAF 运维最佳实践

7.1 日志分析与安全运营

# 分析 WAF JSON 审计日志

# 统计攻击类型分布
cat /var/log/modsec/audit.json | \
    python3 -c "
import sys, json
from collections import Counter
tags = Counter()
for line in sys.stdin:
    try:
        entry = json.loads(line)
        for msg in entry.get('transaction', {}).get('messages', []):
            for tag in msg.get('details', {}).get('tags', []):
                if tag.startswith('attack-'):
                    tags[tag] += 1
    except: pass
for tag, count in tags.most_common(20):
    print(f'{count:>6}  {tag}')
"

# 统计被拦截的源 IP
cat /var/log/modsec/audit.json | \
    python3 -c "
import sys, json
from collections import Counter
ips = Counter()
for line in sys.stdin:
    try:
        entry = json.loads(line)
        tx = entry.get('transaction', {})
        if tx.get('response', {}).get('http_code', 0) == 403:
            ips[tx.get('client_ip', 'unknown')] += 1
    except: pass
for ip, count in ips.most_common(20):
    print(f'{count:>6}  {ip}')
"

7.2 WAF 测试

WAF 部署后需要定期测试其有效性。常用的测试工具和方法:

# 使用 nikto 进行基础 WAF 测试
nikto -h https://example.com -Tuning 9

# 使用 wfuzz 进行规则覆盖测试
# 测试 SQL 注入规则
wfuzz -z file,/usr/share/wordlists/sqli.txt \
    -d "id=FUZZ" --hc 200 \
    https://example.com/api/user

# 手动测试常见攻击向量
# SQL 注入
curl -s -o /dev/null -w "%{http_code}" \
    "https://example.com/search?q=1'+OR+1=1--"
# 期望:403

# XSS
curl -s -o /dev/null -w "%{http_code}" \
    "https://example.com/search?q=<script>alert(1)</script>"
# 期望:403

# 命令注入
curl -s -o /dev/null -w "%{http_code}" \
    -d "cmd=;cat /etc/passwd" \
    https://example.com/api/exec
# 期望:403

# 路径遍历
curl -s -o /dev/null -w "%{http_code}" \
    "https://example.com/file?path=../../../etc/passwd"
# 期望:403

7.3 WAF 选型对比

产品 类型 规则引擎 语义分析 部署方式 成本
ModSecurity 3 开源 正则 + libinjection 部分 嵌入 Nginx/Apache 免费
Coraza 开源 兼容 ModSecurity 嵌入/Sidecar 免费
Cloudflare WAF 云服务 正则 + ML 云端 $20+/月
AWS WAF 云服务 正则 + Bot Control 部分 AWS 生态 按规则计费
F5 ASM 商业 正则 + 正向模型 硬件/虚拟
Imperva 商业 正则 + ML 云端/本地

选型建议: - 已使用 CDN → 优先使用 CDN 自带 WAF(一体化管理) - 云原生架构 → 云 WAF(AWS WAF / GCP Cloud Armor) - 需要深度定制 → ModSecurity 或 Coraza(开源可控) - Service Mesh 环境 → Coraza 作为 Envoy Filter

参考文献

  1. OWASP Foundation, “OWASP ModSecurity Core Rule Set,” github.com/coreruleset/coreruleset.
  2. Trustwave, “ModSecurity Reference Manual,” github.com/SpiderLabs/ModSecurity.
  3. Gallagher, N., “libinjection: A C Library for SQL/XSS Injection Detection,” github.com/libinjection.
  4. OWASP Foundation, “OWASP Top 10 Web Application Security Risks,” owasp.org.
  5. Ristic, I., “ModSecurity Handbook,” Feisty Duck, 2nd Edition.
  6. Coraza WAF, “Coraza: Enterprise-Grade Web Application Firewall,” github.com/corazawaf/coraza.
  7. Cloudflare, “WAF Attack Score and WAF ML,” Cloudflare Documentation.
  8. PortSwigger, “Web Security Academy: WAF Bypass Techniques,” portswigger.net.

上一篇: DDoS 防御架构:容量型、协议型与应用层攻击 下一篇: 网络入侵检测与防御:Suricata、签名与异常检测

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2025-08-04 · network

【网络工程】QUIC 生态与工程部署:从实验到生产

QUIC 已经不是实验性协议——HTTP/3 标准化后,CDN、浏览器和主流服务端框架都在推进 QUIC 支持。本文从工程视角对比主流 QUIC 库的成熟度和性能特征,讲解 CDN/负载均衡器的 QUIC 适配方案、从 TCP 迁移到 QUIC 的渐进路径、QUIC 调试工具链,以及生产环境的部署陷阱和性能调优实践。

2025-08-05 · network

【网络工程】eBPF 可编程网络:从包过滤到流量工程

eBPF 正在重新定义网络工程——从传统的 iptables/netfilter 规则堆砌,到可编程、可观测、高性能的网络数据平面。本文系统讲解 eBPF 网络程序类型(XDP/TC/Socket)、Map 数据结构、Cilium 的 eBPF 数据平面实现,以及 eBPF 在负载均衡、可观测性和网络安全中的工程实践。

2025-08-06 · network

【网络工程】可编程数据平面与 P4:软件定义转发

传统网络设备的转发逻辑固化在硬件中。P4 语言让交换机的转发管线可编程——你可以定义自己的包头解析、匹配规则和转发动作。本文从 P4 语言核心概念出发,讲解 Parser/Match-Action/Deparser 的编程模型、可编程交换机芯片(Tofino)的架构、P4 在数据中心和运营商网络中的应用案例,以及 P4 与 eBPF 的定位差异。

2025-08-07 · network

【网络工程】网络模拟与测试:netem、Mininet 与混沌工程

生产环境的网络条件远比实验室复杂——延迟抖动、随机丢包、带宽突变、链路故障。本文系统讲解 tc netem 的完整用法、Mininet 虚拟网络拓扑搭建、网络层混沌工程(Toxiproxy/Comcast/tc-netem)的实战方法,以及如何在 CI/CD 流水线中集成网络条件测试,确保应用在恶劣网络下的鲁棒性。


By .