[审计]SoSite 全代码审计报告(2026-08-06)

👑Lv.11 元老 🌞 骨干会员
2026-10-25 00:12:36

本文由 FlintHub 开发文档归档发布。原始文档日期见标题前缀,来源:8月13日备份/审计20260806.md。

SoSite 全代码审计报告(2026-08-06)

审计方式:全代码只读遍历(PHP/CSS/JS/视图/插件),多维度并行扫描 + 人工核实关键点。

范围:app/(48 个 PHP 文件,约 9379 行)、assets/css/(10 个文件,约 7068 行)、assets/js/(6 个文件,约 2934 行)、app/Views/plugins/(18 个插件视图)、protected/、根目录。

结论:本次审计未修改任何代码,以下为发现与建议,供决策参考。


一、安全审计

1.1 SQL 注入 —— 总体良好,无高危可利用点 ✅

参数化纪律优秀:Database::query() 一律 prepare() + 参数绑定,PDO::ATTR_EMULATE_PREPARES=false;LIMIT/OFFSET 绝大多数显式 (int) 转换;IN (...) 全部命名占位符或先 array_map('intval')。未发现"用户输入直接拼入 SQL 且无净化"的注入点。

#位置风险说明
S1app/Controllers/Admin/DatabaseController.php:308-377🟠 中mysqlImport() 将管理员导入的 .sql 备份逐条 $conn->exec($sql) 原样执行。虽有 CSRF + 路径校验 + .sql 扩展名限制,但被篡改备份可致全库沦陷;属功能固有风险,建议校验备份格式并在界面显著警告
S2app/Core/Model.php:198-201🟡 低sanitizeOrderBy 用黑名单"剔除非法字符"而非白名单;虽无法构造子查询/注释,建议改为白名单

1.2 XSS 输出 —— 转义纪律良好,个别属性值待加固 ✅

扫描全部视图输出(132 处 echo 初筛 → 38 处人工甄别),绝大多数用户可控字段均已 $this->e() / formatPostContent / decodeContent 转义。

#位置风险说明
X1app/Views/theme/settings.php:34,36🟡 低$color 直接输出进 style="..." 未过 e()(值源自主题配置,非直接用户输入,风险低);建议统一转义
X2app/Views/admin/search_settings.php:37🟡 低$percent 进内联 style(数值型,width:% 语义安全,但建议 (int) 强转)
X3其余 36 处命中✅均为 style="background:<?php echo $this->e($color) ?>" 等已转义形式,属误报

1.3 CSRF —— 覆盖完整 ✅

所有写操作(发帖/回帖/评论/私信/上传/投票/编辑/删除/后台)均 Csrf::verifyOrDie();15 个 Admin 控制器统一继承 Admin/BaseController。已人工核实 BlogController::show:106、create:176 等均有校验。未发现缺失。

1.4 文件上传 —— 校验完善,服务器防护缺失 ⚠️

Upload.php 校验链路完整:扩展名白名单 → is_uploaded_file → finfo MIME 白名单严格匹配 → 16 字节随机文件名 → move_uploaded_file → 缩略图(>5000px 像素炸弹拒绝、Imagick 格式限制)。

#位置风险说明
U1assets/uploads/(无防护文件)🟠 中uploads 目录无 .htaccess/nginx 规则禁止脚本执行。虽 MIME+扩展名双白名单(jpg/png/gif/webp/pdf/zip/doc/docx,无 php)已挡掉直接上传可执行文件,但 polyglot 文件(图片头+脚本尾)在"服务器配置不当"时仍可能被解析。建议在 uploads 部署 php_flag engine off / nginx location ~ \.php$ { deny all; }
U2app/Helpers/Upload.php:58-61🟡 低finfo 扩展不可用时仅靠扩展名白名单兜底放行(有 error_log),建议此时拒绝图片以外的类型
U3app/Helpers/Upload.php:107🟡 低原图保存前无 getimagesize 真实性校验(缩略图生成时才有);建议上传时即校验

1.5 SSRF —— 已加固但存在两个高优先绕过点 🔴

ApiController::fetchImage 已有:登录 + 限流 + URL 协议校验 + host 内网检测 + DNS 解析后真实 IP 校验 + 用 IP 替换 host 防 DNS Rebinding。

#位置风险说明
R1app/Controllers/ApiController.php:172-196🔴 高169.254.0.0/16(云元数据 169.254.169.254)与 100.64.0.0/10(CGNAT 内网段)未封禁,可直连云元数据/内网地址
R2app/Controllers/ApiController.php:205-233🔴 高follow_location=1 跟随重定向但重定向目标未逐跳二次内网校验,黑名单可通过重定向绕过
R3app/Controllers/ApiController.php:161-196🟡 低未限制端口(非 80/443 亦可)、SSL 校验关闭(IP 直连所需,可接受但应知悉)
—修复建议—重定向逐跳二次校验 + 禁 169.254.0.0/16、100.64.0.0/10 + 端口白名单 80/443

1.6 命令注入 —— 零发现 ✅

全库扫描 shell_exec/system/exec/passthru/proc_open/popen:仅注释提及(TemplateCompiler 防模板注入),无实际调用。

