ModSecurity WAF 规则实战是 Web 应用安全防护的核心技能,本文演示如何在 Nginx 上集成开源 WAF 引擎 ModSecurity 与 OWASP CRS 核心规则集,实现对 SQL 注入、XSS、命令注入等常见攻击的自动化拦截,并提供可直接复制的完整配置与验证方法。
适用场景
- 网站未接入商业 WAF,需要低成本自建 Web 应用防火墙的场景
- 等保合规要求部署 WAF 或 Web 攻击防护能力的场景
- 需要统一拦截 SQL 注入、XSS、命令注入等 OWASP Top 10 攻击的场景
- 希望在不改业务代码前提下快速获得 Web 层攻击防护的场景
前置条件
- Linux 服务器(本教程以 Ubuntu 22.04 + Nginx 为例)
- 已安装 Nginx 并可正常访问业务站点
- 具备 root 或 sudo 权限
- 域名已解析到服务器(本教程以 example.com 为例)
原理说明
ModSecurity 是一款开源 Web 应用防火墙引擎,采用规则驱动的工作方式:每个请求经过引擎时,会依次匹配一组安全规则,规则命中后执行对应的动作(记录、拦截、放行)。OWASP CRS(Core Rule Set)是 ModSecurity 官方推荐的核心规则集,内含覆盖 OWASP Top 10 的数百条规则,分为注入攻击、XSS、协议违规、恶意文件上传等类别。ModSecurity 通过 Nginx 的 ngx_http_modsecurity_module 模块嵌入请求处理流程,在 access 阶段完成检测与拦截。
操作步骤
1. 编译安装带 ModSecurity 模块的 Nginx
Nginx 官方二进制包默认不带 ModSecurity 模块,需通过编译方式安装。为简化流程,推荐使用 libmodsecurity3 动态模块方式:
# 安装编译依赖
sudo apt update && sudo apt install -y build-essential libpcre3-dev libxml2-dev libcurl4-openssl-dev libyajl-dev liblua5.1-0-dev pkgconf
# 下载 ModSecurity 源码并编译动态模块
git clone --depth 1 -b v3.0.12 https://github.com/owasp-modsecurity/ModSecurity
cd ModSecurity
./build.sh
./configure --with-yajl
make -j4 && sudo make install
再编译 modsecurity-nginx 连接器动态模块:
git clone --depth 1 https://github.com/owasp-modsecurity/modsecurity-nginx
cd modsecurity-nginx
wget http://nginx.org/download/nginx-1.24.0.tar.gz
tar xzf nginx-1.24.0.tar.gz && cd nginx-1.24.0
./configure --with-compat --add-dynamic-module=../modsecurity-nginx
make modules
sudo cp objs/ngx_http_modsecurity_module.so /usr/lib/nginx/modules/
2. 加载模块并下载 OWASP CRS 规则集
# 在 /etc/nginx/nginx.conf 顶部加载动态模块
echo 'load_module modules/ngx_http_modsecurity_module.so;' | sudo tee -a /etc/nginx/nginx.conf
# 下载 OWASP CRS 规则集
sudo mkdir -p /etc/nginx/modsecurity /etc/nginx/crs
cd /etc/nginx/modsecurity
sudo cp /usr/local/modsecurity/bin/modsecurity.conf-recommended modsecurity.conf
sudo cp /usr/local/modsecurity/unicode.mapping .
cd /etc/nginx/crs
sudo git clone --depth 1 -b v3.3.5 https://github.com/coreruleset/coreruleset .
sudo cp crs-setup.conf.example crs-setup.conf
sudo ln -s /etc/nginx/crs/rules /etc/nginx/crs/rules
3. 配置 ModSecurity 主配置
编辑 /etc/nginx/modsecurity/modsecurity.conf,设置检测模式与审计日志:
# 生产环境建议先设为 DetectionOnly 观察误报,稳定后再改为 On
SecRuleEngine DetectionOnly
# 请求体限制(与 Nginx client_max_body_size 保持一致)
SecRequestBodyLimit 13107200
SecRequestBodyNoFilesLimit 131072
# 审计日志
SecAuditEngine RelevantOnly
SecAuditLog /var/log/nginx/modsec_audit.log
SecAuditLogType Serial
# 上传临时目录(必须配置)
SecTmpDir /tmp/
SecDataDir /tmp/
4. 在 Nginx 站点中启用 ModSecurity
server {
listen 80;
server_name example.com;
# 启用 ModSecurity 与 CRS 规则集
modsecurity on;
modsecurity_rules_file /etc/nginx/modsecurity/modsecurity.conf;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
}
}
同时将 CRS 规则引入:编辑 modsecurity.conf 末尾追加以下两行,引用 CRS 配置与规则:
Include /etc/nginx/crs/crs-setup.conf
Include /etc/nginx/crs/rules/*.conf
5. 调整 CRS 关键参数
编辑 /etc/nginx/crs/crs-setup.conf,建议关注以下参数:
# 异常评分阈值(默认 5 个严重级别,建议保持默认)
# 设置为 100000 可完全关闭拦截只记录(排障用)
SecAction "id:900000,phase:1,nolog,pass,t:none,setvar:tx.blocking_paranoia_level=1"
# 设置被保护业务的白名单(可选,防止误伤管理后台)
SecRule REQUEST_URI "@beginsWith /wp-admin/" "id:900100,phase:1,nolog,pass,t:none,ctl:ruleRemoveById=942100"
若误报较多,可先保持 SecRuleEngine DetectionOnly 运行数天,观察审计日志中命中的正常请求,再针对性添加白名单规则后切换为 On。
6. 重载 Nginx 并验证模块加载
sudo nginx -t
sudo systemctl reload nginx
# 验证模块是否加载
nginx -V 2>&1 | grep modsecurity
配置验证
使用 curl 发送典型攻击载荷验证拦截效果:
# 模拟 SQL 注入(应触发 942 系列规则)
curl -i "http://example.com/?id=1%27%20OR%201%3D1%20--%20"
# 模拟 XSS 攻击(应触发 941 系列规则)
curl -i "http://example.com/?q=<script>alert(1)</script>"
# 检查审计日志中的命中记录
tail -20 /var/log/nginx/modsec_audit.log | grep -E "id "9[0-9]{4}""
SecRuleEngine On 模式下,攻击请求应返回 403;DetectionOnly 模式下请求正常放行但审计日志会记录命中规则 ID。命中规则以 9 开头(如 942100、941100),说明 CRS 检测生效。
常见问题
FAQ 1:启用后正常业务被拦截(误报)怎么办?
先用 SecRuleEngine DetectionOnly 运行观察,通过审计日志找出误报的规则 ID,然后在 crs-setup.conf 中添加针对性白名单:SecRule REQUEST_URI "@beginsWith /api/v1/report" "id:900101,phase:1,pass,nolog,ctl:ruleRemoveById=942100"。也可调低异常评分阈值(如 setvar:tx.inbound_anomaly_score_threshold=100)降低敏感度,待规则熟悉后再收紧。
FAQ 2:加载模块后 Nginx 启动失败?
常见原因有二:一是 load_module 指令必须放在 nginx.conf 的 events 块之前,且路径与编译出的 .so 文件实际位置一致;二是 modsecurity.conf 引用的 unicode.mapping 等文件缺失,用 sudo nginx -t 会明确报错指明缺失文件,补全后重载即可。若使用 CentOS 等系统,注意 SELinux 可能阻止模块读取规则文件,需 setsebool -P httpd_can_network_connect 1 或调整上下文。
总结
通过 Nginx + ModSecurity + OWASP CRS 的组合,可在不改动业务代码的前提下,为 Web 应用快速建立 OWASP Top 10 攻击防护能力。核心要点是:先以 DetectionOnly 模式灰度观察、用审计日志精准定位误报、通过白名单与阈值调优后再切换拦截模式。ModSecurity 规则配置是安全运维的实用技能,结合 CRS 规则理解与日志分析,能够显著提升网站对自动化攻击的防御能力。