[审计]SoSite V3.8.0 代码深度审查报告

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

本文由 FlintHub 开发文档归档发布。原始文档日期见标题前缀,来源:检查结果.md。

SoSite V3.8.0 代码深度审查报告

审查时间:2026-07-08

审查范围:全部 PHP / CSS / JS 文件(150+ 个文件)

审查维度:安全 / 逻辑 / 冗余 / 关联性


一、总体评估

维度评分说明
安全45/100多处高危:数据库弱密码硬编码、模板缓存竞态条件可致代码注入、install.php SQL 注入、CSRF 防护不完整、SSRF 防护可绕过、多插件 AdminController 无权限校验
逻辑60/100$thread 未定义变量导致"楼主删回复"功能完全失效;User::deleteWithCascade 删除顺序错误致关联数据清理失败;Admin/ThemeController::setDefault 条件逻辑反转;权限过滤逻辑跨模块不一致
冗余55/100database/init.php 与 protected/database/init.php 大量重复;Controller 安全头重复;插件 activate/init_after 双重建表;Emoji 双映射表;Helper 与 Model 职责重叠
关联性50/100版本号不一致(V3.8.0 vs V4.0.0);dev_docs 命名空间大小写不一致(Linux 致命);SQLite 兼容性不完整;路由注册缺少 require_once;分页条数来源不一致

综合评分:52/100(中等偏下)


二、高危问题清单(17 项)

H-01 | 数据库弱密码硬编码

  • 文件:config.php:9
  • 代码:define('DB_PASS', '123456');
  • 描述:数据库密码硬编码为弱密码 123456,且该文件位于 Web 可访问目录,若服务器配置不当可直接暴露密码
  • 修复:使用强密码;将 config.php 移至 Web 根目录外;Web 服务器配置禁止访问

H-02 | 模板缓存竞态条件(可致任意代码执行)

  • 文件:app/Core/TemplateCompiler.php:216-226
  • 代码:file_exists 检查后无锁地 file_put_contents 缓存文件,然后 require 该文件
  • 描述:TOCTOU 竞态条件:并发请求可能 require 到部分写入的缓存文件,导致 PHP 解析错误或代码注入;file_put_contents 非原子操作
  • 修复:使用临时文件 + rename(原子操作)替代直接 file_put_contents;或使用 flock 加文件锁

H-03 | 模板编译 {if} 条件表达式无安全过滤

  • 文件:app/Core/TemplateCompiler.php:155-159
  • 代码:cbIf() 和 cbElseif() 直接将模板变量嵌入 PHP 代码,无安全过滤
  • 描述:若主题上传功能允许上传自定义模板,攻击者可构造恶意模板文件注入 PHP 代码
  • 修复:对 {if} / {elseif} 表达式做语法白名单校验;禁止用户上传自定义模板

H-04 | install.php 数据库名 SQL 注入

  • 文件:protected/database/install.php:106
  • 代码:$pdo->exec("CREATE DATABASE IF NOT EXISTS {$dbname} ...")
  • 描述:$dbname 来自用户 POST 输入,仅经 trim() 未做格式校验,可构造恶意数据库名逃逸反引号
  • 修复:preg_match('/^[a-zA-Z0-9_]+$/', $dbname) 白名单校验

H-05 | install.php DSN 注入

  • 文件:protected/database/install.php:103-104
  • 代码:$dsn = "mysql:host={$host};port={$port}"
  • 描述:$host 和 $port 来自用户 POST 输入,直接拼入 DSN 字符串,可注入额外 DSN 参数
  • 修复:对 $host 做域名/IP 校验;$port 做 (int) 转换并检查 1-65535 范围

H-06 | database/init.php 表名 SQL 拼接

  • 文件:database/init.php:119 / protected/database/init.php:98
  • 代码:$stmt = $conn->query("SHOW COLUMNS FROM {$tableName}")
  • 描述:$tableName 直接拼接进 SQL,addColumnIfNotExists() 的 $column 和 $definition 同理,与 tableExists() 的白名单校验不一致
  • 修复:对所有动态标识符做正则白名单校验

