Web 应用防火墙(WAF)工作在应用层,专门针对 HTTP/HTTPS 流量进行深度检测和过滤,是防御 SQL 注入、跨站脚本(XSS)、文件上传漏洞等 Web 攻击的关键安全组件。本文将以开源 WAF 引擎 ModSecurity 为核心,讲解其工作原理、部署方法、规则编写和防护策略。
WAF 的工作原理
WAF 位于 Web 服务器之前(或集成在 Web 服务器中),对每一个 HTTP 请求和响应进行分析。其检测方式主要包括:
正则匹配(Signature-Based)
通过预定义的正则表达式模式匹配请求中的恶意特征,如 SQL 关键字(UNION SELECT、OR 1=1)、XSS 载荷(<script>、onerror=)等。这是最传统也最常用的检测方式,规则明确、误报可控。
语义分析(Semantic Analysis)
超越简单的字符串匹配,理解请求内容的语义。例如,对 SQL 片段进行语法解析,判断是否构成有效的 SQL 注入语句。这种方式能有效应对各类编码和混淆绕过。
行为分析(Behavioral Analysis)
基于请求频率、访问模式、参数异常等行为特征进行判断。例如同一 IP 短时间内大量请求同一接口,或请求参数长度异常等。通常结合评分机制(Anomaly Scoring)综合判定。
WAF 部署模式
| 模式 | 说明 | 示例 |
|---|---|---|
| 反向代理 | WAF 作为独立反向代理部署在 Web 服务器前 | Nginx + ModSecurity |
| 嵌入式 | WAF 模块嵌入 Web 服务器 | Apache mod_security |
| 云 WAF | 基于 DNS/CDN 的云端 WAF | Cloudflare WAF、AWS WAF |
| 旁路检测 | 镜像流量进行分析,不阻断 | 用于监控和审计 |
ModSecurity 部署
ModSecurity 是最著名的开源 WAF 引擎,支持 Apache、Nginx 和 IIS。ModSecurity v3(libmodsecurity)采用了与 Web 服务器解耦的架构,通过连接器(Connector)与不同的 Web 服务器集成。
Nginx + ModSecurity v3 部署
# 安装依赖
sudo apt install -y git gcc make build-essential autoconf automake \
libtool libcurl4-openssl-dev libpcre3-dev libxml2-dev \
libyajl-dev pkgconf libgeoip-dev libssl-dev zlib1g-dev
# 编译 libmodsecurity
git clone --depth 1 https://github.com/SpiderLabs/ModSecurity.git
cd ModSecurity
git submodule init && git submodule update
./build.sh && ./configure
make -j$(nproc) && sudo make install
# 下载 Nginx ModSecurity 连接器
git clone --depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git
# 编译 Nginx 动态模块(或重新编译 Nginx)
cd /path/to/nginx-source
./configure --with-compat --add-dynamic-module=../ModSecurity-nginx
make modules
sudo cp objs/ngx_http_modsecurity_module.so /etc/nginx/modules/
Nginx 配置启用 ModSecurity
# /etc/nginx/nginx.conf
load_module modules/ngx_http_modsecurity_module.so;
http {
# 全局启用 ModSecurity
modsecurity on;
modsecurity_rules_file /etc/nginx/modsecurity/modsecurity.conf;
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# 特定 location 可单独配置规则
location /api/ {
modsecurity_rules '
SecRuleRemoveById 941100
SecRuleRemoveById 941160
';
proxy_pass http://127.0.0.1:8080;
}
}
}
Apache + ModSecurity 部署
# 直接安装 Apache ModSecurity 模块
sudo apt install -y libapache2-mod-security2
sudo a2enmod security2
# 复制默认配置
sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
# 重启 Apache
sudo systemctl restart apache2
ModSecurity 主配置文件
# /etc/modsecurity/modsecurity.conf
# 引擎开关:DetectionOnly(仅检测不阻断)/ On(检测并阻断)
SecRuleEngine On
# 请求体检查
SecRequestBodyAccess On
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072
SecRequestBodyLimitAction Reject
# 响应体检查
SecResponseBodyAccess On
SecResponseBodyMimeType text/plain text/html text/xml application/json
SecResponseBodyLimit 524288
# 临时文件目录
SecTmpDir /tmp/modsecurity/tmp/
SecDataDir /tmp/modsecurity/data/
# 审计日志配置
SecAuditEngine RelevantOnly
SecAuditLogRelevantStatus "^(?:5|4(?!04))"
SecAuditLogParts ABIJDEFHZ
SecAuditLogType Serial
SecAuditLog /var/log/modsecurity/audit.log
# 调试日志
SecDebugLog /var/log/modsecurity/debug.log
SecDebugLogLevel 0
# 异常评分模式阈值(OWASP CRS 使用)
SecAction "id:900110, phase:1, nolog, pass, t:none, \
setvar:tx.inbound_anomaly_score_threshold=5, \
setvar:tx.outbound_anomaly_score_threshold=4"
# Unicode 映射
SecUnicodeMapFile unicode.mapping 20127
# 默认动作
SecDefaultAction "phase:1,log,auditlog,pass"
SecDefaultAction "phase:2,log,auditlog,pass"
OWASP CRS 核心规则集
OWASP CRS(Core Rule Set)是 ModSecurity 最常用的规则集,提供了对常见 Web 攻击的全面防护。
安装 CRS
# 下载最新版 CRS
git clone https://github.com/coreruleset/coreruleset.git /etc/nginx/modsecurity/crs
cd /etc/nginx/modsecurity/crs
# 复制配置模板
cp crs-setup.conf.example crs-setup.conf
# 在 modsecurity.conf 中引入 CRS
echo 'Include /etc/nginx/modsecurity/crs/crs-setup.conf' >> /etc/nginx/modsecurity/modsecurity.conf
echo 'Include /etc/nginx/modsecurity/crs/rules/*.conf' >> /etc/nginx/modsecurity/modsecurity.conf
CRS 规则分类
| 规则文件 | 防护类型 |
|---|---|
| REQUEST-911-METHOD-ENFORCEMENT | HTTP 方法限制 |
| REQUEST-913-SCANNER-DETECTION | 扫描器检测 |
| REQUEST-920-PROTOCOL-ENFORCEMENT | 协议合规检查 |
| REQUEST-930-APPLICATION-ATTACK-LFI | 本地文件包含(LFI) |
| REQUEST-931-APPLICATION-ATTACK-RFI | 远程文件包含(RFI) |
| REQUEST-932-APPLICATION-ATTACK-RCE | 远程命令执行(RCE) |
| REQUEST-933-APPLICATION-ATTACK-PHP | PHP 注入攻击 |
| REQUEST-941-APPLICATION-ATTACK-XSS | 跨站脚本(XSS) |
| REQUEST-942-APPLICATION-ATTACK-SQLI | SQL 注入 |
| REQUEST-943-APPLICATION-ATTACK-SESSION | 会话固定攻击 |
| REQUEST-944-APPLICATION-ATTACK-JAVA | Java 攻击 |
CRS 异常评分模式
CRS 默认使用异常评分模式(Anomaly Scoring Mode):每条匹配的规则不会立即阻断,而是给请求增加一个异常分数。当总分数超过设定阈值时才触发阻断动作。这大幅减少了误报。
# crs-setup.conf 中配置评分模式
SecAction "id:900000, phase:1, nolog, pass, t:none, \
setvar:tx.paranoia_level=1"
# Paranoia Level 说明:
# PL1 - 基础防护(推荐起步)
# PL2 - 增强防护,可能有些误报
# PL3 - 高级防护,需要调优
# PL4 - 最高防护,误报率高,需大量白名单
自定义规则编写
防 SQL 注入
# 检测 URL 参数中的 SQL 注入
SecRule ARGS "@rx (?i)(\bunion\b.*\bselect\b|\bselect\b.*\bfrom\b.*\bwhere\b|\binsert\b.*\binto\b|\bdelete\b.*\bfrom\b|\bdrop\b.*\btable\b)" \
"id:100001, \
phase:2, \
deny, \
status:403, \
log, \
msg:'SQL Injection Detected in Parameters', \
tag:'attack-sqli', \
severity:'CRITICAL', \
logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}'"
# 检测 SQL 注释符号
SecRule ARGS "@rx (--|#|/\*)" \
"id:100002, \
phase:2, \
pass, \
nolog, \
setvar:tx.anomaly_score=+3, \
msg:'SQL Comment Sequence Detected'"
防 XSS
# 检测请求体中的 XSS 攻击
SecRule REQUEST_BODY "@rx (?i)(<script[^>]*>|javascript\s*:|on\w+\s*=|<\s*img[^>]+onerror)" \
"id:100003, \
phase:2, \
deny, \
status:403, \
log, \
msg:'XSS Attack Detected in Request Body', \
tag:'attack-xss', \
severity:'CRITICAL'"
# 检测 Cookie 中的 XSS
SecRule REQUEST_COOKIES "@rx (?i)(<script|javascript:|on\w+=)" \
"id:100004, \
phase:1, \
deny, \
status:403, \
log, \
msg:'XSS in Cookie Detected'"
防恶意文件上传
# 限制上传文件类型
SecRule FILES_NAMES "@rx \.(php|php3|php4|php5|phtml|pht|jsp|jspx|asp|aspx|exe|sh|py|pl|cgi|bat|cmd)$" \
"id:100005, \
phase:2, \
deny, \
status:403, \
log, \
msg:'Dangerous File Upload Blocked', \
tag:'attack-upload', \
severity:'CRITICAL'"
# 检测文件内容中的 PHP 标签(双重检测)
SecRule FILES_TMP_CONTENT "@rx (?i)(<\?php|<\?=|<%)" \
"id:100006, \
phase:2, \
deny, \
status:403, \
log, \
msg:'PHP Code in Uploaded File Detected'"
# 限制上传文件大小(5MB)
SecRequestBodyLimit 5242880
白名单与误报处理
在实际生产环境中,WAF 的误报管理至关重要。以下是常用的误报处理方法:
# 方法1:按规则 ID 移除(全局)
SecRuleRemoveById 941100 941160
# 方法2:按 URL 路径排除规则
SecRule REQUEST_URI "@beginsWith /api/webhook" \
"id:100010, \
phase:1, \
pass, \
nolog, \
ctl:ruleRemoveById=942100-942999"
# 方法3:按参数名排除
SecRuleUpdateTargetById 942100 "!ARGS:html_content"
SecRuleUpdateTargetById 941100 "!ARGS:html_content"
# 方法4:IP 白名单
SecRule REMOTE_ADDR "@ipMatch 192.168.1.100,10.0.0.0/8" \
"id:100011, \
phase:1, \
allow, \
nolog, \
msg:'Whitelisted IP'"
# 方法5:特定 User-Agent 白名单(内部监控工具)
SecRule REQUEST_HEADERS:User-Agent "@contains InternalMonitor" \
"id:100012, \
phase:1, \
allow, \
nolog"
误报排查流程
# 查看审计日志中被拦截的请求
grep -A 20 "403" /var/log/modsecurity/audit.log
# 提取被触发的规则 ID
grep "id \"" /var/log/modsecurity/audit.log | sort | uniq -c | sort -rn
# 分析特定规则的触发详情
grep "941100" /var/log/modsecurity/audit.log
# 临时切换为 DetectionOnly 模式观察
# SecRuleEngine DetectionOnly
WAF 绕过技术与防御
了解常见的绕过技术有助于加强防御:
| 绕过技术 | 示例 | 防御方法 |
|---|---|---|
| 大小写混淆 | UnIoN SeLeCt | 规则使用 (?i) 忽略大小写 |
| URL 编码 | %27%20OR%201%3D1 | 启用 t:urlDecodeUni 转换 |
| 双重编码 | %2527 | 多次解码 t:urlDecode,t:urlDecode |
| 注释插入 | UN/**/ION SEL/**/ECT | 使用 t:removeComments |
| 空字节绕过 | sel%00ect | 启用 t:replaceNulls |
| 分块传输 | Transfer-Encoding: chunked | 确保完整重组请求体 |
| HPP(参数污染) | id=1&id=2 OR 1=1 | 检查所有同名参数 |
# 增强规则:多重转换函数
SecRule ARGS "@rx (?i)(union.*select|insert.*into)" \
"id:100020, \
phase:2, \
deny, \
status:403, \
t:none, \
t:urlDecodeUni, \
t:htmlEntityDecode, \
t:removeComments, \
t:compressWhitespace, \
t:lowercase, \
msg:'Enhanced SQL Injection Detection'"
安全建议
- 循序渐进部署:先以
DetectionOnly模式运行,分析日志确认无大量误报后再切换为On模式阻断。 - 合理设置 Paranoia Level:从 PL1 起步,根据安全需求和误报容忍度逐步提高。
- 持续更新规则:定期更新 OWASP CRS 至最新版本,获取最新的攻击特征。
- 精细化白名单:按 URL 路径、参数名精确排除误报,避免全局禁用规则。
- 多层防御:WAF 不是银弹,应与输入验证、参数化查询、CSP 等应用层安全措施配合使用。
- 监控与告警:将 WAF 日志接入 SIEM,配置高危规则触发时的实时告警。
- 性能监控:关注 WAF 对请求延迟的影响,必要时优化规则或使用硬件加速。
- 定期渗透测试:聘请专业团队对 WAF 防护效果进行测试验证,发现规则盲区。
总结
ModSecurity 配合 OWASP CRS 提供了一套强大且灵活的 Web 应用防护方案。通过正则匹配、异常评分和行为分析的组合,能够有效检测和阻断绝大多数常见 Web 攻击。然而,WAF 的有效性高度依赖于规则的质量和调优水平。在部署 WAF 时,应坚持”先监控后阻断”的原则,持续优化规则集,在安全防护和业务可用性之间找到最佳平衡点。同时,WAF 应作为纵深防御体系中的一环,与代码审计、安全编码实践、网络层防护共同构建全方位的安全防线。