OWASP CRS 托管规则
按网站开启 OWASP Core Rule Set(CRS),由节点上的 ModSecurity 检查请求,记录命中的规则,在拦截模式下拒绝攻击请求。
概念
| 术语 | 定义 |
|---|---|
| CRS | OWASP 维护的通用 Web 攻击检测规则集(SQL 注入、XSS、路径穿越、协议违规等)。规则 ID 位于 900000–999999。 |
| ModSecurity | 执行 CRS 的 WAF 引擎,以 OpenResty 动态模块随 edgeweir-openresty-modsecurity 软件包安装。CRS 版本随软件包固定,节点运行时不下载规则。 |
| 异常分数 | 每条命中的规则按严重程度累加分数:critical 5、error 4、warning 3、notice 2。请求的总分达到阈值即判定为攻击。 |
| Paranoia level | CRS 的规则等级,1–4。等级越高启用的规则越多,检出更多攻击,也更容易误报。 |
| 模式 | 关闭、仅检测(只记录命中)、拦截(达到阈值返回 403)。 |
开启 CRS
前提:网站所在集群的全部活动节点支持 modsecurity-v1(安装了 edgeweir-openresty-modsecurity,见接入节点)。
-
打开 网站,选择网站,进入「安全」页签。
-
在「OWASP CRS 托管规则」卡片的「模式」中选择「仅检测」。
-
按需在「预设」中选择宽松、标准(默认)或严格,或选择「自定义」设置「Paranoia 等级」「异常分数阈值」「请求体检查上限(字节)」;按需添加「排除的规则 ID」。
-
点击「保存」。控制台提示「已保存」,并为网站所在集群发布新的配置版本。
-
验证:节点应用该版本后发送一个测试载荷:
curl -s -o /dev/null -w '%{http_code}\n' --resolve www.example.com:443:<节点 IP> \ 'https://www.example.com/?q=%3Cscript%3Ealert(1)%3C/script%3E'「仅检测」模式返回源站的正常状态码;一分钟内「命中最多的 CRS 规则」出现该请求命中的规则(如 941100)。
-
观察命中与误报后,把「模式」改为「拦截」并保存。同一请求返回
403。
字段
| 字段 | 取值 | 默认值 | 作用 |
|---|---|---|---|
| 模式 | 关闭 / 仅检测 / 拦截 | 关闭 | 仅检测只记录命中;拦截在异常分数达到阈值时返回 403 |
| Paranoia 等级 | 1–4 | 1 | 启用的 CRS 规则等级 |
| 异常分数阈值 | 1–1000 | 5 | 请求的异常分数达到该值即判定为攻击;5 表示一条 critical 规则即可 |
| 请求体检查上限(字节) | 0–134217728(128 MiB) | 131072(128 KiB) | 只检查请求体的前这么多字节;0 不检查请求体 |
| 排除的规则 ID | 900000–999999,不重复,最多 200 个;不含 901xxx、949xxx、959xxx、980xxx | 无 | 这些规则对该网站不运行,用于处理误报 |
| 预设 | Paranoia 等级 | 异常分数阈值 | 请求体检查上限(字节) |
|---|---|---|---|
| 宽松 | 1 | 10 | 65536 |
| 标准 | 1 | 5 | 131072 |
| 严格 | 2 | 5 | 1048576 |
预设不改变「模式」与「排除的规则 ID」。保存的取值与任何预设都不同时显示为「自定义」。
排除规则:在「排除的规则 ID」输入框输入一个或多个 ID(逗号或空格分隔),点击「添加」或按回车;点击 ID 旁的 × 移除。修改在点击「保存」后生效。
行为
| 项目 | 行为 |
|---|---|
| 范围 | 只有开启 CRS 的网站经过 ModSecurity;其他网站的请求不受影响 |
| 缓存命中 | 开启 CRS 的网站对缓存命中的请求同样检查 |
| 拦截 | 拦截模式下达到阈值的请求返回 403,不回源 |
| 配置变更 | 节点把网站的 CRS 设置渲染为规则文件,校验通过后重载;校验失败时保留原配置 |
| 回滚 | 配置回滚恢复该版本中网站的 CRS 设置 |
| 审计 | 每次修改写审计 site.waf_update |
查看命中
| 位置 | 内容 |
|---|---|
| 「安全」页签 → 「命中最多的 CRS 规则」 | 所选时间范围(过去 1 小时至 30 天)内命中次数最多的规则 ID。统计为近似值:每个节点每分钟每个网站只上报命中最多的 20 条规则 |
| 网站「日志」页签 | 开启访问日志采样后,命中规则的请求显示「CRS」列:规则 ID(每个请求最多 16 个)与「已拦截」标记。CSV 增加 wafRuleIds(空格分隔)与 wafBlocked 列 |
命中统计与日志在「仅检测」和「拦截」模式下都会记录。误报的规则可以就地排除:在「命中最多的 CRS 规则」或日志行右侧点击「⋯」→「排除 CRS 规则 N」并确认,规则 ID 追加到「排除的规则 ID」并立即保存,CRS 卡片随之更新。初始化、拦截判定与关联类规则(901xxx、949xxx、959xxx、980xxx)只负责计分与判定,例如 949110 在每个被拦截的请求上都命中:它们不进入「命中最多的 CRS 规则」,也不能排除(控制台与 API 都拒绝,WAF_RULE_NOT_EXCLUDABLE),因为排除它们会让 CRS 失效或关闭拦截;误报时排除日志行中真正检测到问题的规则,不想拦截时把模式改为「仅检测」。「安全」页签顶部的状态行显示 CRS 的模式与预设,点击跳到 CRS 卡片。访问日志见访问日志。
性能
开启 CRS 的网站每个请求都要经过 ModSecurity 规则匹配,节点 CPU 占用与请求延迟随 Paranoia 等级、请求体检查上限和请求大小增加。未开启 CRS 的网站不经过 ModSecurity。建议先以「仅检测」运行,观察命中、误报和节点负载,再改为「拦截」;只对需要的网站开启,并尽量保持较低的 Paranoia 等级和请求体检查上限。
节点上有网站开启 CRS 时,节点加载 ModSecurity 与内置规则,nginx 内存增加约 40 MiB,持续负载下更多。最后一个网站关闭 CRS 后,这部分内存要到节点下次重启 nginx(例如节点升级或重启服务)才释放。
节点能力
| 能力 | 需要的场景 |
|---|---|
modsecurity-v1 | 任一网站开启 CRS(仅检测或拦截) |
集群中有活动节点不支持 modsecurity-v1 时,未开启 CRS 的网站「模式」不可选,并显示「所在集群有节点不支持,暂时无法开启」(GET /sites/{id}/features 的 crs.reason 为 nodes);已开启的 CRS 仍可修改或关闭。通过 API 仍可开启:配置照常发布,缺少该能力的节点保留 last-known-good 配置并显示「需要升级」,直到节点安装 edgeweir-openresty-modsecurity 或升级。
限制
| 项目 | 说明 |
|---|---|
| 规则 | 只运行节点软件包内置的 CRS;不能添加自定义 ModSecurity 规则 |
| 排除 | 只能按规则 ID 对整个网站排除,不能按路径或参数排除 |
| 统计 | 命中统计为近似值,每个节点按网站、分钟只上报命中最多的 20 条规则 |
| 节点 | 使用 --no-modsecurity 安装的节点不支持 CRS |
故障排查
| 现象 | 原因 | 处理 |
|---|---|---|
| 「模式」不可选,显示「所在集群有节点不支持,暂时无法开启」 | 集群中有活动节点未安装 edgeweir-openresty-modsecurity 或版本过旧 | 在节点上安装该软件包或升级节点 |
| 节点显示「需要升级」 | 经 API 开启了 CRS,节点缺少 modsecurity-v1 | 在节点上安装该软件包或升级节点 |
| 正常请求被 403 | 误报 | 在「命中最多的 CRS 规则」或访问日志中找到规则 ID,加入「排除的规则 ID」;或降低 Paranoia 等级、提高异常分数阈值 |
| 测试载荷没有被拦截 | 模式为「仅检测」;异常分数未达到阈值;相关规则已被排除;节点尚未应用配置 | 检查设置与节点的已应用版本 |
| 「规则 ID 为 900000 至 999999 的整数,不重复,最多 200 个」 | 输入的 ID 不在 CRS 范围、重复或超过数量 | 修正输入 |