H-07 | Session use_strict_mode = 0

  • 文件:config.php:33
  • 代码:ini_set('session.use_strict_mode', 0);
  • 描述:接受客户端提供的任意 session ID,存在 Session Fixation 攻击风险。install.php 生成的新 config.php 设为 1,当前配置不一致
  • 修复:改为 ini_set('session.use_strict_mode', 1);

H-08 | settings_cache.php 安全数据明文存储

  • 文件:protected/settings_cache.php:16
  • 代码:'captcha_salt' => '7ad552abb3ca545aa9719885077e1b36'
  • 描述:验证码 salt 硬编码在缓存文件中且以明文存储;登录锁定信息也持久化到缓存文件
  • 修复:salt 从环境变量或独立配置读取;登录锁定状态应存于数据库/Redis

H-09 | ApiController::upload 缺失 CSRF 验证

  • 文件:app/Controllers/ApiController.php:86-121
  • 描述:upload 方法完全缺失 CSRF 验证,攻击者可构造恶意页面上传任意文件。同文件中 vote 方法有 CSRF 校验,upload 遗漏
  • 修复:添加 Csrf::verifyOrDie($_POST['csrf'] ?? '')

H-10 | ThemeController::settings 三重安全缺陷

  • 文件:app/Controllers/ThemeController.php:16-22
  • 描述:(1) 无 CSRF 验证;(2) 无登录检查;(3) $theme 值未与可用主题列表校验,可能导致路径遍历
  • 修复:添加 Csrf::verifyOrDie() + requireLogin() + Theme::getAvailable() 白名单校验

H-11 | ThreadController::delete $thread 未定义变量

  • 文件:app/Controllers/ThreadController.php:273
  • 代码:$isOp = (int)$thread['user_id'] === (int)$currentUser['id'];
  • 描述:$thread 在此时未定义(282行才赋值),导致"楼主删回复"功能完全失效
  • 修复:在 273 行之前查询 thread 信息

H-12 | Admin/DatabaseController::mysqlImport 可执行任意 SQL

  • 文件:app/Controllers/Admin/DatabaseController.php:62,126-145
  • 描述:导入的 SQL 文件被直接 exec() 执行,可执行任意 SQL 语句;SQL 解析器极其简陋;catch 块静默吞掉错误
  • 修复:增加额外密码确认或独立 CSRF token;使用 mysql 命令行工具替代手工解析;移除空 catch

H-13 | Content.php PHP 标记还原为原始文本

  • 文件:app/Helpers/Content.php:104-117
  • 描述:还原 PHP 标记时将占位符还原为 <?php 和 <?= 原始文本而非 HTML 实体,在错误配置下可能触发代码注入
  • 修复:PHP 标记也应还原为 HTML 实体

H-14 | Captcha fallback 盐值可预测

  • 文件:app/Helpers/Captcha.php:30-32
  • 代码:return \hash('sha256', 'SoSiteCaptcha_' . \__DIR__);
  • 描述:fallback 盐值基于 __DIR__ 和固定字符串,可预测性极高
  • 修复:fallback 使用 random_bytes(16) 或强制从 settings 表读取

H-15 | Upload Imagick readImageBlob 未限制格式

  • 文件:app/Helpers/Upload.php:122
  • 描述:Imagick 的 readImageBlob 可处理 SVG/MSL/MVG 等危险格式,可能触发 RCE
  • 修复:在 Imagick 读取前明确限制格式

H-16 | User::deleteWithCascade 删除顺序错误

  • 文件:app/Models/User.php:230-283
  • 描述:先删除 threads/posts 后再删除投票和附件,导致子查询返回空集,投票和附件清理完全失效
  • 修复:调整顺序为:投票 -> 附件 -> posts -> threads -> 其他 -> 用户

H-17 | 多插件 AdminController 无权限校验

  • 文件:plugins/announcements/AdminController.php、content_review/AdminController.php、friend_links/AdminController.php、seo/AdminController.php
  • 描述:多个 AdminController 没有任何管理员权限校验,若路由中间件被绕过,任何登录用户可管理插件
  • 修复:所有 AdminController 每个方法开头添加 requireAdmin()