1.7 认证与会话 —— 配置严谨 ✅

  • Session:use_only_cookies、cookie_httponly、use_strict_mode、samesite=Lax、文件存储 + 定期 GC(config.php)
  • RememberMe:token 仅存 sha256 哈希 + hash_equals 恒定比较 + 每次自动登录轮换 token + httponly/samesite Cookie(RememberMe.php)
  • Auth::isAdmin:数据库双重确认(role=admin 且 group_id=4)
  • Auth::requireAdmin:30 分钟二次验证(admin_verified_at)+ 登录页跳转

1.8 路径穿越/附件 —— 基本安全,一处待加固 ✅

#位置风险说明
P1app/Helpers/Settings.php:610-618🟠 中deleteAttachment(int $id) 仅按 id 删文件,无归属校验,依赖调用方先校验(ThreadController/PostController 均已先校验 thread_id/post_id,当前安全,但函数自身 API 脆弱)
P2app/Controllers/BlogController.php:234🟡 低封面删除 @unlink(UPLOAD_PATH . $coverImage) 未 basename/realpath(文件名来自 Upload 随机名,当前不可利用),建议加 basename
P3ProfileController.php:87-88✅头像删除已 basename + realpath 前缀校验


二、权限与业务逻辑审计

总体:属主校验、管理员接口、requireLogin、私信越权均覆盖良好,未发现可直接越权读写他人数据的高危 IDOR。发现 1 个中危信息泄露、1 条账号接管链、多个限流/验证码/二次验证缺口。

#位置风险说明
P-1app/Models/User.php:38 + SearchController.php:66🟠 中用户搜索泄露他人 email/role/status 字段给任意登录用户;建议只 SELECT 展示所需字段
P-2app/Controllers/ProfileController.php:31-52🟠 中改邮箱无需当前密码确认 → 配合忘记密码可构成账号接管链(会话窃取后改绑邮箱 → 重置密码);建议改邮箱要求密码或二次验证
P-3app/Controllers/AuthController.php:35-117🟠 中登录仅按用户名锁定(5 次/15 分钟),无 IP 级限流,密码喷洒(每账号试 1-4 次)不受限,且可被恶意触发登录 DoS
P-4app/Controllers/PostController.php:58-152🟠 中发新主题(POST /post/new)无频率限制(回帖/评论/私信/上传都有限流,唯独发帖没有),可无限刷帖刷积分(+5/帖)
P-5app/Controllers/BlogController.php:171/217/267🟠 中前台 Blog 增删改(admin-only)只查 isAdmin(),绕过 admin_verified_at 30 分钟二次验证;建议并入验证或迁移后台路由
P-6app/Controllers/AuthController.php:251-253🟡 低忘记密码无验证码(登录/注册都有),虽有限流(3 次/时)仍建议补 Captcha 防邮件轰炸
P-7app/Helpers/RateLimiter.php:97-106🟡 低IP 文件缓存读-改-写无锁(仅写时 LOCK_EX),并发可少量突破限流阈值(TOCTOU)
P-8app/Controllers/ThemeController.php:19-24🟡 低主题切换 POST 无 requireLogin(仅 CSRF),影响面小(只改自己 cookie/theme)
P-9ThreadController.php:203/296/303、PostController.php:172🟡 低管理员在前台编辑/删除他人帖子不要求二次验证(与 P-5 同类,影响略低)
✅私信读取/已读/删除—MessageController::detail:124、markAsRead、deleteOwned 均校验收件人/发件人,无越权


三、模板与样式冗余审计

3.1 CSS 重复定义(同名类多文件互覆)—— 高风险区 🟠

项目历经多套模板迭代(旧模板 → Modern),旧 CSS(layout/forum/pages/blog)与 components.css、admin.css 存在大量同名类不同参数:

#选择器位置说明
C1.badgeforum.css:112 / layout.css:57 / admin.css:240-245,313三种含义(通用徽章/导航未读数/后台徽章),加载顺序决定胜负
C2.alert/.alert-*components.css:166-175 / pages.css:496-516 / admin.css:248-258三套配色体系(边框 3px/4px、不同色板)
C3.stat-cardcomponents.css:57 / admin.css:130邀请码统计卡 vs 后台渐变仪表盘,均无作用域
C4.avatar-placeholdercomponents.css:144 / layout.css:45024px 圆形首字母 vs 100% 父容器填充,同名不同行为
C5.btn-dangercomponents.css:241 / forum.css:370参数拼合互相干扰
C6.category-header-bar / .category-row / .reply-card / .attachment-item / .empty-state / .stat-labelcomponents.css / forum.css / pages.css 多处中低危同名互覆
C7侧栏盒子体系forum.css:7-8 / blog.css:238-251 / layout.css:152-166三套"白卡片+标题下划线"仅前缀不同(forum-/blog-/无前缀)
C8搜索表单forum.css:9-12 / blog.css:252-275 / pages.css:323-344 / layout.css:187-2094 套实现
C9分页体系forum.css:311 / blog.css:193+730 / components.css:647 / modern.css:6136 套分页实现

