# 高危漏洞修复功能检查清单

> **对应批次**：2026-08-06 08:54:02 ~ 08:54:07  
> **仓库**：`ylrz_his_scrm_java`  
> **提交数量**：10 个 security/docs fix commit  
> **作者**：吴树波  
> **用途**：测试 / 自检勾选；配套报告见同目录 `高危漏洞修复报告.md`  
> **说明**：本批为高危安全加固（无业务新功能、无本批 SQL 脚本）。`companyUI` / `adminUI` 当日上午无对应 08:54 提交。

---

## 一、本批提交简表

按时间从早到晚：

| # | Hash（短） | 时间 | Message |
|---|------------|------|---------|
| 1 | `9d0c68c9` | 08:54:02 | fix(security): 修复SQL注入风险 |
| 2 | `c9551cfb` | 08:54:03 | fix(security): 修复上传路径穿越与SSRF |
| 3 | `cbe52d3c` | 08:54:03 | fix(security): 禁用登录后门并收敛匿名放行 |
| 4 | `49b3cd07` | 08:54:04 | fix(security): 修复会员与名片数据越权 |
| 5 | `909d908a` | 08:54:04 | fix(security): 修复支付回调与跨租户重置密码 |
| 6 | `2d0c50a8` | 08:54:06 | fix(security): 修复XXE风险 |
| 7 | `78ba1b49` | 08:54:06 | fix(security): 关闭Fastjson AutoType并移除硬编码云密钥 |
| 8 | `1aaf380e` | 08:54:07 | fix(security): 修复命令注入风险 |
| 9 | `e4e18fbe` | 08:54:07 | fix(security): 禁止html上传并加固剩余上传入口 |
| 10 | `c1600cf7` | 08:54:07 | docs: 新增高危漏洞修复报告 |

**一句话归纳**：SQL 白名单、上传/SSRF、登录后门与匿名放行收敛、销售会员/名片越权、支付回调与重置密码、XXE、Redis Fastjson AutoType、短信密钥外置、命令注入、禁止 html 上传。

---

## 二、环境前提（测本批前必读）

| # | 前提项 | 说明 |
|---|--------|------|
| 1 | 重启后端 | 涉及 `fs-framework` Security、`fs-common` 工具类、多端 Controller；至少重启 admin、user-app、company / company-app、store、qw-api 等实际部署节点 |
| 2 | 无需本批 SQL | 无表结构变更，不必执行本批 DDL/DML |
| 3 | 短信密钥 | `tencent.cloud.secret-id` / `secret-key` 须配置（环境变量 `TENCENT_CLOUD_SECRET_ID` / `TENCENT_CLOUD_SECRET_KEY` 或 yml）；未配置则发短信报「腾讯云短信密钥未配置」 |
| 4 | 后门已禁用 | 万能验证码已清空；`/loginByUserId`、`/loginTest` 固定 **403**。请用真实短信，勿再依赖旧后门 |
| 5 | 清 Token 重登 | 建议清浏览器/App 旧 Token 后重登；匿名已取消的接口未带 Token 会 **401** |
| 6 | Redis / AutoType | 各端 Fastjson **关闭 AutoType**；若出现反序列化异常，清相关 key 或整库测试 Redis 后重登 |
| 7 | 销售端鉴权说明 | `fs-company-app` 仍为 `/** permitAll` + `@Login` 拦截（未改为 Spring 强鉴权）；销售登录 401 优先查 **拦截器/JWT/网关**，不要只盯 admin 的 `SecurityConfig` |

---

## 三、按模块检查表

检查结果列请填写：`通过` / `失败` / 备注。

### 1. 用户登录 / Token / 匿名放行（`cbe52d3c`）

| 检查目的 | 操作步骤 | 预期结果 | 失败排查 | 检查结果 |
|----------|----------|----------|----------|----------|
| 正常短信登录可用 | App/H5：发验证码 → 登录 | 成功拿到 Token，可进首页 | 接口：登录 Controller（如 `/app/...` 短信登录）；Redis `sms:code:{手机}`；短信密钥配置；日志是否「验证码错误/过期」 |  |
| 万能验证码失效 | 用历史固定码（如原 `EdisonX!@#.+-123`）登录 | 失败（验证码错误/过期） | 确认已部署新包；`INTERNAL_LOGIN_CODE` 为空 |  |
| 验证码一次性 | 同一验证码登录成功后再登一次 | 第二次失败 | Redis 是否仍有 `sms:code:`；成功路径应 `deleteObject` |  |
| 改密防刷 | 故意错验证码 ≥5 次后改密 | 提示「错误次数过多，请30分钟后再试」 | Redis `sms:fail:{手机}` TTL 30 分钟 |  |
| 后门禁用 | POST `loginByUserId` / `loginTest` | **403**「该接口已禁用」；日志 warn | 是否打到旧节点；日志关键字 `已禁用的高危接口` |  |
| 原匿名上传需鉴权 | 无 Token 调 `/common/uploadOSS**`、`uploadWang`、`chat/upload/uploadFile`、`download**`、`unbindQwUserByServerIds` | **401**（需认证） | `SecurityConfig` 是否生效；网关是否绕过 |  |
| 支付/回调仍可匿名 | 无 Token 访问仍应匿名的支付/短信等路径（配置里保留的） | 能进回调逻辑（签名另验） | 对比 `SecurityConfig` 仍保留的 `.anonymous()` 列表 |  |
| Swagger/Druid | 生产环境无 Token 访问 swagger/druid | 应 **401**，不可再匿名打开 | 若仍通：可能未重启或另有网关放行 |  |