三、中危问题清单(50 项)

核心层(13 项)

  1. M-01 config.php 版本号 V3.8.0 vs install.php 生成 V4.0.0
  2. M-02 Session 存储双轨并存(config.php 文件 session vs init.php MySQL session)
  3. M-03 index.php 插件路由 {name} 参数未白名单校验,路径遍历风险
  4. M-04 API 路由 /api/vote、/api/upload 无 CSRF;/api/fetch-image SSRF 风险
  5. M-05 Autoloader 路径穿越检查不充分(只过滤 .. 未过滤绝对路径)
  6. M-06 Controller::view() 每次创建新 TemplateCompiler,忽略全局实例
  7. M-07 Controller 安全头重复且 viewRaw() 缺少 CSP/Permissions-Policy
  8. M-08 Database 连接失败直接 echo + exit,可被 DoS 利用
  9. M-09 Model::insert 列名未校验,key 含反引号可逃逸
  10. M-10 Model::buildWhere 允许原始 SQL 条件字符串,绕过参数化查询
  11. M-11 Router ?r= 参数仅阻止 admin 前缀,未阻止其他敏感路径
  12. M-12 Router 未验证 REQUEST_METHOD 白名单,REQUEST_URI 可能为 null
  13. M-13 TemplateCompiler detectTheme 每次查数据库 + extract 双重执行

Controller 层(14 项)

  1. M-14 ApiController SSRF DNS Rebinding 绕过 + DNS 失败时校验跳过
  2. M-15 AuthController::resendVerification 无速率限制 + GET 触发邮件
  3. M-16 AuthController::resetPassword tokenValid 逻辑错误致密码重置表单消失
  4. M-17 BlogController 评论内容未 Content::decode()
  5. M-18 ProfileController 权限过滤逻辑与 ForumController/HomeController 不一致
  6. M-19 Admin/SettingsController 数值设置未校验 + SMTP 密码明文存储
  7. M-20 Admin/ThemeController CSS 注入过滤不充分
  8. M-21 Admin/ThemeController setDefault 条件逻辑错误(|| 应为 &&)
  9. M-22 Admin/ThemeController 主题上传空文件名风险
  10. M-23 Admin/ThreadController edit 缺失 CSRF
  11. M-24 PostController 异常消息泄露数据库信息
  12. M-25 ThreadController 颜色值未校验致 CSS 注入
  13. M-26 Admin/DatabaseController 备份大表内存溢出
  14. M-27 ThreadController 分页条数来源不一致(常量 vs Settings)

Helper/Model 层(10 项)

  1. M-28 Csrf Token 全 Session 不变,泄露后可反复使用
  2. M-29 Content.php javascript: 协议检测可绕过(空白字符 + HTML 实体变体)
  3. M-30 Plugin::executeHook 使用 extract + include,暴露内部变量
  4. M-31 RateLimiter 基于 Session 易绕过(清 Cookie 即获新配额);CRC32 碰撞
  5. M-32 RememberMe 用户 ID 存 Cookie 暴露内部结构
  6. M-33 Category Model 使用 unserialize 反序列化缓存,对象注入风险
  7. M-34 Search.php 允许 * 通配符搜索致全表扫描 DoS
  8. M-35 Thread/User Model LIKE 通配符未转义;User::search 返回含密码哈希等敏感字段
  9. M-36 Settings::require 缓存文件可执行恶意代码
  10. M-37 Settings::flushCounters 计数器值与内存缓存可能不同步

插件层(13 项)

  1. M-38 qa/AdminController 全部 POST 方法无 CSRF
  2. M-39 seo custom_head 直接 echo 致全站 XSS
  3. M-40 seo sitemap XML 未转义 $siteUrl
  4. M-41 content_review 仅前端隐藏非数据库隐藏,可通过 API 访问
  5. M-42 invite 邀请码无速率限制且明文存储
  6. M-43 content_review 通知标题含帖子标题未转义
  7. M-44 content_review reason 字段复用为头像路径
  8. M-45 red_packet 退回操作无行锁
  9. M-46 daily_checkin 签到并发竞态
  10. M-47 invite 积分消耗可自定义无上限
  11. M-48 red_packet 分配边界缺陷
  12. M-49 edit_info/daily_checkin 建表逻辑不一致
  13. M-50 post_favorite/invite 路由注册缺少 require_once

