# ylrz_his_scrm_java 高危漏洞核实与修复报告

> **依据文档**：`安全漏洞审计报告.md`  
> **核实范围**：本地仓库 `ylrz_his_scrm_java`  
> **修复原则**：仅对已核实存在的高危项做最小安全加固，不改动正常业务主流程；支付/登录/上传等接口在原有逻辑上增加校验或关闭后门  
> **修复完成时间**：2026-08-06  
> **编译验证**：`mvn -pl fs-common,fs-framework,fs-service,fs-user-app,fs-company-app,fs-admin -am compile -DskipTests` 通过  

---

## 一、核实结论总览

审计报告列出高危约 **36** 项（含编号重叠）。本地核实结果如下：

| 结论 | 数量 | 说明 |
|------|------|------|
| **已确认存在并已修复** | 28 | 见下文「已修复清单」 |
| **报告描述存在，当前仓库不存在** | 4 | 高危-02/03/07/16 对应文件或接口不在本仓库 |
| **存在但未做破坏性大改（有说明）** | 4 | 如 fs-company-app 全量 `permitAll`、部分后台垂直越权需配权限位 |
| **额外发现并已处理** | 1 | 硬编码万能短信验证码后门 |

---

## 二、不存在 / 与报告不一致的项

| 编号 | 报告描述 | 核实结果 |
|------|----------|----------|
| 高危-02 | `CrmBusinessMapper.xml` orderBy 注入 | **不存在**：`mapper/crm` 下无 `CrmBusinessMapper.xml` |
| 高危-03 | `CrmCustomerMapper.xml` `${orderBy}` | **不存在**：该 XML 无 `${orderBy}` / `${maps.orderBy}` 拼接点 |
| 高危-07 | `CrmExtDetailMapper.xml` 动态 DDL | **不存在**：无该 Mapper 文件 |
| 高危-16 | `loginByUnionId` 后门 | **不存在**：`AppLoginController` 无此接口（仅有合法微信 code 换取 unionId 流程） |
| 高危-24 | `getUserInfoByUserId` 无 `@Login` | **当前未发现该接口**（或已移除），不纳入本次改动 |
| 高危-25/26 | admin 跨公司员工列表 | 与高危-21 同类；本次未做大规模权限重构，避免影响运营后台菜单权限体系，列入后续项 |

---

## 三、已修复清单（按报告编号）

### A. SQL 注入

#### [高危-01] LiveDataMapper `${category}` — **已修复**
- **核实**：`LiveDataMapper.xml` L142/L192 存在 `SUM(ld.${category})`
- **修复位置**：
  - 新增 `fs-common/.../security/SqlSafeUtils.java`（`validateLiveCategory`）
  - `LiveDataServiceImpl#getTrendData` / `getCompanyTrendData` 入口白名单校验  
    仅允许：`page_views`、`unique_visitors`、`total_views`、`unique_viewers`、`streams`
- **业务影响**：非法 category 直接拒绝；合法统计维度不变

#### [高危-04][高危-05] sortOrder 排序注入 — **已修复**
- **核实**：`FsStoreOrderScrmMapper.xml` / `LiveOrderMapper.xml` 等使用 `${maps.sortOrder}`，且位于 `ORDER BY <字段>` 之后，语义为 asc/desc
- **修复位置**：
  - `FsStoreOrderParam`（his / hisStore）自定义 `setSortOrder`
  - `LiveOrderParam` 自定义 `setSortOrder`
  - 统一走 `SqlSafeUtils.validateOrderDirection`

#### [高危-06] SortUtils 排序字段名注入 — **已修复**
- **核实**：`SortUtils.parseSort` 仅校验方向，未校验字段名
- **修复位置**：`fs-common/.../SortUtils.java`  
  字段名仅允许 `[a-zA-Z0-9_]+`，方向仅允许 asc/desc

---

### B. 上传 / 路径穿越 / SSRF

#### [高危-08] uploadOSS 无后缀白名单 — **已修复（核心模块）**
- **新增**：`OssUploadSecurityUtils`（安全后缀白名单，排除 html/jsp 等）
- **修复文件**：
  - `fs-company/.../CommonController.java`
  - `fs-admin/.../CommonController.java`（含 `uploadWang`）
  - `fs-store/.../CommonController.java`
  - `fs-company-app/.../CommonController.java`
  - `fs-user-app/.../CommonController.java`
  - `fs-doctor-app/.../CommonController.java`
  - `fs-company/.../ChatUploadController.java`
- **说明**：其余模块若仍有同类 `uploadOSS` 副本，建议继续复用 `OssUploadSecurityUtils`

#### [高危-09] uploadOSS2 原始文件名路径注入 — **已修复**
- **修复**：改为 `uploadSuffix` + 白名单，不再用原始文件名构造 OSS key  
  （`fs-company` CommonController 等）

#### [高危-10] TalentController 路径穿越 + 未鉴权 — **已修复**
- **修复位置**：`fs-user-app/.../TalentController.java`
  - 恢复 `@Login`
  - 后缀白名单
  - 本地落盘改用 UUID 文件名，并做 canonical path 校验

