ModSecurity WAF 规则实战:OWASP CRS 核心规则配置

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 模式下,攻击请求应返回 403DetectionOnly 模式下请求正常放行但审计日志会记录命中规则 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.confevents 块之前,且路径与编译出的 .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 规则理解与日志分析,能够显著提升网站对自动化攻击的防御能力。