### 2. 销售端会员 / 名片 / 权限（`49b3cd07`）

| 检查目的 | 操作步骤 | 预期结果 | 失败排查 | 检查结果 |
|----------|----------|----------|----------|----------|
| 改自己名下会员 | 销售 A 改归属自己的会员昵称/备注 | 成功 | company-app 日志；`FsUserController`；关系表 `fs_user_company_user` |  |
| 越权改他人会员 | 销售 A 用 B 的会员 id 调修改/启停 | 「无权操作该会员」 | 是否带正确 Token；`checkUserCompanyUserOwnership` |  |
| 批量启停 | 批量含他人联系人 id | 整批拒绝 | 同上 |  |
| 删自己名片 | 删本人 cardId | 成功 | `UserController.delMyCard` |  |
| 越权删名片 | 删他人 cardId | 「无权删除他人名片」或名片不存在 | 同上 |  |
| getUserList 需登录 | 无 `@Login` Token 调 `/getUserList` | 按拦截器失败（未登录） | company-app `@Login` 拦截器、Token 头 |  |
| 改同事状态 | 非管理员 / 跨公司调 `changeUserState` | 「仅管理员」或「无权操作其他公司用户」 | 操作者 `isAdmin`、`companyId` |  |

**销售登录 401 补充**：本批未改 company-app 的 `permitAll`。若登录后业务接口 401：查 JWT 是否写入、拦截器白名单、网关鉴权；对比是否误走了 admin `SecurityConfig` 域名。

### 3. 支付回调与后台重置密码（`909d908a`）

| 检查目的 | 操作步骤 | 预期结果 | 失败排查 | 检查结果 |
|----------|----------|----------|----------|----------|
| 微信回调单笔单账 | 各业务前缀订单真实/沙箱支付（inquiry/store/package/course/appvip/integral/product/payment） | 仅对应业务入账一次，无串账 | `WxPayController` 日志；订单状态；未知前缀有 warn |  |
| 汇付回调验签 | 合法回调 vs 篡改 sign/空 sign | 合法成功；非法返回 `fail`，error 日志「验签失败」 | `/hfPayNotify`；`BasePay.HUIFU_DEFAULT_PUBLIC_KEY`；日志 `汇付回调` |  |
| 跨租户重置密码 | 无数据权限账号重置他租户用户密码 | 被 `checkUserDataScope` 拦截 | admin `SysUserController.resetPwd`；数据权限配置 |  |

### 4. 上传 / 路径穿越 / 禁 html（`c9551cfb` + `e4e18fbe`）

| 检查目的 | 操作步骤 | 预期结果 | 失败排查 | 检查结果 |
|----------|----------|----------|----------|----------|
| 正常图片/文档/音视频上传 | 各端常用上传（jpg/png/pdf/mp4 等） | 成功返回 URL | `OssUploadSecurityUtils`；文件后缀白名单 |  |
| 拒绝 html/htm/jsp | 上传 `.html`/`.htm` | 失败（不支持类型） | `MimeTypeUtils` 已去掉 html；各 upload 入口 |  |
| 路径穿越文件名 | 文件名含 `../`、`\` | 拒绝「文件名非法」 | OSS 工具类校验 |  |
| 达人上传需登录 | 无 Token 调达人 `uploadOSSTalent` | 未登录失败；登录后正常 | `TalentController` `@Login` |  |
| 知识库文件名 | 上传带特殊字符中文名 | 清洗后可上传，过长截断 | `ChatDatasetFileController` |  |

### 5. SSRF / 声纹 / FastGpt（`c9551cfb`）

| 检查目的 | 操作步骤 | 预期结果 | 失败排查 | 检查结果 |
|----------|----------|----------|----------|----------|
| 内网 URL 拒绝 | 声纹/拉 URL 填 `http://127.0.0.1` 或内网 IP | 「禁止访问内网或本地地址」 | `UrlSecurityUtils`；`CompanyUserController` / FastGpt `urlToFile` |  |
| 合法公网 HTTPS | 正常公网资源 | 仍可用 | DNS/网络；是否误伤内网依赖（若有） |  |

### 6. SQL 注入防护（`9d0c68c9`）