四、高危关联性问题(2 项)

A-01 | dev_docs 命名空间大小写不一致(Linux 致命)

  • 文件:plugins/dev_docs/AdminController.php(Plugin\DevDocs)vs Plugin.php(Plugin\dev_docs)
  • 描述:Windows 不区分大小写所以正常运行,但部署到 Linux 时会类找不到致命错误
  • 修复:统一为 Plugin\DevDocs

A-02 | install.php CSRF/安全缺陷

  • 文件:protected/database/install.php:441-460
  • 描述:delete_install action 无 CSRF 校验;明文密码存 Session;安装锁仅 file_exists 检查

五、低危与建议级问题(42 项)

  1. config.php Session GC 并发 race condition
  2. index.php /index.php 路由冗余
  3. init.php 步骤编号重复(三个步骤4)
  4. init.php Session 过期时间硬编码 30 分钟 vs gc_maxlifetime 24 分钟
  5. Autoloader 闭包每次重建
  6. Controller::viewRaw 重复调用 RememberMe::check()
  7. Database::getDbType 硬编码返回 mysql
  8. Model::update 非法 key 静默跳过不报错
  9. TemplateCompiler realpath 返回 false 未检查
  10. database/init.php 与 protected/database/init.php 大量重复代码
  11. install.php SQL 解析器无法处理含分号的字符串
  12. install.php CSRF token 未用 json_encode 输出到 JS
  13. rebuild_runtime.php exec 调用 + 无 HTTP 访问限制
  14. BlogController 浏览数 POST 时也递增 + cover_image 未用 basename
  15. ThreadController incrementView 在 POST 时也递增 + $currentUser 重复赋值
  16. Admin/BaseController rtrim 后冗余条件
  17. Admin/TrashedController 死变量
  18. Admin/LevelController 成功消息 redirect 后丢失
  19. ApiController upload 分支结构冗余
  20. ForumController/HomeController Controller 层做 HTML 转义(应由 View 负责)
  21. TagsController 权限过滤在分页后导致每页条数不固定
  22. MessageController 私信发送无速率限制
  23. Auth::isAdmin role + group_id 双条件 fallback 值问题
  24. Auth::requireAdminVerify 仅依赖 Session 无服务端绑定
  25. Mailer 非加密连接时 AUTH LOGIN 凭据暴露
  26. Emoji QQ_MAP 和 QQ_LIST 重复数据
  27. Theme 预览功能无权限检查 + Cookie 缺 secure 属性
  28. Upload MIME 映射表不覆盖 ALLOWED_EXTENSIONS 全部类型
  29. Vote toggle() 绕过 Database::query() 直接用 prepare
  30. Settings::require 缓存文件可执行恶意代码
  31. Settings::flushCounters 计数器值与内存缓存可能不同步
  32. Settings::updateOnlineStatus 每次请求都清理过期记录
  33. Blog::batchDelete 无事务保护
  34. Thread::batchDelete 未删除缩略图
  35. Message::deleteOwned 一方删除导致双方都看不到
  36. Permission getAuthorizedCategoryIds 与 check 重复逻辑
  37. Search searchMySQLFulltext 与 searchLIKE 结构重复
  38. Points::award 无事务保护
  39. friend_links/AdminController 重复的 session 赋值行
  40. content_review/hook/nav_main_links.php 已废弃但仍注册
  41. daily_checkin/hook/nav_user_menu_items.php 已废弃但仍注册
  42. edit_info 两个编辑钩子高度重复代码

六、View 层安全问题摘要

  • auth/login.php:多处未转义输出存在 XSS($_GET['error']、$_GET['redirect'] 直接输出)
  • invite/index.php:$inviteCode 和 $errorMsg 未转义
  • layouts/main.php:40:custom_css 直接输出 <style> 标签,CSS 注入风险
  • thread/show.php:多处用户输入直接输出
  • blog/detail.php:评论内容渲染安全性取决于 Content::decode 实现
  • admin/user_edit.php:custom_css 字段直接输出

