本文共计3541个字,预计阅读时长14.2分钟。
annoying酱AI 摘要
annoying酱正在阅读文章,请稍候…
Annoying 小屋 Xiuno 安全加固记录
加固日期:2026-07-30
适用站点:Annoying 小屋
处理范围:Web 访问控制、会话安全、后台请求、数据库访问、插件安装、SSH、防火墙与备份目录
为什么要做这次加固
近期检查论坛时,我参考了社区关于 Xiuno 安全问题的讨论,并进一步核对了本站正在运行的程序。社区文章中提到的修复结论主要面向后续重构版本,而本站仍基于 Xiuno BBS 4.0.4 老核心,并安装了较多插件,因此不能直接认定相关问题已经随重构版一并解决。
这次加固不是“网站从此绝对没有漏洞”的保证 ,解决了本次检查中能够确认和安全修复的问题,并显著降低旧核心暴露在公网时的风险。
检查发现的问题
1. Web 根目录中存在不应公开的文件
站点目录中存在历史备份、插件备份、SQL 文件、配置文件、日志和维护工具。部分文件原先可以通过 URL 直接访问,攻击者可能借此获取数据库结构、配置内容、源代码或历史插件版本。
2. Cookie 安全属性不完整
旧核心创建登录 Cookie 时没有统一启用 Secure、HttpOnly 和 SameSite。这会增加 Cookie 被前端脚本读取、通过明文连接发送或被跨站请求携带的风险。
3. 后台 POST 缺少统一的来源约束
旧后台没有在统一入口处验证写操作的请求来源。在管理员保持登录的情况下,恶意页面可能尝试诱导浏览器向后台提交跨站请求。
4. 数据库查询层依赖字符串拼接
Xiuno 老核心的数据库辅助函数大量依赖 SQL 字符串拼接。即使上层多数位置做了过滤,只要某个插件遗漏校验,就可能把风险带到数据库层。
5. 后台支持远程下载并自动解压插件
远程下载、自动解压并直接放入站点目录的流程权限过大。一旦下载源、传输链路或后台账号出现问题,恶意文件可能直接进入可执行目录。
6. SSH 与服务器端口需要收紧
服务器同时暴露了不必要的 SSH 入口,密码登录也扩大了暴力破解风险。网络边界需要改为只开放网站和指定的密钥登录端口。
我做了哪些修复
一、封锁敏感目录和文件
我为 Nginx 增加了独立的安全规则,禁止通过公网访问以下内容:
- 配置、日志、缓存、临时文件和维护工具目录
- 数据库模型、路由和框架内部目录
- 历史备份、插件备份和个人资料封面备份目录
.sql、.bak、.zip、.tar.gz、.env、.log 等敏感文件INSTALL.txt、README.md、LICENSE.txt 等不需要公开的说明文件
对于这些请求,服务器统一返回 404,减少目录结构和防护规则本身的信息暴露。
同时增加了以下响应头:
Strict-Transport-Security
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Referrer-Policy
Permissions-Policy
并关闭 Nginx 版本号展示。
二、把历史备份迁出 Web 根目录
仅靠 Nginx 拦截仍不够稳妥,因为未来的配置调整可能再次暴露文件。我将 95 个历史备份目录(约 90 MB)整体迁移到 Web 根目录之外,并收紧了目录权限。
这些文件没有被删除,仍保留恢复清单,可以在确有需要时由服务器管理员手动取回。这样既降低公开泄露风险,也保留了回滚能力。
三、统一加固登录 Cookie
论坛的普通会话、登录令牌、管理员令牌和 Cookie 测试项现在统一使用:
Secure
HttpOnly
SameSite=Lax
Path=/
作用如下:
Secure:Cookie 只通过 HTTPS 发送HttpOnly:普通前端脚本不能直接读取登录令牌SameSite=Lax:减少跨站请求自动携带 Cookie 的场景Path=/:让站内 Cookie 作用范围保持一致,避免旧路径残留
由于会话属性发生变化,加固上线前已经登录的管理员和用户可能需要重新登录一次,这是预期行为。
四、增加后台同源 POST 校验
我在后台统一入口加入了写请求来源校验。所有后台 POST 请求必须来自本站 HTTPS 域名,来源不匹配时直接返回 403。
该措施可以阻挡一批常见的跨站请求伪造攻击,但它不是完整 CSRF Token 的替代品。后续仍应逐步给关键表单加入独立、一次性或会话级 CSRF Token。
五、加固数据库辅助层
我没有大规模重写业务代码,而是在核心数据库辅助函数中增加统一约束:
- SQL 字段名必须通过白名单校验
- 比较运算符必须来自允许列表
- 查询值通过 PDO 驱动进行正确引用
- 排序字段和排序方向必须合法
- 插入、更新的字段名必须合法
- 算术更新只接受数字
修改完成后,重新生成了 Xiuno 的合并运行文件,并对所有相关 PHP 文件执行语法检查。这一层防护可以降低旧插件遗漏过滤时形成 SQL 注入的概率,同时尽量保持老核心原有调用方式不变。
六、关闭远程插件自动下载和解压
后台不再允许直接从远程地址下载并自动解压插件。插件更新现在需要经过受控流程:先离线检查来源和文件内容,再上传到服务器并验证权限。
这会少一点操作便利,但能避免未知压缩包直接写入网站可执行目录,是旧版插件生态中非常必要的限制。
七、收紧 SSH 登录
SSH 现在采用以下策略:
PasswordAuthentication no
PermitRootLogin no
PubkeyAuthentication yes
MaxAuthTries 4
服务器只保留指定端口的密钥登录,关闭默认 SSH 端口的公网访问。部署后重新建立了一次独立 SSH 连接,确认密钥登录正常,再继续后续操作,避免因配置错误把服务器锁死。
八、启用主机防火墙
主机防火墙采用默认拒绝入站策略,只允许:
- HTTP:80
- HTTPS:443
- 指定 SSH 密钥登录端口
默认 SSH 端口已拒绝访问,出站流量保持允许。启用后分别复测了 SSH、HTTP 跳转和 HTTPS 页面。
修复后的验证
本次不是只修改文件,我还进行了实际回归测试。
| 检查项 | 修复前 | 修复后 |
| --- | --- | --- |
| 历史备份压缩包 | 可被公网访问 | 404 |
| SQL、配置和日志文件 | 存在公开暴露风险 | 404 |
| 维护工具与内部目录 | 存在公开暴露风险 | 404 |
| 跨站后台 POST | 缺少统一拦截 | 403 |
| 登录 Cookie | 安全属性不统一 | 已启用安全属性 |
| SSH 密码登录 | 攻击面较大 | 已关闭 |
| 默认 SSH 端口 | 对公网开放 | 已拒绝 |
| 首页、板块、文章、登录页 | 正常 | 均正常返回 200 |
另外完成了以下检查:
- Nginx 配置语法检查通过
- 修改过的 PHP 文件语法检查通过
- 首页、板块页、文章页和登录页数据库查询正常
- 浏览器页面正常渲染,控制台未出现新增错误
- 加固后的 PHP 与 Nginx 错误日志未出现新增异常
回滚与备份位置
为避免在旧核心上直接修改后无法恢复,本次操作保留了三类备份:
- Nginx 修改前配置备份
- PHP 核心文件修改前备份
- 从 Web 根目录迁出的历史文件及迁移清单
具体服务器路径不在公开文章中展示,防止泄露目录结构。管理员可在服务器的受限备份目录中查看。回滚时应先验证配置,再重载服务,不能直接覆盖当前运行文件。
仍然存在的长期风险
这次处理解决的是当前确认的问题和高风险暴露面。由于论坛仍基于停止维护的老核心,后续还需要继续做以下工作:
- 规划迁移到仍在维护的论坛核心或兼容重构版本
- 给后台和高风险用户操作加入完整 CSRF Token
- 在测试环境梳理内联脚本后逐步启用 CSP
- 定期审计第三方插件,移除停更和来源不明的插件
- 定期轮换 SSH 密钥、数据库密码和第三方 API 密钥
- 建立自动备份、异地备份和可验证的恢复演练
- 持续检查上传目录、文件权限、越权访问和插件接口
目前没有直接启用严格 CSP,是因为论坛主题和插件使用了较多内联脚本。未经测试直接上线严格策略会造成编辑器、弹窗或插件功能失效,因此该项会在测试环境完成兼容性调整后再部署。
总结
这次加固优先处理了最容易被直接利用的风险:公开敏感文件、弱会话属性、后台跨站写请求、数据库拼接边界、远程插件安装、SSH 暴露和备份目录位置。
加固后,论坛的正常页面与核心功能保持可用,敏感文件和目录不再能从公网读取,后台跨站请求会被拒绝,服务器也只保留必要端口。
安全不是一次修改就结束。对于 Xiuno 4.0.4 这样的老核心,当前方案属于兼容现有业务的紧急防护;长期最可靠的方向仍是减少第三方插件依赖、持续审计,并迁移到受维护的程序版本。
评论区