| 检查目的 | 操作步骤 | 预期结果 | 失败排查 | 检查结果 |
|----------|----------|----------|----------|----------|
| 订单列表正常排序 | 商城/直播订单列表 asc/desc | 列表正常 | 对应订单列表接口；参数 `sortOrder` |  |
| 非法 sortOrder | 传 `asc;drop...` 等 | 业务异常「排序方向非法」 | `SqlSafeUtils.validateOrderDirection` |  |
| 直播趋势 category | 合法：`page_views` 等；非法字符串 | 合法出图；非法拒绝 | `LiveDataServiceImpl`；白名单五列 |  |

### 7. 企微 XML / XXE（`2d0c50a8`）

| 检查目的 | 操作步骤 | 预期结果 | 失败排查 | 检查结果 |
|----------|----------|----------|----------|----------|
| 正常企微回调 | 触发正常消息/事件回调 | 解析成功、业务照常 | `QwController`、`XMLParse` |  |
| （安全）带 DOCTYPE 的恶意 XML | 若可测 | 解析失败，不读外部实体 | 应用日志 Parser 异常 |  |

### 8. Redis Fastjson AutoType / 短信密钥（`78ba1b49`）

| 检查目的 | 操作步骤 | 预期结果 | 失败排查 | 检查结果 |
|----------|----------|----------|----------|----------|
| 登录与缓存读写 | 登录、读用户缓存、常见列表 | 无 AutoType 反序列化炸栈 | 异常堆栈含 Fastjson；清 Redis 后重试 |  |
| 短信发送 | 配置密钥后发验证码 | 成功 | 未配置则明确错误；查 yml/环境变量 |  |

### 9. 音视频 / 直播命令执行（`1aaf380e`）

| 检查目的 | 操作步骤 | 预期结果 | 失败排查 | 检查结果 |
|----------|----------|----------|----------|----------|
| 语音转 silk / ffmpeg 相关 | 走原语音消息转换、点播转码、直播推流 | 功能与改前一致 | 服务器是否有 silk/ffmpeg；`ProcessBuilder` 相关 ERROR 日志；路径含空格场景 |  |

---

## 四、相邻批（非本批，勿与 08:54 混验）

若联调覆盖「小程序校验文件 / 飞书 Redis」，请按 **2026-08-05 下午** 单独验证：

| 仓库 | Hash | 时间 | Message |
|------|------|------|---------|
| java | `7fd8ce05` | 08-05 **16:24** | 删除不用的配置文件，销售端新增小程序，上传校验文件（含 `uploadMiniappVerifyFile`、`FeiShuService` Redis 索引失效） |
| companyUI | `2e1aad25` | 08-05 **16:33** | 同上（播放源配置：添加小程序、上传校验文件 UI） |

### 【相邻批】小程序校验文件（08-05，非 08:54）

| 检查目的 | 操作步骤 | 预期结果 | 失败排查 | 检查结果 |
|----------|----------|----------|----------|----------|
| 销售后台上传校验文件 | companyUI「播放源配置」→ 上传校验文件 | 原名落盘；列表显示 `verifyFileName` | 后端 `POST /app/common/uploadMiniappVerifyFile`；配置 `fs.miniappVerifyPath`；落盘机磁盘权限；common-api 日志 |  |
| 微信校验可访问 | 用微信要求的 URL 访问校验文件 | HTTP 200、内容正确 | Nginx/静态目录是否指向同一路径 |  |

### 【相邻批】飞书 Redis 缓存（08-05，非 08:54）

| 检查目的 | 操作步骤 | 预期结果 | 失败排查 | 检查结果 |
|----------|----------|----------|----------|----------|
| 创建免授权文档缓存 | 生成飞书直链文档 | Redis 有 `feishu:direct_doc:*`，并登记 `feishu:direct_doc:index:*` | `FeiShuService` 日志「创建并缓存飞书免授权文档」 |  |
| 一键群发强制刷新 | 补发/强制刷新飞书链接 | 旧缓存删除，`usedIndex=true` 时按索引删；日志「删除完成」 | 日志字段 `usedIndex`/`deleted`；勿再依赖 SCAN；索引缺失时走有界兜底（最多 shard 500） |  |

---

## 五、建议冒烟顺序

1. 配置短信密钥并重启相关后端  
2. 用户真实短信登录（含后门 403、万能码失效抽检）  
3. 销售端会员/名片：正常操作 + 越权各一单  
4. 常用上传（正常类型成功；html 拒绝）  
5. 一笔支付回调（有环境再测；汇付验签抽检）  
6. 订单列表排序（正常 asc/desc + 非法 sortOrder）  
7. （若已发 8/5）小程序校验文件与飞书刷新  

---

## 六、文档与提交说明

| 项 | 说明 |
|----|------|
| 报告文档 | `c1600cf7` 新增 `docs/高危漏洞修复报告*.md`，联调时以报告为修复依据 |
| 本文件 | 功能检查勾选表，可直接打印或复制到测试用例库 |

检查人：__________　日期：__________　环境：__________