vr-shopxo-plugin/plan.md

4.9 KiB
Raw Blame History

vr-shopxo-plugin 安全审计与路由修复方案

版本v1.0Round 1 初稿)| 日期2026-04-16 | Agentcouncil/SecurityEngineer 背景Phase 2 后台两个致命问题——侧栏乱码 + 路由无法渲染


问题摘要

# 症状 根因推测 优先级
P1 侧栏显示 VR票务 而非 VR票务 数据库/配置字段编码损坏UTF-8→Latin1 misinterpretation P1
P2 访问 adminwatekc.php?s=VrTicket/SeatTemplateList → 空白 "template not exists" 控制器路径错误 + strtolower+ucfirst 匹配失败 P1
P3 视图路径 ../../../plugins/view/... 在容器内无法解析 符号链接绝对路径 vs 相对路径问题 P2

任务清单

阶段一:根因分析与方案设计

  • S1.1 读取 vrt_power 表的 name 字段值,检查是否为乱码的 Latin1 字节序列
  • S1.2 检查 plugins 表中 vr_ticket 条目的 name / title 字段编码
  • S1.3 对比正常插件freightfeeplugins 表记录,找出字段差异
  • S1.4 读取 vr_ticket 插件根目录 config.json检查其中 name/title 字段编码
  • S1.5 读取 ShopXO 核心 Plugins/Index.php,确认 strtolower+ucfirst 类名匹配逻辑
  • S1.6 对比 freightfee/Admin.php根目录vs vr_ticket/SeatTemplate.php子目录的命名模式
  • S1.7 检查 freightfee 的视图路径引用方式(相对 vs 绝对)

阶段二:修复实施

  • S2.1 修复乱码:如果 config.json 中文损坏,重写正确的 name/title
  • S2.2 修复路由:按 freightfee 模式,在 vr_ticket 根目录创建 Admin.php删除子目录控制器
  • S2.3 修复视图路径:采用 freightfee 的相对路径方式
  • S2.4 验证 strtolower+ucfirst 匹配:确认 VrTicket vs Vrticket 类名大小写问题

阶段三:验证

  • S3.1 访问 adminwatekc.php?s=VrTicket/SeatTemplateList,截图确认内容区正常渲染
  • S3.2 截图确认侧栏插件名显示为中文 VR票务 而非乱码
  • S3.3 提交修复 commit 到 council/SecurityEngineer

根因假设与分析

P1 乱码根因分析

假设:数据库 vrt_power.nameplugins.title 字段存储的是经过两次编码的中文字符串:

  • 原始中文 票务 → UTF-8 字节 → 被当作 Latin1 存储 → 解码时又用 UTF-8 → 变成 票务

两种可能路径

  1. 插件安装时,中文 name 被以 Latin1 编码写入 vrt_power
  2. config.json 中的 name 字段本身就是乱码,安装时复制到数据库

修复方案

  • 直接修改数据库中 vrt_power 表和 plugins 表的 name/title 字段
  • 或重写 config.json 的 name 字段为正常中文,重新安装

P2 路由根因分析

ShopXO 核心 Plugins/Index.php 调用插件控制器逻辑大致为:

$class = strtolower(ucfirst($controller_name)); // e.g. "Vrticket" 或 "Vrticketadmin"
$class_file = "$plugin_path/$class.php";        // 期望文件在根目录

vr_ticket 的控制器在 admin/controller/SeatTemplate.php,而 ShopXO 期望 VrTicket.php 在根目录。

正确模式freightfee

freightfee/Admin.php  ← 根目录,类名 = "Admin"
freightfee/Hook.php

错误模式vr_ticket

vr_ticket/admin/controller/SeatTemplate.php ← 子目录,类名 = "SeatTemplate"

修复方案:在 vr_ticket 根目录创建 Admin.php 作为主入口,参考 freightfee/Admin.php 结构。

P3 视图路径分析

freightfee 用相对路径 ../../../plugins/view/...,这是相对于 PHP 文件位置计算的。当 ShopXO 运行时,其 working directory 是 web root所以这个相对路径能正确解析到 ROOT/plugins/view/...

安全关注点

  • 硬编码 ../../../ 路径可能在不同部署环境下失效
  • 如果插件视图路径拼接时未做 sanitize可能存在路径遍历风险低风险因为 ShopXO 有基础过滤)

依赖关系

  • S1.1S1.7 全部完成前,不进行 S2.x 修复
  • S2.2 和 S2.3 可并行执行
  • S3.x 需要在 main 分支合并后执行

claim 状态

任务 claim
S1.1S1.7 [Claimed: council/SecurityEngineer]
S2.1S2.4 [Claimed: council/SecurityEngineer]
S3.x [Claimed: council/SecurityEngineer]

GitHub 参考插件分析

如果有时间可检查以下插件结构ShopXO 应用商店中已验证可用的后台插件):

  1. freightfee — 根目录 Admin.php直接继承 think\Controller
  2. answers — freightfee 子插件,同一结构
  3. 任何带 admin/view/ 的插件

关键发现:所有正常工作的 ShopXO 插件都使用根目录 Admin.php 模式,不使用子目录控制器。


约束

  • 必须截图验证所有修复
  • 先解决路由P2再解决乱码P1
  • 不在无充分证据时修改数据库字段