七、CSS/JS 前端问题摘要

CSS 冗余

  • 4 套侧边栏样式重复定义(admin.css + forum.css + pages.css + layout.css)
  • 10 组样式属性冲突(同一选择器在不同文件中定义不同值)
  • 主题 CSS 中大量 !important 覆盖(至少 12 处)

JS 安全

  • script.js:AJAX 请求应统一 CSRF token 处理
  • editor.js:编辑器内容应在前端做基础校验
  • vote.js:投票结果应防重复提交

八、修复计划

阶段一:紧急安全修复(P0 - 立即执行)

编号修复项涉及文件
H-02模板缓存竞态 -> 临时文件+renameTemplateCompiler.php
H-04install.php SQL 注入 -> 白名单校验install.php
H-05install.php DSN 注入 -> 类型校验install.php
H-07session.use_strict_mode = 1config.php
H-09upload CSRF -> 添加 verifyOrDieApiController.php
H-11$thread 未定义 -> 提前查询ThreadController.php
H-13PHP 标记还原 -> HTML 实体Content.php
H-16deleteWithCascade 顺序 -> 重排User.php
H-17AdminController 权限校验 -> requireAdmin多个插件文件
A-01dev_docs 命名空间 -> 统一大写Plugin.php

阶段二:高危安全加固(P1 - 3天内)

编号修复项涉及文件
H-01数据库弱密码 -> 强密码+移出Web目录config.php
H-03模板 {if} 白名单 -> 表达式校验TemplateCompiler.php
H-06表名 SQL 拼接 -> 白名单校验database/init.php
H-08captcha_salt+login_lock -> 安全存储settings_cache.php
H-10ThemeController 三重缺陷 -> CSRF+登录+白名单ThemeController.php
H-12DatabaseController 导入 -> 额外确认+错误报告DatabaseController.php
H-14Captcha fallback 盐值 -> random_bytesCaptcha.php
H-15Imagick 格式限制 -> setFormatUpload.php

阶段三:中危修复(P2 - 1周内)

  • CSRF 遗漏补全(Admin/ThreadController::edit、qa/AdminController、ThemeController::settings)
  • SSRF 防护增强(DNS Rebinding、follow_location)
  • AuthController::resendVerification -> POST + 速率限制
  • AuthController::resetPassword -> tokenValid 逻辑修正
  • Admin/ThemeController::setDefault -> 条件修正
  • Admin/ThemeController CSS 注入 -> 增强过滤
  • Model::insert -> 列名校验
  • Router -> ?r= 白名单 + REQUEST_METHOD 校验
  • Vote::toggle -> 统一使用 Database::query()
  • Thread/User Model LIKE 通配符转义
  • User::search -> 不返回敏感字段
  • 插件 CSRF 遗漏 + 安全加固

阶段四:逻辑与冗余修复(P3 - 2周内)

  • 统一 Session 存储策略(消除双轨)
  • 统一分页条数来源(Settings vs 常量)
  • 统一权限过滤逻辑(空 allowedIds 的语义)
  • Content::decode() 调用统一
  • 删除 database/init.php 重复文件
  • Controller 安全头提取为公共方法
  • Emoji 双映射表合并
  • Helper/Model 职责厘清(Setting、Tag)
  • 插件建表机制统一
  • 清理废弃钩子文件

阶段五:前端优化(P4 - 1个月内)

  • View 层 XSS 修复(login.php、invite/index.php、main.php 等)
  • CSS 侧边栏样式合并
  • CSS !important 清理
  • JS CSRF token 统一处理

九、统计数据

级别安全逻辑冗余关联性合计
高危1420117
中危22164850
低危61810438
建议243110
合计44401714115


本报告仅为检查结果和修复计划,不执行任何修改。等主人指令后按计划逐步修复。

轻量级、高性能、零 MySQL 依赖的PHP社区系统。
| 浏览 1 次 | 回复 0 次

全部回复 (0)

暂无回复

请 登录