建议:以 modern.css 为唯一基座,删除旧模板 CSS(layout/forum/pages/blog)或彻底废弃未用部分;同名类合并为单一作用域。

3.2 死类与未使用样式 🟡

  • assets/css/home.css:死文件(无任何视图引用),可删(交接文档已确认)
  • 旧模板类(forum.css/layout.css/pages.css 中大量)在 Modern 视图下已无对应元素,属遗留死代码,删除前需逐一确认前台页面
  • !important:modern.css reduced-motion 4 处、editor.css 全屏 1 处(均建议保留);admin.css 已清零 ✅

3.3 内联样式滥用 🟡

多个视图存在大量内联 style="..."(如 thread/show.php、blog/detail.php、admin/),与 Modern 变量体系(--mn-)割裂,后续换肤/维护成本高。建议逐步收敛为类。

3.4 模板冗余 🟡

  • 帖子行/评论行结构在 thread/show.php、blog/detail.php、各插件视图重复实现,未抽公共组件
  • plugins/*/views/ 存在与前台重复的卡片结构(子代理确认 2 份重复视图)

四、代码质量审计(死代码/孤儿文件/遗留)

4.1 孤儿文件(无任何引用,可删/归档)🟠

文件说明
app/Views/admin/settings.php后台设置视图,未被任何控制器 view() 调用(实际用 settings_basic/display/mail/search)
app/Views/emails/verify_email.txt零引用(app 内无 renderEmailTemplate/verify_email 调用)
protected/database/schema_mysql.sql、schema_sqlite.sqlV2.x 双库遗留死文件,全库 0 引用(交接文档已确认)
protected/rebuild_runtime.php疑似遗留脚本(子代理确认)

4.2 悬空引用 🔴

  • plugins/user_profile/FrontController.php:25:$this->view('errors/404', ...) —— app/Views/errors/ 目录不存在,用户不存在时视图渲染将失败(已人工核实 glob 无 errors 目录)

4.3 零调用方法(25 个,可清理或确认保留)🟡

  • Helpers:RateLimiter::remaining、Points::getLog/getLevelTitle/isReplyToView、Settings::getOnlineUsers/paginate/renderPagination/getAttachment、Search::rebuildFTS、Tag::renderInput、Theme::getInfo/exists/safeTitleColor(部分为插件可能使用,删除前需再查)
  • Permission 遗留 5 个:getUserGroupId/getUserGroup/isAdminGroup/getGroupName/canReplyToThread
  • Models 9 个:Blog::getByCategory、BlogComment::getByBlog、Post::getLastPage/restore、Thread::getLatest/getLatestPaginated/search、User::onlineCount、Message::getUnreadCount

4.4 硬编码敏感信息 —— 非配置零命中 ✅

app/plugins/protected 中未发现散落的数据库密码/密钥/token。⚠️ 部署注意:config.php:8-9 DB 账号 so/123456 为弱默认口令、config.php:21 MAIL_PASS_KEY 为固定 AES 密钥,正式部署必须更换。

4.5 遗留标记

  • TODO/FIXME/XXX/HACK:零命中 ✅
  • 注释掉的代码块:零命中 ✅
  • 临时文件:tmp_audit_xss.php(本次审计所用,审计完成后应删除)

五、风险汇总矩阵(按优先级)

优先级问题位置
🔴 高SSRF:169.254.0.0/16 与 100.64.0.0/10 未封禁 + 重定向未二次校验ApiController.php:172-233
🔴 高悬空引用:user_profile 插件渲染不存在的 errors/404 视图plugins/user_profile/FrontController.php:25
🟠 中改邮箱无需密码(账号接管链)ProfileController.php:31-52
🟠 中登录无 IP 级限流 / 发新主题无频率限制AuthController / PostController
🟠 中前台 admin-only 操作绕过 30 分钟二次验证(博客增删改等)BlogController / ThreadController
🟠 中用户搜索泄露 email/role/statusUser.php:38
🟠 中uploads 目录无禁止脚本执行规则assets/uploads/
🟠 中后台 SQL 导入 exec 任意 SQL(功能固有风险)Admin/DatabaseController.php
🟡 低忘记密码无验证码、RateLimiter TOCTOU、deleteAttachment 无归属校验等多处

六、建议整改顺序

  1. 安全:修复 SSRF 两个绕过点(R1/R2)→ 改邮箱加密码确认(P-2)→ 登录/发帖补限流(P-3/P-4)→ uploads 禁止脚本执行(U1)
  2. 健壮性:修 user_profile 悬空 404 视图引用(4.2)
  3. 信息泄露:User::search 裁剪字段(P-1)
  4. 冗余清理:删孤儿文件(4.1)→ CSS 旧模板体系合并/废弃(3.1)→ 零调用方法清理(4.3)
  5. 部署卫生:更换 config.php 弱口令与固定密钥(4.4)

审计完成 — SoSite 2026-08-06。本次未修改任何代码,所有结论基于只读检查与脚本统计。

轻量级、高性能、零 MySQL 依赖的PHP社区系统。
| 瀏覽 4 次 | 回覆 0 次

全部回覆 (0)

暫無回覆

請 登入