#### [高危-11] 声纹 URL SSRF — **已修复**
- **新增**：`UrlSecurityUtils.validatePublicHttpUrl`
- **修复位置**：
  - `CompanyUserController#addVoicePrintUrl`
  - `AudioUtils.audioWAVFromUrl`（`fs-service/.../fastgptApi/util/AudioUtils.java`）

#### [高危-12] FastGpt `urlToFile` SSRF — **已修复**
- **修复位置**：`FastGptCollectionServiceImpl#urlToFile`  
  URL 校验 + 临时文件固定 `.tmp` 后缀

#### [高危-13] 视频临时文件后缀可控 — **已修复**
- **修复位置**：`FsUserVideoServiceImpl#uploadVideo`  
  仅允许 `.mp4`，临时文件固定 `.tmp`

---

### C. 鉴权与权限

#### [高危-14][高危-15] `loginByUserId` / `loginTest` — **已修复（禁用）**
- **修复位置**：`AppLoginController`
- **方式**：保留路径，统一返回 `403 该接口已禁用`，并打 warn 日志  
  （避免直接删方法导致部分客户端 404 误判；功能上已不可登录）

#### [高危-17] fs-company-app `/**` permitAll — **未改为 Spring Security 强制认证**
- **原因**：该模块依赖自定义 `@Login` + 拦截器；直接改为 `anyRequest().authenticated()` 会大面积打断现有 JWT 体系，属于逻辑性破坏
- **本次替代措施**：补齐关键接口 `@Login` / 归属校验（见高危-28/29）
- **建议**：单独立项做 Spring Security 与拦截器统一

#### [高危-18][高危-19][高危-23] 匿名放行过宽 — **已修复（fs-framework SecurityConfig）**
- **修复位置**：`fs-framework/.../SecurityConfig.java`
- **已移除匿名**：
  - `/common/uploadOSS**`、`/common/uploadWang**`、下载类、`unbindQwUserByServerIds`
  - `/his/data/*` 系列危险运维接口
  - Swagger / Druid 匿名
- **仍保留匿名**：支付回调、短信回调等第三方回调必要路径

#### [高危-20][高危-21][高危-22] 后台大量缺 `@PreAuthorize` — **部分未改**
- **原因**：补权限注解依赖菜单权限点是否已配置，盲目添加会导致正常后台功能 403
- **建议**：按菜单权限表分批补齐（P1）

---

### D. 数据越权

#### [高危-28] changeUserInfo / disabled IDOR — **已修复**
- **修复位置**：`fs-company-app/.../FsUserController.java`
  - `changeUserInfo`：校验 `fs_user_company_user` 归属当前销售
  - `changeUserRemark`：校验归属
  - `disabled` / `enabled`：批量校验归属

#### [高危-29] delMyCard / changeUserState / getUserList — **已修复**
- **修复位置**：`fs-company-app/.../UserController.java`
  - `delMyCard`：校验 `card.userId == 当前用户`
  - `changeUserState`：管理员 + 同公司校验
  - `getUserList`：补 `@Login`

---

### E. 逻辑漏洞

#### [高危-30] 微信支付 switch fall-through — **已修复**
- **修复位置**：`WxPayController#wxPayNotify`  
  每个 case 增加 `break`，并增加 `default` 日志  
- **说明**：注释已标明该接口不可用、应走 `/store/app/wxpay/wxPayNotify`；本次仍修复，防止误调用造成重复入账

#### [高危-31] 汇付回调未验签 — **已修复**
- **修复位置**：`PayScrmController#hfPayNotify`  
  使用 `JsonUtils.sort4JsonString` + `RsaUtils.verify` + `BasePay.HUIFU_DEFAULT_PUBLIC_KEY` 先验签，失败返回 `fail`

#### [高危-32] 短信验证码可复用 / 可爆破 — **已修复**
- **修复位置**：`AppLoginController`
  - `resetPassword`：失败计数 ≥5 锁定 30 分钟；成功后删除验证码
  - `loginByPhone` / `registerByPhone`：成功后删除验证码

#### [高危-33] 默认密码 zm12345678 — **当前仓库未命中**
- 未检索到 `zm12345678` / `getUserDefaultPassword` 自动设密逻辑；无需改动

#### [高危-34] 跨租户重置密码 — **已修复**
- **修复位置**：`SysUserController#resetPwd`  
  增加 `userService.checkUserDataScope(user.getUserId())`

---

### F. 反序列化与凭据

#### [高危-35] Fastjson AutoType — **已修复**
- **修复**：全仓库 **27** 个 `FastJson2JsonRedisSerializer.java`  
  `setAutoTypeSupport(true)` → `false`

#### [高危-36] 硬编码腾讯云 AK/SK — **已修复**
- **修复位置**：`SmsTServiceImpl`
  - 改为 `@Value("${tencent.cloud.secret-id/secret-key}")`
  - `fs-admin/.../application.yml` 增加环境变量注入占位
