68 lines
2.4 KiB
Markdown
68 lines
2.4 KiB
Markdown
# Plan — vr-shopxo-plugin 安全评估 + 票务链路审计
|
||
|
||
> 版本:v2.0 | 日期:2026-05-26 | Agent:council/SecurityEngineer
|
||
|
||
---
|
||
|
||
## Round 2 安全评估更新
|
||
|
||
### 新增发现:P3 XSS — `$goods['content']` 未转义
|
||
|
||
**文件**:`ticket_detail.html:75`
|
||
|
||
```php
|
||
<?php echo $goods['content']; ?> // ← admin-rich-text,直接输出
|
||
```
|
||
|
||
ShopXO 富文本编辑器输出。管理员可注入恶意 JS。仅管理员可编辑,风险范围有限。
|
||
|
||
**修复**:改为 `<?php echo htmlspecialchars($goods['content']); ?>` 或在后端对富文本做 XSS 过滤。
|
||
|
||
**结论**:P3(管理面可控),不影响票务安全链路。
|
||
|
||
---
|
||
|
||
### Round 2 验证:QR 签名完整链路确认
|
||
|
||
| 步骤 | 代码 | 状态 |
|
||
|------|------|------|
|
||
| `signQrPayload` 含 `code` 字段 | `BaseService.php:493` | ✅ 已确认 |
|
||
| 签名包含 `iat` + `exp` | `BaseService.php:493` | ✅ 30分钟有效 |
|
||
| `verifyQrPayload` 验证过期 | 需检查验证端 | ⚠️ 待确认 |
|
||
| `BaseService::getVrSecret()` 硬编码 | `BaseService.php:302` | ⚠️ P1(生产需确认.env) |
|
||
| `clearCache` 在 `$count > 0` 后调用 | `TicketService.php:126` | ✅ 正确(但 `$goodsId` 未定义) |
|
||
|
||
### Bug:`ClearCache` 调用时 `$goodsId` 未定义
|
||
|
||
**文件**:`TicketService.php:126`
|
||
|
||
```php
|
||
SeatMapService::ClearCache(intval($goodsId)); // $goodsId 未在作用域内定义
|
||
```
|
||
|
||
这是 `onOrderPaid` 中的 Bug,`$goodsId` 应从 `$og['goods_id']` 获取。当前代码会传递 `0`,清除无效。
|
||
|
||
**严重度**:P3(不影响票务安全,但 seatmap 缓存不会被清除)
|
||
|
||
---
|
||
|
||
## 安全评估结论摘要
|
||
|
||
| # | 问题 | 严重性 | 状态 |
|
||
|---|------|--------|------|
|
||
| S-1 | issueTicket() 并发竞态(无悲观锁) | **P0 建议** | 建议加唯一索引 `(order_id, seat_info)` |
|
||
| S-2 | QR Secret 硬编码 fallback | **P1** | 需确认生产环境 `.env` 配置 |
|
||
| S-3 | FOR UPDATE SKIP LOCKED 概念混淆 | **P2** | 防超卖依赖ShopXO原子UPDATE已有效 |
|
||
| S-4 | onOrderPaid 无事务包装 | **P2** | 可接受(有幂等保护) |
|
||
| S-5 | `$goods['content']` XSS(admin可控) | **P3** | 管理面风险,建议转义 |
|
||
| S-6 | `$goodsId` 未定义导致 `ClearCache` 失效 | **P3** | Bug,不影响票务链路 |
|
||
|
||
**无 P0 安全漏洞。支付链路整体安全,不应成为主攻方向阻塞项。**
|
||
|
||
---
|
||
|
||
## 投票
|
||
|
||
**议题:下一步主攻方向**
|
||
**投票:C(双线并行)**(Round 2 确认,不变)
|