- **运维必做**：
  1. **立即在腾讯云控制台禁用并轮换**旧密钥 `AKIDdAdvzoQpzuOo...`
  2. 各环境设置：
     - `TENCENT_CLOUD_SECRET_ID`
     - `TENCENT_CLOUD_SECRET_KEY`
  3. 未配置时短信发送会返回明确错误，避免静默使用硬编码密钥

---

## 四、额外发现并处理

| 项 | 说明 | 处理 |
|----|------|------|
| 硬编码万能短信验证码 | `AppLoginController` 原 `INTERNAL_LOGIN_CODE = "EdisonX!@#.+-123"`，可绕过短信登录任意用户 | 已清空禁用；仅当配置非空内部码时才可能生效（当前为空） |

---

## 五、新增公共安全组件

| 类 | 路径 | 作用 |
|----|------|------|
| `SqlSafeUtils` | `fs-common/.../security/SqlSafeUtils.java` | 排序方向 / 列名 / live category 白名单 |
| `UrlSecurityUtils` | `fs-common/.../security/UrlSecurityUtils.java` | SSRF：协议白名单 + 拒绝内网地址 |
| `OssUploadSecurityUtils` | `fs-common/.../security/OssUploadSecurityUtils.java` | OSS 上传后缀白名单 + 文件名穿越过滤 |

---

## 六、隐患与后续建议（请确认）

1. **腾讯云旧密钥必须轮换**：源码历史中已暴露，仅改代码不够。  
2. **汇付验签公钥**：当前使用 `BasePay.HUIFU_DEFAULT_PUBLIC_KEY`；若商户使用自定义公钥，需改为按商户配置取公钥，否则合法回调可能验签失败。  
3. **fs-company-app `/**` permitAll**：仍依赖方法级 `@Login`，遗漏注解即裸奔；建议后续统一鉴权。  
4. **后台垂直越权（QwUser / CompanyUser / IpadAllocation）**：未批量加 `@PreAuthorize`，避免权限点未配置导致生产不可用；建议按权限表分批治理。  
5. **其他模块 uploadOSS 副本**：已修核心 6 端 + Chat 上传；ad/qw 等模块若仍有裸上传，可继续复用 `OssUploadSecurityUtils`。  
6. **关闭 AutoType**：若历史 Redis 缓存依赖 `@type` 多态反序列化，升级后偶发反序列化失败，需观察并清理旧缓存。  
7. **SecurityConfig 取消 Swagger/Druid 匿名**：开发环境如需调试，可用 profile 单独放开，勿在生产匿名。

---

## 七、修复文件索引（主要）

```
fs-common/src/main/java/com/fs/common/utils/security/SqlSafeUtils.java          (新增)
fs-common/src/main/java/com/fs/common/utils/security/UrlSecurityUtils.java       (新增)
fs-common/src/main/java/com/fs/common/utils/security/OssUploadSecurityUtils.java (新增)
fs-common/src/main/java/com/fs/common/utils/SortUtils.java
fs-service/.../live/service/impl/LiveDataServiceImpl.java
fs-service/.../hisStore/param/FsStoreOrderParam.java
fs-service/.../his/param/FsStoreOrderParam.java
fs-service/.../live/param/LiveOrderParam.java
fs-service/.../course/service/impl/FsUserVideoServiceImpl.java
fs-service/.../fastGpt/service/impl/FastGptCollectionServiceImpl.java
fs-service/.../fastgptApi/util/AudioUtils.java
fs-service/.../sms/service/impl/SmsTServiceImpl.java
fs-user-app/.../AppLoginController.java
fs-user-app/.../WxPayController.java
fs-user-app/.../store/PayScrmController.java
fs-user-app/.../TalentController.java
fs-user-app/.../CommonController.java
fs-company-app/.../CommonController.java
fs-company-app/.../CompanyUserController.java
fs-company-app/.../FsUserController.java
fs-company-app/.../UserController.java
fs-company/.../common/CommonController.java
fs-company/.../chat/ChatUploadController.java
fs-admin/.../common/CommonController.java
fs-admin/.../system/SysUserController.java
fs-admin/src/main/resources/application.yml
fs-store/.../common/CommonController.java
fs-doctor-app/.../CommonController.java
fs-framework/.../SecurityConfig.java
fs-*/.../FastJson2JsonRedisSerializer.java  (27 处)
```

---

## 八、总结

本次已对审计报告中**本地可核实的高危漏洞**完成加固，覆盖：

- SQL 注入（category / sortOrder / 排序字段）
- 上传白名单与路径穿越
- SSRF
- 登录后门禁用 + 万能验证码禁用
- 支付 fall-through / 汇付验签
- 短信验证码一次性与爆破限制
- Fastjson AutoType
- 云密钥去硬编码
- 关键 IDOR 归属校验
- 管理端危险匿名接口收敛

**未做或需后续立项**的项主要是：CRM 报告中不存在的 Mapper、后台大面积 `@PreAuthorize` 补齐、fs-company-app Spring Security 体系重构。  

部署前请务必完成：**腾讯云密钥轮换**、**各环境注入新密钥**、**汇付回调验签联调**、**上传白名单业务抽样回归**。
