Files
MeshSate/docs/00-总体方案.md
zhaolei 16f134e328 feat: MeshSafe 文件摆渡安全卫士 v1.0 初始提交
核心功能:
- 6 层检测管线: L0 结构分析 → L1 ClamAV → L2 文档深度检测 → L3 关键词匹配 → L4 YARA → L5 PE/二进制
- FastAPI + PostgreSQL + Redis + Docker Compose 架构
- 客户端 HMAC-SHA256 签名鉴权 + 限流 + 幂等性
- 控制台 UI (登录/Dashboard/诊断中心/策略管理/任务列表/测试中心/产品介绍页)
- 三层诊断定时器 (error_scan 30s / db_aggregate 30s / container_check 5min)

并发与稳定性修复:
- 诊断定时器 Redis 时间槽位锁 (多 worker 同一槽位只有一个执行)
- JSONL 存储 fcntl 跨进程排他锁 + 容错解码 + 原子重写
- 移除 SQLite fallback, 统一 PostgreSQL
- API_CLIENTS 脱敏为环境变量, .env 已 .gitignore
2026-10-28 19:07:11 +08:00

1679 lines
103 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MeshSafe 文件安全检测服务 · 总体方案
| 项目 | 内容 |
| ---- | ------------------- |
| 系统名称 | MeshSafe 文件安全检测服务 |
| 版本 | v1.0(方案稿) |
| 文档状态 | 待评审 |
| 适用场景 | 光闸内外网文件摆渡场景下的文件安全检测 |
| 合规要求 | 满足网络安全等级保护三级相关控制项 |
***
## 目录
1. [背景与目标](#1-背景与目标)
2. [范围界定](#2-范围界定)
3. [总体架构](#3-总体架构)
4. [检测能力设计](#4-检测能力设计)
5. [安全设计](#5-安全设计)
6. [接口设计概要](#6-接口设计概要)
7. [策略与裁决模型](#7-策略与裁决模型)
8. [部署架构](#8-部署架构)
9. [在线调试台与文档体系](#9-在线调试台与文档体系)
10. [实施路线](#10-实施路线)
11. [风险与应对](#11-风险与应对)
12. [长期演进预研(非本期实施内容)](#12-长期演进预研非本期实施内容)
13. [待确认事项](#13-待确认事项)
***
## 1. 背景与目标
### 1.1 现状
现有系统为一套基于光闸的内外网数据交换系统,核心能力是文件摆渡、解包与展示,并支持按预设文件格式限制上传。当前缺少针对被摆渡文件的独立安全检查能力,文件"能不能传"仅由格式白名单决定,无法回答"这个文件本身是否安全"。
### 1.2 目标
建设一个**独立部署、可被外部应用调用的专用检测服务**,对摆渡文件执行多层次安全检查,向调用方返回结构化的检测结论与处置建议。
核心目标:
| 编号 | 目标 |
| -- | --------------------------------------- |
| G1 | 提供 RESTful 检测接口,外部应用(光闸摆渡系统)可调用并获得结构化结论 |
| G2 | 覆盖恶意性、可执行性、合规性三类风险判据 |
| G3 | 全组件私有化部署,运行期不依赖公网 |
| G4 | 满足等保三级相关控制项(身份鉴别、访问控制、安全审计、数据完整性与保密性等) |
| G5 | 检测引擎、签名规则、裁决策略均可独立升级,不与摆渡软件耦合 |
| G6 | 提供在线自测控制台,降低对接方联调成本 |
### 1.3 方向定位:一期只做「外网 → 内网」
本服务一期聚焦**外网向内网传入**方向的检测,**内网向外网传出方向的内容审计暂不纳入**,列为待定项。
| 方向 | 一期范围 | 说明 |
| ----------- | ------ | -------------------------------- |
| **外网 → 内网** | ✅ 完整覆盖 | 核心风险是"外部文件伤到内网",即恶意代码与可执行性风险 |
| 内网 → 外网 | ⏸ 待定 | 核心风险是"内部内容违规外泄",属内容审计范畴,依赖业务场景建模 |
**为什么一期不内做内容审计**
外发方向的内容审计需要回答"这段内容是否允许离开内网",其判定依据是**业务规则**——哪些案件材料涉密、哪些个人信息不得外传、哪些类型需审批。这些规则高度依赖具体业务场景与密级标准,在场景未明确前设计检测逻辑,产出大概率不可用。
相比之下,内入方向的判定依据是**技术事实**(这个文件是否有害),与业务规则耦合度低,可以立即工程化。
**架构上为后续预留**:内容审计所需的"文本抽取 → 分类 → 规则裁决"链路,与本方案 L0 文本准备层、策略引擎的形态完全一致。届时只需新增 L-S 语义层与内容规则集,不需重构架构。
### 1.4 非目标(明确不做)
| 不做项 | 原因 |
| ---------------- | ------------------------------------- |
| 内容清洗 / 文件改写 | 本服务只做"判定",不做"加工"。原文件仍由摆渡系统处置 |
| 解包后内容对外输出 | 用户已明确不返回解包内容,仅返回检测结论 |
| 用户 / 权限 / 文档管理系统 | 独立成品的检测服务,不做 OA 能力 |
| 动态沙箱(P4 一期不实现) | 资源开销大、对光闸场景收益有限,架构预留 |
| **内网外发内容审计** | 一期聚焦外网→内网方向;外发方向依赖业务密级规则,场景待定(见 §1.3) |
| 内容敏感信息识别 | 与恶意代码检测属不同问题域,一期不做 |
***
## 2. 范围界定
### 2.1 风险判据分类
光闸场景下,"外网传入的文件是否安全"实际包含三类相互独立的判据。原方案仅覆盖第一类,这是需要补齐的核心缺口。
| 判据 | 关注点 | 典型风险 | 主要覆盖层 |
| -------- | ---------- | ---------------------- | ------------------ |
| **恶意性** | 会不会伤到内网 | 病毒、木马、勒索、挖矿 | L1 ClamAV、L2B YARA |
| **可执行性** | 传进去会不会自动运行 | VBA 宏、DDE、双扩展名、内嵌可执行对象 | L0 结构层、L2 文档深度 |
| **合规性** | 是不是不允许传的东西 | 类型不符、超大文件、加密压缩包、路径穿越 | L0 结构层、全局策略 |
> **关键结论**:可执行性判据在光闸场景中发生频率最高。一个带宏的 `.docx` 在 ClamAV 判定为"干净",但在内网被双击打开时宏即刻执行。因此本方案将 L2 文档深度检测与全局格式策略作为重点,而非动态沙箱。
### 2.1.1 方向差异带来的重点偏移
一期只做外网→内网,因此三类判据的权重与内网外发方向不同:
| 判据 | 外网→内网(一期) | 内网→外网(待定) |
| ---- | ---------------- | ----------------- |
| 恶意性 | **核心**,权重最高 | 次要 |
| 可执行性 | **核心**,权重最高 | 次要 |
| 合规性 | 次要(类型/大小/密级约束较弱) | **核心**(涉及密级与外传审批) |
| 内容语义 | 辅助(识别伪装与诱导) | **核心**(识别涉密与违规内容) |
这解释了为什么一期的能力重心放在**恶意性 + 可执行性**上,以及为什么大模型在内入方向的定位是"识别伪装与诱导"而非"判定涉密"。
### 2.2 支持的输入格式
| 类别 | 格式 |
| ------------- | --------------------------------------------------------------------------------------- |
| Office 文档 | doc / docx / docm / xls / xlsx / xlsm / ppt / pptx / pptm / rtf / odt / ods / odp |
| PDF | pdf |
| 归档 | zip / rar / 7z / tar / gz / bz2 / xz / cab / iso / jar / apk |
| 图像 | jpg / jpeg / png / gif / bmp |
| Windows 可执行 | exe / dll / msi / scr / com / cpl / jar / apk |
| **Linux 可执行** | **.elf / .so / .desktop / .appimage / .deb / .rpm / .run / .bin / .snap / .flatpak** |
| 脚本 | bat / cmd / ps1 / vbs / vbe / js / jse / hta / wsf / **sh / bash / zsh / py / pl / rb** |
| 文本 | txt / csv / json / xml / html / log |
### 2.3 单文件与批量限制
| 约束 | 默认值 | 配置项 |
| -------- | ------- | ------------------------------- |
| 单文件大小上限 | 50 MB | `policy.global.max_file_size` |
| 同步模式处理上限 | 50 MB | `policy.global.sync_max_size` |
| 上传硬上限 | 2048 MB | `MESHSAFE_MAX_UPLOAD_MB` |
| 解包深度上限 | 5 层 | `MESHSAFE_MAX_EXTRACT_DEPTH` |
| 解包总量上限 | 4096 MB | `MESHSAFE_MAX_EXTRACT_TOTAL_MB` |
| 压缩比上限 | 100:1 | `MESHSAFE_MAX_EXTRACT_RATIO` |
***
## 3. 总体架构
### 3.1 分层视图
```
┌──────────────────────────────────────────────────────────────┐
│ 接入层 API 网关 · mTLS/Token 认证 · 限流 · 请求/响应签名 │
├──────────────────────────────────────────────────────────────┤
│ 接收层 文件接收 · 类型识别 · 递归解包 · 哈希计算 │
├──────────────────────────────────────────────────────────────┤
│ 检测层 L0 结构 │ L1 ClamAV │ L2 文档 │ L2B YARA/二进制 │
├──────────────────────────────────────────────────────────────┤
│ 裁决层 策略引擎 · 风险评分 · 处置动作映射 │
├──────────────────────────────────────────────────────────────┤
│ 留存层 结论存储 · 审计日志(哈希链)· 报告生成 │
└──────────────────────────────────────────────────────────────┘
```
### 3.2 关键架构决策
#### 决策 1:独立服务,不嵌入摆渡软件
**理由**:摆渡软件负责数据搬运(数据平面),检测服务负责安全判定(控制平面)。若耦合,升级检测引擎就必须重新发布摆渡软件——在政务/法院内网环境下,这是不可接受的发布风险。
**后果**:需要设计稳定的接口契约,接口版本必须严格管理(见 §6.6)。
#### 决策 2:检测引擎作为独立进程组
ClamAV 守护进程、YARA 规则库、文档解析库在容器内独立运行或独立容器化。好处:
* 引擎崩溃不影响 API 服务的可用性(引擎异常被捕获并降级为"引擎不可用"信号)
* 引擎可独立升级(ClamAV 签名库每日更新不影响应用镜像)
* 资源可独立限制(clamd 内存占用大,需单独限制)
#### 决策 3:同步与异步双模式
| 模式 | 触发条件 | 行为 |
| -- | -------------------------- | ----------------------- |
| 同步 | 文件 ≤ `sync_max_size` 且不需沙箱 | 请求内完成检测并直接返回结论 |
| 异步 | 文件超限或命中强制沙箱规则 | 返回 `task_id`,调用方轮询或等待回调 |
**理由**:同步模式延迟低(摆渡业务最常用);异步模式避免 HTTP 长连接超时给网关造成压力,也让未来接入沙箱时无需改动接口。
#### 决策 4:检测在隔离区完成,单向数据流
```
摆渡系统 ──── 文件内容 ────▶ 检测服务 ──── 检测结论 ────▶ 摆渡系统
│
└── 绝不主动连外网
```
检测服务不修改、不回写被检文件。病毒库与规则库通过**单向导入**方式更新(见 §8.3)。
#### 决策 5:全局单策略
按用户确认,本期采用**全局单策略**,不按业务通道区分。策略引擎在实现上保留通道扩展位(`channel` 字段贯穿全链路),后续扩展无需重构。
***
## 4. 检测能力设计
### 4.1 五层流水线总览
| 层 | 引擎 | 检查对象 | 关键信号 | 典型时延 |
| ------- | --------------------- | ----------------- | ----------------------------------------------- | ---- |
| **L0** | structure / extractor | 全部文件 | 扩展名伪装、双扩展名、危险可执行类型、zip bomb、路径穿越、嵌套过深 | 毫秒 |
| **L0** | link / shortcut | LNK 等 | 目标指向可执行体或远程路径 | 毫秒 |
| **L1** | ClamAV | 全部文件 | 已知木马 / 勒索 / 挖矿签名命中、启发式检测 | 秒 |
| **L2** | oletools / PDF 解析 | Office、PDF、RTF、脚本 | VBA 宏、DDE/DDEAUTO、嵌入对象、PDF JavaScript、外部链接、脚本混淆 | 秒 |
| **L2C** | links / qrcode | 文档与图片 | 外部 URL、二维码内容、可疑域名 | 秒 |
| **L2B** | YARA / pefile | PE、脚本、内存马 | 家族规则命中、危险能力组合、壳与免杀、签名异常 | 秒 |
| **L3** | 沙箱(长期可选项) | 可执行文件 | 释放文件、持久化、外联 C2 | 分钟 |
> **场景定位**:本服务的文件最终由**人工在内网终端打开**,自动化处理极少。这一前提决定了能力重心——所有「打开即执行」的载体必须零容忍拦截(见 §4.8)。
### 4.2 L0 结构与完整性层
这一层最快、最廉价,却能挡掉大量"人工伪装"类攻击,是性价比最高的一层。
#### 4.2.1 真实类型识别
* 双引擎识别:`libmagic`(python-magic)+ 内置魔数表作为兜底
* **不信任扩展名**,一律以内容判定真实类型
* OOXML 容器(docx/xlsx/pptx)通过检查内部部件名区分,避免被误判为普通 zip
#### 4.2.2 伪装检测规则
| 规则名 | 触发条件 | 默认严重度 |
| ------------------------------ | --------------------------- | --------------- |
| `ExtensionMismatch` | 声明扩展名与真实类型不相容 | HIGH |
| `DoubleExtension` | 文件名含两个以上扩展名,且前缀为危险类型 | HIGH |
| `DangerousExecutableExtension` | 顶层文件为 exe/scr/dll/com/pif 等 | CRITICAL / HIGH |
| `ArchiveContainsExecutable` | 归档内含可执行成员 | HIGH |
| `ArchiveBombSuspect` | 压缩比超过阈值 | HIGH |
| `ArchiveTooLarge` | 解压总量超限 | HIGH |
| `PathTraversal` | 归档内含路径穿越条目 | CRITICAL |
| `ArchiveTooManyMembers` | 归档成员数异常(>10000) | MEDIUM |
#### 4.2.3 递归安全解包
**这是最容易被遗漏、也是最关键的一环。** 只扫描外层压缩包是最常见的绕过手法。
安全约束(全部强制执行):
| 约束 | 行为 |
| ----- | ------------------------------------ |
| 解包深度 | 超过 `max_extract_depth` 停止并记录信号 |
| 解压总量 | 累计超过 `max_extract_total_mb` 停止 |
| 单成员大小 | 超过单文件上限则跳过该成员 |
| 压缩比 | 单成员压缩比超阈值则跳过并记录 `ArchiveBombBlocked` |
| 路径穿越 | 拦截含 `..`、绝对路径、盘符的条目 |
| 符号链接 | tar 中的 symlink/hardlink 一律拦截 |
| 文件名 | 解包后文件名重写为安全形式,原始名保留在逻辑路径中供追溯 |
解包出的文件**自动进入待检测队列**,形成递归检测。
#### 4.2.4 加密文件识别
* Office 加密文档 → `PdfEncrypted` / 加密标记信号
* 加密压缩包 → 记录为不可静态分析
按策略,加密文件默认**拒绝**(无法确认安全),除非策略显式放开。
### 4.3 L1 ClamAV 层
#### 4.3.1 部署方式
使用 `clamd` 常驻守护进程(TCP 或 Unix Socket),而非 `clamdscan` 一次性调用。理由:签名库加载到内存需数秒至数十秒,常驻模式可支撑并发扫描。
#### 4.3.2 离线签名库更新机制
这是内网部署最容易失效的环节,必须做成自动化流程:
```
外网侧签名库同步机
│ 每日定时执行 freshclam,拉取官方 CVD
▼
本地私有镜像(cvdupdate 模式 / freshclam 私有镜像模式)
│ 通过单向导入介质(摆渡光闸 / 刻录介质)传入内网
▼
内网签名库分发节点
│ 内网节点增量同步
▼
clamd 容器(签名库版本记入扫描结果 meta)
```
**要求**:签名库版本号与更新时间必须包含在检测结果中,作为检测有效性的举证材料。
#### 4.3.3 命中强度分级
ClamAV 2025 起区分三类命中强度,建议在策略中区分对待:
| 类型 | 含义 | 本方案处置 |
| -------------------- | ------------- | ---------------- |
| Strong Indicator | 传统签名命中,扫描立即中止 | 视为确凿恶意 |
| Potentially Unwanted | 可疑软件,扫描结束时告警 | 视签名关键词判定为 MEDIUM |
| Weak Indicator | 低置信度命中 | 降权处理 |
### 4.4 L2 文档深度检测层
**本方案的重点层**,直接对应光闸场景最高频的实际风险。
| 格式 | 工具 | 检测内容 |
| ---------------------- | ------------------ | ------------------------------------------------------ |
| doc / docm / xls / ppt | `oletools.olevba` | VBA 宏提取与代码分析 |
| 同上 | `oletools.mraptor` | 宏的整体启发式判定(AutoExec + 可疑关键词 + 编码字符串) |
| 同上 | `oletools.msodde` | DDE / DDEAUTO 自动执行字段 |
| 同上 | `oletools.oleobj` | 内嵌 OLE 对象,识别内嵌可执行体 |
| docx / xlsx / pptx | 自研 OOXML 解析 | 外部链接部件、嵌入对象、外部 URI、附加模板、DDEAUTO、文档变量 |
| pdf | `pypdf` | JavaScript 动作、LaunchAction、OpenAction、外部 URI、内嵌文件、加密状态 |
| rtf | `oletools.rtfobj` | OLE 嵌入对象 |
| ps1 / bat / vbs / js | 正则特征集 | 编码命令、Base64 解码执行、下载器、隐藏窗口、关闭防护、勒索前置行为 |
#### 4.4.1 VBA 宏判定分级
| 条件 | 规则名 | 严重度 | 默认权重 |
| ---------------------------------- | -------------------- | -------- | ---- |
| 自动执行入口 + 调用系统命令/外联 | `VBAAutoExecShell` | CRITICAL | 80 |
| 调用 Shell / CreateObject | `VBAShellInvocation` | HIGH | 55 |
| 含自动执行入口(AutoOpen / Workbook_Open) | `VBAAutoExec` | HIGH | 45 |
| 含外部链接 | `VBAExternalLink` | MEDIUM | 25 |
| 含疑似编码/混淆长串 | `VBAEncodedString` | MEDIUM | 20 |
| 仅含宏,无明显恶意特征 | `VBAMacroPresent` | LOW | 15 |
#### 4.4.2 规则覆盖机制
关键规则在策略文件中配置**强制处置**,不依赖评分累加:
```yaml
rule_overrides:
MRaptorAutoExecSuspicious:
action: reject
reason: "文档宏具备自动执行且包含可疑行为,按策略直接拒绝"
DDEAutoExecution:
action: reject
reason: "检测到 DDE/DDEAUTO 自动执行字段,按策略直接拒绝"
```
***
### 4.5 L2B YARA 与二进制分析层
| 组件 | 用途 |
| -------- | ------------------------------- |
| YARA | 通用规则库 + 环境专属规则(如针对内部文书模板名的钓鱼文件) |
| pefile | PE 节区熵值、导入表分析、签名目录检查、编译时间戳 |
| capa(可选) | 可执行文件能力识别(持久化、注入、加密、HTTP 通信) |
规则严重度依据规则名与标签自动判定:
| 标签 / 关键词 | 严重度 | 权重 |
| --------------------------------------------------------- | -------- | -- |
| critical / malware / ransomware / backdoor / c2 / exploit | CRITICAL | 85 |
| high / trojan / dropper / obfusc / shellcode | HIGH | 60 |
| medium / suspicious / pua / packer | MEDIUM | 30 |
| 其他 | LOW | 10 |
**规则库维护要求**:规则库需版本管理与定期回归测试集,否则半年后必然出现大量误报或漏报。
### 4.6 L3 动态沙箱层(长期可选项,一期不实现)
#### 4.6.1 一期不实现的理由
1. **环境不匹配**:CAPE / DRAKVUF 依赖 Windows 客体与裸金属虚拟化(Intel VT-x + EPT),与内网国产化终端环境不匹配
2. **资源开销**:典型配置 4C8G 起,单样本运行 3\~5 分钟,全量沙箱在吞吐上不可行
3. **场景收益有限**:本场景以文档为主,静态分析对文档类样本覆盖度已较高;沙箱真正适用面窄(仅加壳二进制、镜像类)
4. **投入产出失衡**:一套沙箱环境的投入 ≈ 整个检测服务的开发投入
#### 4.6.2 保留的接口语义
异步模式与 `sandbox_required_extensions` 配置项在策略中保留,未来接入沙箱时无需改动接口与策略结构。
| 项目 | 设计 |
| ---- | --------------------------------------------- |
| 触发条件 | 策略命中 `sandbox_required_extensions`(一期不生效,仅占位) |
| 替代措施 | 对高危解析路径(字体、图像、压缩流、复合文档)增加结构完整性校验与畸形构造检测 |
| 接口影响 | 无。异步模式已预留 `task_id` 语义 |
### 4.7 引擎降级与失败处理
任一引擎不可用(进程崩溃、连接超时、库加载失败)时:
1. 记录为"引擎不可用"信号,**不中断整个扫描**
2. 由策略的 `engine_failure_mode` 决定整体处置
3. 生产环境配置为 `fail_closed`(拒绝),符合等保"安全优先"原则
### 4.8 「打开即执行」载体零容忍(核心设计)
#### 4.8.1 为什么这是核心
本场景的关键前提是:**文件最终由人工在内网终端打开,自动化处理极少**。因此"文件打开即执行"的所有载体构成最高风险敞口——这类攻击不需要用户任何操作,一次双击即完成入侵。
传统杀毒以"是否为已知恶意样本"为判据,但在本场景下判据应改为"**是否存在打开即执行的载体**"。
#### 4.8.2 目标终端与威胁模型
本方案一期的目标终端是 **麒麟桌面/UOS(x86_64)+ WPS Office**。这是纯 Linux 桌面环境,与之前方案隐含的 Windows 兼容路线有本质差异——部分 Windows 专属载体在内网终端上不适用(如 LNK 快捷方式),同时存在 Linux 专属威胁载体(如 ELF、.desktop)。
**纵深防御原则**:即使内网是 Linux,Windows 威胁仍保持检测——因为文件可能通过其他路径最终到达 Windows 机器(运维人员的 Windows 工作站、外接 Windows 设备等)。但威胁等级按内网终端环境加权。
#### 4.8.3 载体清单与判定方式(按 Linux 适用性分层)
**A. 跨平台通用载体(Linux 上同样有效)**
| 载体 | 触发条件 | Linux 上是否生效 | 判定方式 | 规则名 |
| ---------------- | ------- | ------------------------ | ------- | ------------------- |
| PDF JavaScript | 打开即执行脚本 | ✅ 麒麟默认 PDF 阅读器和浏览器都支持 JS | pypdf | `PdfJavaScript` |
| PDF LaunchAction | 打开即启动程序 | ✅ Linux PDF 阅读器会触发 | pypdf | `PdfLaunchAction` |
| PDF OpenAction | 打开即执行动作 | ✅ | pypdf | `PdfOpenAction` |
| 宏代码混淆 / 加密 | 意图不可知 | ✅ 与平台无关 | 编码特征检测 | `MacroObfuscated` |
| 路径穿越条目 | 解包时逃逸 | ✅ | 结构校验 | `PathTraversal` |
| ISO / 镜像 | 双击即挂载 | ✅ UOS 可直接挂载 | 挂载后递归扫描 | `IsoWithExecutable` |
**B. 宏相关(WPS on Linux 需实测验证)**
VBA 宏检测的核心逻辑(行为分析、危险 API 识别、混淆检测)是**跨平台**的——不管宏最终在哪个 Office 实现中运行,代码本身的危险特征(调用 Shell、下载文件、混淆加密)都可以被静态识别。差异在于 AutoOpen 等自动执行入口在 WPS on Linux 上是否与 Office on Windows 行为一致。
> **待实测**:AutoOpen / Workbook_Open 在 WPS on 麒麟/UOS 上是否在打开时自动触发;Shell / CreateObject 调用在 WPS on Linux 上是否有效。这项验证在 P0 开发前必须完成(见 §13 Q15 已确认,补充方案见 §4.8.4)。
| 载体 | 触发条件 | 判定方式 | 规则名 |
| -------------- | ----------------------- | ---------------- | ---------------------------------- |
| VBA 宏 AutoOpen | 打开即触发(WPS on Linux 需实测) | oletools + 宏行为分析 | `VBAAutoExec` / `VBAAutoExecShell` |
| DDE / DDEAUTO | 打开即触发(WPS on Linux 需实测) | msodde | `DDEAutoExecution` |
| 外部模板注入 | 打开即触发 | OOXML 解析 | `AttachedTemplate` |
| 内嵌可执行对象 | 点击确认后执行 | oleobj | `EmbeddedExecutable` |
**C. Windows 专属载体(Linux 上无直接威胁,降级为纵深防御)**
以下载体在内网麒麟桌面/UOS 终端上**不生效**,但保持检测——文件可能流向 Windows 工作站:
| 载体 | 触发条件 | Linux 上生效? | 处置定位 | 规则名 |
| -------- | ------- | ----------------------- | -------------------- | ----------------- |
| LNK 快捷方式 | 点击即执行 | ❌ Linux 不识别 .lnk 格式 | 纵深防御(文件可能流向 Windows) | `LnkWithAutoExec` |
| CHM 帮助文件 | 打开即执行脚本 | ❌ Linux 上需专门查看器,默认不自动执行 | 纵深防御 | `ChmWithScript` |
**D. Linux 专属载体(之前方案遗漏,一期必须补充)**
| 载体 | 触发条件 | 判定方式 | 规则名 |
| ------------------------------------ | ------------------------ | ------------------------------------------------------------ | -------------------------- |
| **ELF 可执行文件** | Linux 原生二进制,直接运行 | 真实类型识别 + 签名/熵值分析 | `LinuxExecutable` |
| **.desktop 快捷方式** | 包含 `Exec=` 字段指向程序或 shell | .desktop 文件解析,检查 Exec 字段中是否包含 `/bin/sh -c`、`wget/curl`、隐藏命令等 | `DesktopFileAutoExec` |
| **Shell / Python / Perl / Ruby 等脚本** | 直接可执行,或被其他程序调用 | 脚本特征提取 + 危险函数识别(system/eval/exec/shell\=True 等) | `ShellScriptDangerous` |
| **AppImage / Flatpak / Snap 包** | 跨发行版便携可执行格式,双击即运行 | 真实类型识别,内部可执行递归扫描 | `LinuxPortableExecutable` |
| **压缩包内的 .sh / .deb / .run / .bin** | Linux 下解压即可执行 | 递归解包 + 真实类型识别 | `ArchiveContainsLinuxExec` |
#### 4.8.4 零容忍规则集(更新版,含 Linux 专属)
上述规则中的多数归入**零容忍规则集**,命中即拒绝,**不走评分累加**:
```yaml
zero_tolerance_rules:
# === 跨平台通用 ===
- PdfJavaScript
- PdfLaunchAction
- PdfOpenAction
- PathTraversal
- IsoWithExecutable
- MacroObfuscated
- AttachedTemplate
# === 宏相关(WPS on Linux 生效)===
- VBAAutoExec
- VBAAutoExecShell
- MRaptorAutoExec
- MRaptorAutoExecSuspicious
- DDEAutoExecution
- EmbeddedExecutable
# === Linux 专属(新增)===
- LinuxExecutable
- DesktopFileAutoExec
- ShellScriptDangerous
- LinuxPortableExecutable
- ArchiveContainsLinuxExec
# === Windows 专属(纵深防御)===
- LnkWithAutoExec
- ChmWithScript
```
> **Linux 专属载体一期优先级**:ELF 和 shell 脚本识别已包含在 L0 结构层的真实类型识别和 L2 文档检测中(脚本特征提取 + 正则),一期直接生效;.desktop 文件、AppImage/Flatpak 的专用解析器在 P0 中一并实现。
**为什么零容忍要独立于评分模型**:评分是相对度量(权重累加过阈值才拒绝),而"打开即执行"是绝对问题——一个宏文档哪怕只命中一条,也应直接拒。零容忍用独立机制表达,避免依赖权重调参。
#### 4.8.5 宏行为分级(从「类型黑名单」到「行为白名单」)
内网人员需要打开带宏的公文模板(自动编号、签章定位等),因此不能简单地把"含宏"等同于"拒绝"。判定依据必须是**宏做了什么**,而非**有没有宏**:
| 宏的实际行为 | 风险 | 判定 | 处置 |
| ------------------ | --------- | ----------------- | ------------- |
| 自动执行 + 调用系统命令 / 外联 | 极高 | 特征组合 + 编码特征 | **零容忍,拒绝** |
| 宏代码被混淆 / 加密 | 极高(意图不可知) | 编码特征检测 | **零容忍,拒绝** |
| 自动执行 + 仅本地无害操作 | 低 | 无危险 API、无网络、无文件写入 | **放行(可登记例外)** |
| 无自动执行,仅手动触发 | 中 | 特征分析 | 标记放行 / 转复核 |
**实现方式**:判定"宏做了什么"靠的是**危险 API 调用清单** + **自动执行入口存在性** + **混淆特征**三项的组合,而非单纯的宏存在性。
#### 4.8.5a 危险 API 清单(跨平台 + Linux 等价物)
原来的危险 API 清单是 Windows 专属的。以下补充 Linux 桌面环境下的等价威胁调用:
**Windows 专属(宏中识别,文件可能流向 Windows 工作站)**
| API | 含义 | 威胁等级 |
| ------------------------------------------- | -------------- | ------ |
| `Shell()` | 执行外部程序 | HIGH |
| `CreateObject("wscript.shell")` | 脚本宿主对象,可执行任意命令 | HIGH |
| `URLDownloadToFile()` / `MonikerDownload()` | 下载文件到本地 | HIGH |
| `CreateObject("MSXML2.XMLHTTP")` | HTTP 请求(常配合下载) | HIGH |
| `PowerShell` / `cmd.exe` / `net.exe` 调用 | Windows 系统命令 | HIGH |
| 注册表写入(`HKEY_LOCAL_MACHINE` 等) | 持久化 | MEDIUM |
**Linux 等价物(宏在 WPS on Linux 中调用的系统接口)**
| 调用特征 | 含义 | 威胁等级 |
| -------------------------------------------------------- | --------------------------------- | -------- |
| `Shell()` → 执行 `/bin/sh -c "..."` | Linux 下 Shell 函数通过 `/bin/sh` 执行命令 | HIGH |
| `CreateObject("com.sun.star.system.SystemShellExecute")` | WPS/Office on Linux 执行外部程序的标准接口 | HIGH |
| `ShellExecute` → `curl` / `wget` 下载 | Linux 下常见下载器 | HIGH |
| Shell 命令中含 `cron` 写入 / `systemctl enable` | 持久化 | HIGH |
| Shell 命令中含 `/tmp` / `/var/tmp` 写入 | 落地可执行文件 | MEDIUM |
| Shell 命令中含 `/dev/tcp/` / `bash -i` | 反弹 Shell / 反向连接 | CRITICAL |
> **注意**:以上 Linux 等价物是基于 WPS on Linux 的技术特性推断。§4.8.5b 的实测验证将确认这些调用在 WPS on 麒麟/UOS 上是否真的有效。
#### 4.8.5b WPS on Linux 需实测的验证点
宏行为分级逻辑**核心是跨平台的**——基于宏代码的危险特征组合判定。差异在于这些特征在目标终端上是否可利用。以下验证项需在 P0 开发前完成:
| 验证项 | 说明 | 验证方式 |
| ------------------------------------------------ | ------------------------------------ | ----------------------------------------------------------------------------------- |
| AutoOpen / Workbook_Open 在 WPS on 麒麟/UOS 是否自动触发 | 决定 `VBAAutoExec` 在 Linux 上的威胁等级 | 制作含 AutoOpen 的 docm 文件,在 WPS on 麒麟桌面打开观察 |
| Shell / CreateObject 在 WPS on Linux 是否有效 | 决定"自动执行 + 调用系统命令"场景在 Linux 上是否可利用 | 宏内写 `Shell "ls"` 或 `Shell "/bin/sh -c 'echo test > /tmp/pwned'"`,在 WPS on Linux 上测试 |
| `/dev/tcp/` / `bash -i` 在宏内能否实现反向连接 | 决定 Linux 下反弹 Shell 的实际威胁 | 宏内写反弹 Shell 命令,测试是否成功 |
| DDE / DDEAUTO 在 WPS on Linux 是否生效 | 决定 `DDEAutoExecution` 在 Linux 上的实际威胁 | 构造含 DDEAUTO 的文档,在 WPS on Linux 上打开 |
> **安全优先**:在验证完成前,宏相关零容忍规则保持**默认生效**。即使 AutoOpen 在 Linux 上不自动触发,宏代码本身的危险特征(混淆、Shell 调用、反弹 Shell 尝试)仍足以触发零容忍。
#### 4.8.6 解析器漏洞的处理边界
`MalformedStructure`(畸形结构)不进入零容忍集,仅降权处理。理由:
| 考量 | 说明 |
| ------ | -------------------------------- |
| 无法判定 | 畸形结构既可能是攻击构造,也可能是正常的软件兼容产物 |
| 误报代价高 | 大量正常文档存在非标准结构,零容忍会阻塞业务 |
| 检出能力有限 | 结构校验只能发现部分畸形,无法覆盖全部解析器漏洞 |
| 责任边界 | 根治该类风险属终端侧加固范畴(打补丁、限制字体自动加载、禁用宏) |
**检测服务的责任边界**:识别出「该格式存在解析器攻击面」并在结论中提示,**不给出「检测通过即绝对安全」的暗示**。
#### 4.8.7 链接与二维码:分级而非一刀切
外部链接在正常公文中极常见(法院官网、办事指南),一刀切会造成严重误报。因此采用分级:
| 情形 | 判定 | 处置 |
| ---------------------- | ----- | ---------------- |
| 命中恶意 URL 库 | 确定性命中 | **零容忍,拒绝** |
| 指向非常规端口 / IP 直连 / 短链服务 | 特征命中 | 转复核 |
| 域名与内网已知系统同名但解析异常 | 特征命中 | 转复核 |
| 普通 http/https 链接 | 无命中 | **放行,但在打开风险中提示** |
二维码同理:解码后按 URL 规则判定;同时识别"二维码内容与文档主题完全无关"这一可疑组合。
#### 4.8.8 打开风险等级(结论的独立维度)
在「人打开」场景下,检测服务应把「已确认有害」与「需用户注意」区分开。前者必须拦,后者应告知。
```json
{
"verdict": "suspicious",
"action": "pass_with_flag",
"score": 25.0,
"reason": "文档包含外部链接与二维码,未命中恶意特征",
"open_risk": {
"level": "medium",
"factors": ["external_url", "qrcode", "contains_macro"],
"advice": "此文件包含宏与外部链接,打开前请确认来源,宏请勿启用",
"requires_macro_enable": true
}
}
```
| 等级 | 判定条件 | 提示语义 |
| ---------- | ------------------------------------------------------ | ------------------ |
| `low` | 无宏、无外链、无嵌入对象 | 无需特别提示 |
| `medium` | 含外部链接 / 二维码 / 隐藏内容 | 请确认来源后再访问链接 |
| `high` | 含宏(行为无害)/ 含外部模板引用 | 打开时请勿启用宏 |
| `critical` | 含可执行文件 / ISO / Linux ELF / .desktop / AppImage / 零容忍命中 | 请勿直接双击,使用虚拟机或联系管理员 |
**设计要点**:
| 要点 | 说明 |
| ----- | ---------------------------------------- |
| 独立字段 | `action` 供系统判断,`open_risk` 供人阅读,语义不同不可混用 |
| 消费方分离 | 摆渡系统读 `action`;内网用户看 `open_risk.advice` |
| 可忽略 | 对接方觉得多余可直接忽略该字段,不影响接口兼容 |
| 独立演进 | 提示文案调整不影响判定逻辑 |
***
## 5. 安全设计
### 5.1 威胁模型
| 威胁 | 场景 | 应对 |
| -------- | ------------------ | ------------------------------ |
| 越权调用 | 未授权方直接调用检测接口 | mTLS + HMAC 签名 + 时间戳 + nonce |
| 重放攻击 | 截获合法请求后重复发送 | timestamp 窗口 ±300s + nonce 一次性 |
| 篡改响应 | 中间人将"恶意"结论改为"干净" | 响应体独立签名,调用方验签 |
| 参数试探 | 拿到密钥后反复调接口摸清检测逻辑 | 限流 + 按角色裁剪响应 + 错误信息不区分原因 |
| 恶意文件打服务端 | 上传构造的压缩炸弹 / 路径穿越文件 | 解包配额 + 路径清洗 + 进程隔离 + 超时限制 |
| 提权 | 通过文件内容影响服务进程 | 非 root 运行、只读文件系统、无出网权限 |
| 凭据泄露 | 配置文件中的密钥泄露 | 环境变量注入 + 文件权限 600 + 密钥派生隔离 |
| 日志篡改 | 事后删除不利审计记录 | 审计日志哈希链,篡改可被检测 |
| 未授权访问控制台 | 攻击者利用调试台探测系统 | 登录认证 + 失败锁定 + 生产默认关闭 |
### 5.2 认证与签名体系
#### 5.2.1 凭证模型
每个调用方分配独立的 `client_id` / `secret`:
* 密钥不直接使用,通过 **HKDF-SHA256** 按用途派生出相互隔离的子密钥:
* 请求签名密钥:`info = "meshsafe/api/v1/request-signing"`
* 响应签名密钥:`info = "meshsafe/api/v1/response-signing"`
* 用途隔离的意义:即使请求签名密钥泄露,攻击者也无法伪造响应签名
#### 5.2.2 请求签名
待签名串按固定顺序拼接,分隔符为 `\n`:
```
METHOD \n PATH \n CANONICAL_QUERY \n BODY_SHA256 \n TIMESTAMP \n NONCE \n CLIENT_ID
```
签名为 `HMAC-SHA256(请求签名密钥, 待签名串)` 的小写十六进制。
完整规范、校验向量、多语言示例见《接口文档》。
#### 5.2.3 响应签名
服务端对响应体计算签名并通过响应头返回:
```
X-MS-Response-Signature = HMAC-SHA256(响应签名密钥, SHA256(响应体) || TIMESTAMP)
```
调用方**必须验签**。未验签的调用方无法获得防篡改保障——这在文档中会明确标注为对接方的强制要求。
#### 5.2.4 防重放
| 机制 | 参数 | 说明 |
| --------- | ----------------------------------- | ------------- |
| 时间戳窗口 | ±300 秒(`MESHSAFE_SIGNATURE_WINDOW`) | 超窗直接拒绝 |
| nonce 一次性 | Redis `SET NX` + TTL | 重复 nonce 直接拒绝 |
nonce 校验通过 Redis 保证分布式一致性;Redis 不可用时降级为仅时间戳校验(记录告警)。
#### 5.2.5 分权响应
| 角色 | 返回内容 |
| ---------- | --------------------------------------------------- |
| `operator` | 完整结论 + 全部 findings + 提取文件路径 |
| `basic` | 仅 verdict / score / action / reason 摘要 + 精简 file 信息 |
目的是缩小信息泄露面,避免攻击者通过对比不同密钥的响应差异反推检测规则细节。
#### 5.2.6 错误信息不泄露原因
认证失败统一返回"认证失败",不区分"client_id 不存在"与"签名错误",避免 client_id 枚举。
### 5.3 控制台安全
| 控制项 | 实现 |
| ----- | ------------------------------------- |
| 口令存储 | PBKDF2-HMAC-SHA256,60 万次迭代,16 字节随机盐 |
| 口令复杂度 | ≥12 位,含大小写字母、数字、特殊字符 |
| 失败锁定 | 5 次失败锁定 15 分钟 |
| 会话管理 | 服务端会话存储,30 分钟超时,滑动续期 |
| CSRF | 状态变更请求校验 CSRF Token + SameSite Cookie |
| 首次登录 | 强制修改初始密码(`must_change_password`) |
| 操作审计 | 登录、登出、上传扫描、查看明细、策略重载全部留痕 |
| 生产关闭 | 默认 `always_on` 模式,路由不注册,访问返回 404 |
### 5.4 审计与合规
| 控制项 | 实现 |
| ----- | -------------------------------------------------------- |
| 审计范围 | 所有 API 调用、认证事件、策略变更、人工复核、控制台操作 |
| 防篡改 | 哈希链:`row_hash = SHA256(记录字段 ‖ prev_hash)`,任一条被改则后续链断裂可检出 |
| 留存期 | ≥ 180 天(`MESHSAFE_AUDIT_RETENTION_DAYS`) |
| 完整性校验 | `GET /api/v1/audit/verify` 提供链完整性自检 |
| 日志外发 | 审计日志支持导出,便于对接集中审计平台 |
### 5.5 运行环境安全
| 项 | 配置 |
| ---- | ------------------------------ |
| 容器用户 | 非 root 运行 |
| 文件系统 | 应用目录只读,仅临时目录可写 |
| 网络 | 检测容器无出网权限;仅 Nginx 暴露 443 |
| 密钥管理 | 环境变量注入,不写入镜像层 |
| 依赖 | 版本锁定(`requirements.txt` 精确版本号) |
| 镜像 | 固定基础镜像 tag,定期重建 |
### 5.6 等保三级要求的融入点
本节不展开逐条对照(测评时另行整理),而是说明**等保三级对本系统的设计产生了哪些实际约束**——这些约束已经体现在前面的架构决策中。
#### 5.6.1 约束如何影响设计
| 等保要求方向 | 对本系统的实际影响 | 体现在哪 |
| ---------- | -------------------- | ------------------------- |
| **身份鉴别** | 接口必须有强鉴别,不能只靠 IP 白名单 | §5.2 请求签名全量校验 |
| **访问控制** | 需按角色分配权限,防止越权获取信息 | §5.2.5 分权响应 |
| **安全审计** | 审计记录需完整、留存 ≥6 个月、防篡改 | §5.4 哈希链 + 180 天 |
| **数据完整性** | 传输与存储过程需有完整性保护手段 | 请求体哈希 + 响应签名 + 哈希链 |
| **数据保密性** | 口令不可逆存储,密钥不落盘 | §5.3 PBKDF2 + §5.5 环境变量注入 |
| **剩余信息保护** | 检测后不留存敏感文件 | 临时文件任务结束即清理 |
| **安全计算环境** | 恶意代码防范软件能力 | 本系统自身即为恶意代码防范组件 |
| **集中管控** | 策略需集中配置与审计 | 策略引擎 + 策略版本快照 |
#### 5.6.2 本系统需要特别注意的两点
**① "安全优先"的故障处理**
等保要求"安全优先",因此策略的 `engine_failure_mode` 默认必须是 `fail_closed`(引擎不可用时拒绝文件)。这与一般业务系统的"可用性优先"相反,是刻意的设计取舍——检测服务在引擎故障时若继续放行,等同于没有检测。
**② 双因素鉴别的依赖**
等保三级对重要系统要求两种或以上鉴别方式组合。本服务的接口层已具备"证书 + 请求签名"的双要素,但对**控制台的人工操作**而言,目前只有单一口令。
建议方案:控制台接入承载方的统一身份认证体系(UAC / CA 证书 / 短信令牌),由该体系提供第二因素。若测评要求服务自身实现,则需增加 TOTP 模块——这会成为一个待补项。
#### 5.6.3 依赖部署侧落实的事项
以下事项不在应用代码内,但测评时会被检查,需在部署方案中明确:
| 事项 | 要求 |
| ------ | -------------------------------------------------- |
| 时钟同步 | NTP 同步,偏差 \< 1 秒(签名窗口 ±300 秒,同步可避免误拒) |
| TLS 证书 | 内部 CA 签发,TLS 1.2+,禁用弱套件 |
| 磁盘加密 | 存储数据库与策略文件的卷启用加密 |
| 容器加固 | 非 root、只读根文件系统、`cap_drop: ALL`、`no-new-privileges` |
| 网络隔离 | 检测网段与业务内网隔离,无出网路由 |
| 主机加固 | 麒麟 / Ubuntu 安全基线(SSH、口令策略、审计服务) |
| 备份策略 | 数据库与配置备份计划 + 演练记录 |
***
## 6. 接口设计概要
> 完整契约见《接口文档》。此处仅列概要。
### 6.1 接口清单
| 方法 | 路径 | 说明 | 权限 |
| ---- | -------------------------------- | ---------- | -------- |
| POST | `/api/v1/scans` | 提交文件扫描 | 调用方 |
| GET | `/api/v1/scans/{task_id}` | 查询扫描结果 | 调用方 |
| POST | `/api/v1/scans/{task_id}/rescan` | 按当前策略重扫 | 调用方 |
| POST | `/api/v1/scans/{task_id}/review` | 人工复核结论回写 | operator |
| GET | `/api/v1/health` | 引擎状态与签名库版本 | 调用方 |
| GET | `/api/v1/policies` | 查询生效策略 | operator |
| POST | `/api/v1/policies/reload` | 重载策略文件 | operator |
| GET | `/api/v1/audit/verify` | 审计链完整性自检 | operator |
### 6.2 结论字段语义
| 字段 | 取值 | 含义 |
| --------- | ------------------------------------------------------ | ---- |
| `verdict` | `clean` / `suspicious` / `malicious` / `error` | 总体判定 |
| `action` | `pass` / `pass_with_flag` / `manual_review` / `reject` | 处置建议 |
| `score` | 0\~100 | 风险评分 |
**`action` 与 `verdict` 解耦**:调用方应依据 `action` 执行业务逻辑,`verdict` 供人判断。
### 6.3 处置动作语义
| action | 调用方应采取的行动 |
| ---------------- | ---------------------- |
| `pass` | 正常放行 |
| `pass_with_flag` | 放行但记录标记(低风险信号) |
| `manual_review` | 转入人工复核流程,暂不放行 |
| `reject` | 拒绝本次传输,并向用户说明 `reason` |
### 6.4 响应结构概要
```json
{
"task_id": "…",
"verdict": "malicious",
"score": 85.0,
"action": "reject",
"reason": "检测到 VBA 宏 + DDEAUTO 自动执行",
"status": "completed",
"file": {
"sha256": "…", "md5": "…", "size": 284915,
"real_type": "Microsoft Word 2007+",
"declared_ext": ".docx", "filename": "起诉状.docx"
},
"findings": [
{
"engine": "document", "layer": "L2", "severity": "critical",
"rule": "DDEAutoExecution", "detail": "…", "weight": 65.0
}
],
"extracted": [ { "path": "word/vbaProject.bin", "size": 10240 } ],
"meta": {
"scan_duration_ms": 1840,
"policy_version": "2026.10.1",
"clamav": { "version": "…", "signature": "…" }
}
}
```
### 6.5 同步 / 异步
| 模式 | 请求 | 响应 |
| -- | ------------------------------ | ----------------------------------------------------------------------------- |
| 同步 | `POST /api/v1/scans` | 直接返回完整结论 |
| 异步 | `POST /api/v1/scans`(文件超限或需沙箱) | 返回 `{ "task_id": "…", "status": "pending" }`,轮询 `GET /api/v1/scans/{task_id}` |
### 6.6 版本与兼容策略
* 采用**路径版本**:`/api/v1/`,便于网关路由配置
* v1 契约内的**新增字段**不视为破坏性变更,调用方应忽略未知字段
* **字段删除或语义变更**必须升 v2,v1 与 v2 路径并存
* 响应中始终携带 `meta.policy_version`,便于问题定位
### 6.7 打开风险等级(`open_risk`)
本服务的结论有两个面向:**系统判定** 与 **人工提示**。前者供摆渡系统执行业务逻辑,后者供最终在内网打开文件的用户判断风险。`open_risk` 即为后者的独立字段。
#### 6.7.1 与 `action` 的语义分离
| 字段 | 消费者 | 含义 |
| ----------- | ------------ | ----------------------- |
| `action` | 摆渡系统 | **机器执行**——放行 / 拒绝 / 转复核 |
| `open_risk` | 内网用户 / 安全管理员 | **人阅读**——打开时需要注意什么 |
两者独立演进:提示文案调整不影响判定逻辑;判定规则变更也不强制修改提示模板。
#### 6.7.2 字段结构
```json
{
"open_risk": {
"level": "high",
"factors": ["contains_macro", "attached_template", "external_url"],
"advice": "此文件包含宏与外部模板引用,打开时请勿启用宏,并确认来源可信",
"requires_macro_enable": true
}
}
```
| 字段 | 类型 | 说明 |
| ----------------------- | ----- | -------------------------------------- |
| `level` | 枚举 | `low` / `medium` / `high` / `critical` |
| `factors` | 字符串数组 | 触发该等级的具体因素标识,供前端选择性提示 |
| `advice` | 字符串 | 面向最终用户的中文提示语,可直接展示 |
| `requires_macro_enable` | 布尔 | 该文件是否需要用户手动启用宏才能正常使用(仅提示,不代表检测建议) |
#### 6.7.3 等级定义
| 等级 | 触发条件 | 典型提示 |
| ---------- | ------------------------------------------------------ | -------------- |
| `low` | 无宏、无外链、无嵌入对象、无非常规容器 | 无提示 |
| `medium` | 含普通外部链接 / 二维码 / 隐藏内容 | "请确认链接来源" |
| `high` | 含宏(行为无害)/ 含外部模板引用 / 含嵌入对象(非可执行) | "打开时请勿启用宏" |
| `critical` | 含可执行文件 / ISO / Linux ELF / .desktop / AppImage / 零容忍命中 | "请勿直接双击,联系管理员" |
#### 6.7.4 消费方忽略权
对接方若不需要该字段可直接忽略,**不影响接口兼容**。本服务保证 `open_risk` 始终存在于响应中,即使 `verdict = clean` 也会返回 `level = low` 的结构。
#### 6.7.5 与零容忍的关系
零容忍命中时:`action = reject` 且 `open_risk.level = critical`。两者同时出现,摆渡系统看 `action` 自动拒绝,内网用户若绕过摆渡(通过其他途径拿到文件)也能在安全审计面板看到 `open_risk` 的警告。
***
## 7. 策略与裁决模型
### 7.1 裁决流程
```
检测信号
│
▼
┌─────────────────────────────────┐
│ 0. 零容忍检查(独立机制) │ ── 命中 → 直接 reject,不走评分
└─────────────────────────────────┘
│ 未命中
▼
┌─────────────────────────────────┐
│ 1. 硬性约束检查 │ ── 引擎可用性 / 大小 / 扩展名 / 加密
└─────────────────────────────────┘
│ 通过
▼
┌─────────────────────────────────┐
│ 2. rule_overrides 检查 │ ── 命中 → 按覆盖动作执行
└─────────────────────────────────┘
│ 未命中
▼
┌─────────────────────────────────┐
│ 3. 权重累加评分 + 阈值映射 │ ── 得到 verdict / action / open_risk
└─────────────────────────────────┘
```
**顺序是强制的**:零容忍独立于评分模型,优先级最高。这样"路径穿越 / VBA 自动执行"这类绝对问题不会因为文件其他方面"干净"而被放过。
### 7.2 裁决步骤
| 步骤 | 检查 | 触发后果 |
| -- | ------------------------- | --------------------------------------- |
| 0 | 命中 `zero_tolerance_rules` | **直接 `reject`**,记录原因,跳过后续所有步骤 |
| 1 | 引擎可用性 | `fail_closed` 下直接拒绝 |
| 2 | 文件大小超限 | 直接拒绝 |
| 3 | 扩展名不在白名单 | 直接拒绝 |
| 4 | 文件加密且策略不允许 | 直接拒绝 |
| 5 | 命中 `rule_overrides` | 按覆盖动作执行 |
| 6 | 其余信号权重累加 | 得到评分 |
| 7 | 评分阈值映射 | 得到最终 `verdict` / `action` / `open_risk` |
> **例外机制的切入点**:若文件同时命中零容忍规则和例外条件(见 §7.7),则零容忍检查会额外查询例外表——存在有效例外时跳过该条零容忍,继续进入步骤 1。这是整个裁决流程中唯一的"零容忍放宽"入口。
### 7.3 评分与阈值
| 评分区间 | verdict | action |
| ------------------------------------- | ------------ | ---------------- |
| 0 | `clean` | `pass` |
| 0 \< score \< review_low | `suspicious` | `pass_with_flag` |
| review_low ≤ score \< block_score | `suspicious` | `manual_review` |
| score ≥ block_score | `malicious` | `reject` |
默认阈值:`review_score = [30, 70]`,`block_score = 70`。
### 7.4 策略文件
策略以 YAML 管理,与代码分离。调整裁决规则只改 YAML,不动代码。
```yaml
version: "2026.10.1"
global:
block_score: 70
review_score: [30, 70]
engine_failure_mode: fail_closed
max_file_size: 52428800
sync_max_size: 52428800
allow_encrypted_archive: false
allow_encrypted_document: false
# ===== 零容忍规则集(步骤 0,优先级最高)=====
# 命中即 reject,不走评分。与评分模型完全独立的机制。
zero_tolerance_rules:
- VBAAutoExec
- VBAAutoExecShell
- MRaptorAutoExec
- MRaptorAutoExecSuspicious
- DDEAutoExecution
- PdfJavaScript
- PdfLaunchAction
- PdfOpenAction
- AttachedTemplate
- EmbeddedExecutable
- LnkWithAutoExec
- ChmWithScript
- IsoWithExecutable
- PathTraversal
- MacroObfuscated
allowed_extensions: [ .docx, .pdf, .xlsx, .jpg, .png, .zip ]
sandbox_required_extensions: [ .exe, .msi, .js, .vbs, .iso ]
# ===== 规则覆盖(步骤 5)=====
# 对特定规则强制指定处置动作,独立于权重累加
rule_overrides:
VBAShellInvocation: { action: manual_review, reason: "…" }
ArchiveContainsExecutable: { action: manual_review, reason: "…" }
# ===== 宏行为例外(步骤 0 的唯一放宽入口)=====
# 内网人员需要打开带宏的公文模板,按文件指纹放行
# 详见 §7.7 例外机制
macro_exceptions:
- fingerprint_sha256: "a1b2c3d4..."
filename_pattern: "公文模板*.docm"
reason: "内部公文模板,宏仅执行本地编号与签章定位"
approved_by: "admin"
approved_at: "2026-10-15T10:30:00Z"
expires_at: "2027-10-15T10:30:00Z"
```
策略加载时执行严格校验(阈值区间合法性、动作枚举合法性、扩展名格式、例外的 SHA256 格式、到期时间不早于当前),**校验不通过则拒绝加载并保留旧策略**,防止错误的策略文件导致误放行。
### 7.5 策略版本追溯
每次扫描结果记录 `policy_version` 与 `policy_sha256`。策略重载时在数据库中留存版本快照,支持"按历史策略复现"能力。
### 7.6 零容忍机制详解
#### 7.6.1 为什么独立于评分
评分是**相对度量**——权重累加过阈值才拒绝,天然存在"权重调参"问题。而"打开即执行"载体是**绝对问题**:一个宏文档哪怕只命中一条零容忍规则,也应直接拒。
如果把零容忍规则塞进评分体系(比如给 `PathTraversal` 一个 100 分权重),那么:
* 策略维护者需要记住"这条规则权重必须 ≥ block_score 才会生效"
* 未来有人调低 `block_score` 可能无意间让零容忍规则失效
* 逻辑上"零容忍"就变成了"高权重",语义弱化
**独立机制的好处**:零容忍是一份**不与评分耦合的清单**,增删条目无需考虑权重平衡。
#### 7.6.2 清单来源
当前零容忍规则集中的所有条目来源于 §4.8.3 的分层载体判定表。未来新增零容忍规则的准入条件:
| 条件 | 说明 |
| -------- | ------------------- |
| 命中即有害 | 不存在"合法使用"的场景(如路径穿越) |
| 无法通过权重平衡 | 即使其他信号都是干净的,命中本身即应拒 |
| 可稳定判定 | 不依赖大模型或主观判断 |
宏的处理是唯一例外——存在"合法宏模板"场景,因此引入例外机制(§7.7)而非直接把所有宏相关规则放进零容忍集。
#### 7.6.3 与 `rule_overrides` 的交互
```
zero_tolerance_rules → 步骤 0 最先检查,命中直接 reject
rule_overrides → 步骤 5 在零容忍未命中后检查
```
两者**不重叠**。如果某规则在零容忍清单中,它不会再出现在 `rule_overrides` 的覆盖对象里——因为零容忍已经处理了它。`rule_overrides` 仅针对"未进零容忍集但需要强制处置"的规则(如 `VBAShellInvocation`)。
### 7.7 宏行为例外机制
内网业务场景下,需要打开带宏的公文模板(自动编号、签章定位等),这类宏**不做网络访问、不调用系统命令、仅在本地操作文档**。零容忍机制必须为此预留受控的放宽入口。
#### 7.7.1 五道保险
| 保险 | 机制 | 效果 |
| --------- | ---------------------------- | ------------------------------------------------------ |
| **指纹绑定** | 例外按 `sha256` 精确匹配 | 换一个字节的模板文件就不匹配,攻击者无法批量绕过 |
| **双因素匹配** | 同时校验指纹 + 文件名模式(glob) | 防止同哈希文件被不同文件名复用 |
| **必须到期** | 例外必须有 `expires_at`,最长不超过 1 年 | 防止过期例外长期有效;到期自动失效 |
| **审批留痕** | 创建例外需 `approved_by` + 审计日志 | 谁批的、为什么批、批了什么全部可追溯 |
| **行为前提** | 例外仅对"无危险 API"的宏生效(§4.8.4 判定) | 宏虽在例外中,但若检测到 Shell 调用 / URLDownloadToFile / 混淆等,仍触发零容忍 |
#### 7.7.2 例外如何生效
```
文件进入零容忍检查 ──► 命中 VBAAutoExec ──► 查询例外表
│
┌───────────┴───────────┐
▼ ▼
存在有效例外 无有效例外
(指纹 + 文件名 + 或 已过期
宏行为无害)
│ │
▼ ▼
跳过此条零容忍 零容忍 reject
继续步骤 1
```
**关键约束**:例外是**逐规则、逐文件**的,不是"对某类文件全部例外"。一个例外只对清单中明确列出的那一条零容忍规则生效(如仅放宽 `VBAAutoExec`,但 `DDEAutoExecution` 仍会触发零容忍)。
#### 7.7.3 例外的审批流程
| 方式 | 描述 | 适用 |
| ----------------- | ------------------------------------------------------------------------ | ---------------------------- |
| **线下审批 + 写进策略文件** | 业务侧提交书面申请 → 安全管理员审核 → 写入 `policy.yaml` 的 `macro_exceptions` 段 → 控制台触发热重载 | 一期默认方式,流程清晰、审计留痕自然 |
| 系统内审批流 | 控制台内发起申请 → 另一名管理员审批 → 自动入库并热重载 | 待后续评估,一期不做(与线下方式等价,但开发量显著增加) |
**一期采用线下审批**。理由:例外数量预计很少(可能 \<10 条),不值得为其开发审批工作流。控制台的配置编辑页面(§9.7)提供例外表的可视化增删改查。
***
## 8. 部署架构
### 8.1 容器拓扑
```yaml
services:
api: # FastAPI 应用(API + 控制台)
clamav: # clamd 守护进程
db: # PostgreSQL
redis: # 任务队列 / 幂等缓存 / 限流 / nonce
nginx: # TLS 终止 + 静态资源 + 反向代理
```
单机 Docker Compose 编排,无需 Kubernetes。
### 8.2 目标环境
| 环境 | 说明 |
| ---------------- | --------------------------------------------------------- |
| **检测服务部署(服务器端)** | Ubuntu 20.04+ / 麒麟 V10(服务器版),x86_64 架构 |
| **容器运行时** | Docker 20.10+ / Docker Compose v2 |
| **资源要求** | ≥ 4 核 8 GB(ClamAV 签名库加载需约 2 GB 内存),磁盘 ≥ 50 GB |
| **网络** | 检测服务部署在隔离区,仅对摆渡系统开放 443 |
| **目标终端环境** | 麒麟桌面/UOS(x86_64)+ WPS Office,纯 Linux 桌面环境(见 §4.8.2 威胁模型) |
### 8.3 签名库离线更新流程
```
① 外网同步机:freshclam 每日拉取官方 CVD
② 外网镜像:cvdupdate 模式提供私有镜像
③ 单向导入:通过光闸/介质将签名库传入内网
④ 内网分发:内网节点从内网镜像增量同步
⑤ clamd 加载:更新签名库并重载
⑥ 验证:GET /api/v1/health 确认版本与更新时间
```
**要求**:更新流程需文档化并纳入运维手册;签名库超过 7 天未更新应在健康检查中告警。
### 8.4 网络访问控制
| 源 | 目标 | 端口 | 说明 |
| ----- | ---------- | ----------- | ------- |
| 摆渡系统 | Nginx | 443 | 检测接口 |
| 运维终端 | Nginx | 443 | 控制台(按需) |
| Nginx | api | 8000 | 内部 |
| api | clamav | 3310 | 内部 |
| api | db / redis | 5432 / 6379 | 内部 |
| api | 外部 | — | **禁止** |
***
## 9. 在线调试台与文档体系
### 9.1 文档体系
保持精简,只保留两份:
| 文档 | 读者 | 内容 | 载体 |
| ------ | ------- | ----------------------- | ------------------- |
| 本文档 | 全体 | 总体方案(架构、检测能力、安全设计、演进路线) | Markdown |
| 《接口文档》 | 对接方开发人员 | API 契约 + 签名规范 + 多语言示例 | Markdown(**对外交付物**) |
其他内容按需在本文档内补充章节,不单独成文。运维手册、README 等在方案定稿后再补。
### 9.2 为何不能只提供 Swagger
| 问题 | 说明 |
| ------------------- | --------------------------------------------------------- |
| 不体现签名机制 | Swagger 的 "Try it out" 必然失败(缺签名头),对接方会误判接口故障 |
| 不体现 multipart 签名特殊性 | 文件上传时 body 哈希如何计算、`Content-Type` 含随机 boundary 的处理方式必须文字说明 |
| 不体现响应验签 | 对接方若不做验签则失去防篡改保障,而这不会在 Swagger 中体现 |
因此文档必须是\*\*"人读 Markdown + 机读 OpenAPI + 可运行示例代码"\*\* 三件套。
### 9.3 在线调试台组成
| 页面 | 路径 | 说明 |
| ---------- | ------------------ | ------------------------------ |
| Swagger UI | `/docs` | FastAPI 生成,含中文描述、示例值、枚举说明 |
| 签名调试台 | `/console/signing` | 表单输入 → 实时生成签名头 → 一键复制 |
| 请求模拟器 | `/console/try` | 构造带签名请求并实际发送,展示完整 HTTP 报文与验签结果 |
| 历史任务 | `/console/tasks` | 按时间/结论筛选,查看详情与 findings |
| 审计查询 | `/console/audit` | 查询审计日志,触发链完整性自检 |
| 引擎看板 | `/console/health` | 各引擎状态、签名库版本、队列深度 |
**关键设计**:调试台自行实现一遍签名并展示验签计算过程,让对接方直观理解"签名怎么来、怎么验",比读十页文字更快。
### 9.4 控制台必须走正式接口
**控制台不得直接调用内部扫描函数**,必须经由完整 HTTP 链路:
```
浏览器 ──▶ /console/api/* ──▶ httpx(带签名) ──▶ /api/v1/scans ──▶ 业务逻辑
```
理由:
1. 测试出的是**真实对接体验**,包含签名正确性、响应验签头等
2. 避免"控制台能跑通但对接方跑不通"的旁路假象
3. 控制台自身即为一个调用方,形成 dogfooding 验证
**实现要点**:控制台持有独立的内部凭证 `client_id = console-internal`,其调用在审计日志中与外部调用方一致,可区分"人工上传测试"与"系统自动扫描"。
### 9.5 门控与部署模式
配置项(`config/console.yaml`):
```yaml
console:
mode: always_on # always_on / enabled / internal_only
show_api_docs: false
show_signing_tool: false
allow_live_scan: false
show_full_findings: false
allowed_cidrs: [] # internal_only 模式下的允许网段
```
| 模式 | 控制台 | /docs | 适用 |
| --------------- | ----- | ----- | ------------ |
| `always_on` | 关闭 | 关闭 | **生产默认** |
| `enabled` | 开放 | 开放 | 开发测试 |
| `internal_only` | 限指定网段 | 限指定网段 | 生产但内部团队需查阅文档 |
**关闭的实现方式**:在**路由注册期**决定,而非运行期判断。
```python
if console_cfg.mode != "always_on":
app.include_router(console_router, prefix="/console")
```
这样生产环境中 `/console` 与 `/docs` 在路由表中根本不存在,外部扫描得到 404 —— 比返回 403 更好,因为 403 会暴露"这里有东西"。
**注意**:`openapi_url` 需同步控制,否则关闭 UI 但保留 `/openapi.json` 等于文档仍在被爬取。
### 9.6 对外文档的信息边界
对外文档需控制信息暴露程度:
| 应当提供 | 不应提供 |
| -------------- | ---------- |
| API 契约与字段枚举 | YARA 规则正文 |
| 签名规范与校验向量 | 内部代码结构与目录 |
| 规则名 + 含义 + 严重度 | 引擎版本号与依赖细节 |
| 多语言完整示例代码 | 绕过检测的手法说明 |
### 9.7 策略配置页面
#### 9.7.1 核心原则:数据库为准
配置同时以 YAML 文件和数据库两种形式存在,但**数据库是权威数据源**:
| 项 | 说明 |
| ------- | ---------------------------------------------------- |
| 权威源 | `policy_versions` 表 + `macro_exceptions` 表,控制台编辑直接写库 |
| YAML 文件 | 每次发布版本时从数据库**导出**,供文件备份与容器镜像打包使用 |
| 加载方式 | API 服务启动时从数据库加载当前生效版本,而非读 YAML 文件 |
| 一致性 | 数据库与 YAML 的 SHA256 定期校验,不一致则告警 |
**为什么数据库为准**:实施人员通过网页改配置时,不可能手动同步修改文件和重新部署容器。数据库方案让"编辑 → 热重载"变为一次操作。
#### 9.7.2 双模式编辑
```
┌──────────────────────────────────────────────────┐
│ 策略编辑页 /console/config │
├──────────────┬───────────────────────────────────┤
│ 📋 表单模式 │ 📝 YAML 模式 │
│ │ │
│ · 分组卡片 │ 完整 YAML 编辑器(只读高亮) │
│ · 下拉框/开关 │ 直接编辑原始结构 │
│ · 带校验提示 │ 高级用户可精确控制字段 │
│ · 初学者友好 │ 实施人员可直接粘贴整段配置 │
└──────────────┴───────────────────────────────────┘
│ │
└────────┬───────────┘
▼
统一后端校验 → 保存到数据库 → 触发热重载
```
| 模式 | 适合场景 | 特点 |
| ------- | ---------- | --------------------------------------- |
| 表单模式 | 运维人员日常调参 | 分组卡片、枚举下拉、阈值滑块、SHA256 格式校验、到期时间日历选择 |
| YAML 模式 | 高级实施人员批量配置 | 与 `policy.yaml` 完全同结构、语法高亮、粘贴即校验、实时预览影响 |
两种模式共享同一份后端校验逻辑,保存时执行相同的完整校验(§7.4 策略文件校验规则)。
#### 9.7.3 策略页面分区
```
策略配置页
├── ① 基本裁决参数(global)
│ ├── block_score / review_score 阈值滑块
│ ├── engine_failure_mode 开关
│ └── 各文件大小上限
│
├── ② 零容忍规则集(zero_tolerance_rules)
│ ├── 全部规则,每条独立开关
│ ├── 新增 / 删除条目(需填规则名)
│ └── 每条附规则含义说明与来源
│
├── ③ 规则覆盖(rule_overrides)
│ ├── key = 规则名,value = {action, reason}
│ ├── 下拉框列出已注册的全部规则供选择
│ └── action 枚举限制为 reject / manual_review
│
├── ④ 宏行为例外(macro_exceptions)
│ ├── 表格:指纹 / 文件名模式 / 原因 / 审批人 / 到期时间
│ ├── 新增时校验 SHA256 格式、到期时间
│ ├── 到期自动标记失效,保留历史记录
│ └── 支持"扫描中发现需例外的文件 → 一键添加"快捷入口
│
├── ⑤ 允许的扩展名(allowed_extensions)
│ └── 勾选式多选项,附格式说明
│
└── ⑥ 版本管理面板
├── 当前版本号 / SHA256 / 创建时间 / 创建人
├── 历史版本列表(可按版本号 / 时间筛选)
├── 点击历史版本 → 只读预览
└── 一键回滚到任意历史版本
```
#### 9.7.4 保存校验流程
```
用户点击"保存"
│
▼
前端基本校验(必填 / 格式 / 枚举范围)
│ 通过
▼
后端完整校验(与 §7.4 策略文件校验规则相同)
│ 通过
▼
写入 policy_versions 表(新行,状态 = pending)
│
▼
触发热重载 /api/v1/policies/reload
│ 成功
▼
更新 policy_versions 状态 → active(旧版本自动标记 archived)
│
▼
导出 YAML 到 `config/policy.yaml`(供备份)
│
▼
审计日志记录完整 diff
│
┌───────── 失败分支 ─────────┐
▼ ▼
热重载失败 校验失败(极罕见)
│ │
▼ ▼
新策略自动标记 archived 返回具体字段错误
继续使用旧策略 不写入数据库
```
**关键设计**:任何环节失败都不会让系统进入"无有效策略"状态。
#### 9.7.5 权限分级
| 角色 | 权限 |
| ---------- | --------------------------------------------------- |
| `admin` | 完整读写:编辑策略各段、增删零容忍规则、增删例外、回滚版本 |
| `operator` | 只读 + 例外增删:可查看全部配置,可新增/删除宏行为例外(需审批留痕),不可修改裁决阈值或零容忍规则 |
| `viewer` | 只读:仅查看当前生效策略与历史版本,不可编辑 |
> **等保三级对应**:权限分级即"访问控制"要求的落地。`operator` 角色可管例外(因为是日常运维高频操作)但不能改裁决逻辑,降低误操作风险。
***
## 10. 实施路线
> **原则**:一期聚焦核心风险敞口——"打开即执行"载体的零容忍拦截 + 恶意文件识别。其余能力按风险收益排序。沙箱(原 P4)与大模型(原 P5)已从实施计划中移除,前者见 §12.4,后者见 §12.1。
### 10.1 阶段总览
| 阶段 | 定位 | 核心内容 | 交付物 |
| ------------- | ----------- | ----------------------------------------------------------------------------------------------------------------- | -------------------- |
| **P0 核心引擎** | 能跑通、能拦核心风险 | 项目骨架 + 安全层 + L0/L1/L2 检测流水线 + **零容忍机制** + **宏行为分级** + **LNK 深度解析** + **URL/二维码提取** + **open_risk 等级** + **例外机制** | 完整检测引擎,覆盖场景中最高频的恶意载体 |
| **P1 扩展检测** | 覆盖剩余格式与启发式 | ISO 挂载内递归 + CHM 复合文档校验 + 内网特征词表引擎 + 畸形文件启发式检测 + 同步/异步任务编排 | 覆盖全部目标格式,降低误报率 |
| **P2 控制台与部署** | 可配置、可运维、可交付 | 控制台(登录/锁定/CSRF)+ **策略配置页面**(§9.7 双模式/版本管理/回滚)+ Docker Compose 编排 + Nginx TLS + 签名调试台 + 审计链自检 | 单机可部署、实施人员可操作的完整系统 |
| **P3 接口与测试** | 正式交付 | 对外接口文档(含签名规范、校验向量、四语言示例)+ 单元/集成测试 + 恶意样本回归测试集 | 可交付、可联调、可验收 |
### 10.2 各阶段详细内容
#### P0 核心引擎
**目标**:覆盖场景中最高频、最危险的恶意载体。能跑通一条完整的"上传 → 检测 → 裁决 → 返回结论"链路。
| 模块 | 具体工作 | 优先级理由 |
| ----------------- | --------------------------------------------------------------------------- | ------------------------ |
| 项目骨架 | FastAPI + PostgreSQL + Redis + 配置体系 + ORM + 安全层(HKDF / 签名 / PBKDF2 / 审计哈希链) | 全部上层的基础 |
| L0 结构层 | 真实类型识别 / 伪装检测 / 递归安全解包 / 路径穿越 / zip bomb | 拦截 60% 以上的人工伪装攻击 |
| L1 ClamAV | clamd 接入 + INSTREAM 协议 + 签名库版本记录 | 已知恶意样本的基本拦截 |
| L2 文档深度 | oletools(olevba + mraptor + msodde + oleobj)+ pypdf + OOXML 解析 | 宏 / DDE / PDF JS 是场景核心风险 |
| **零容忍机制** | 当前零容忍规则集(§4.8.4,含跨平台 / Linux 专属 / 纵深防御三层)+ 独立裁决步骤(§7.2 步骤 0) | 打开即执行载体必须零容忍 |
| **宏行为分级** | 危险 API 清单 + 自动执行入口检测 + 混淆特征识别(§4.8.4) | 区分"有害宏"与"公文模板宏" |
| **LNK 深度解析** | LnkParse3 库 + 目标路径/参数解析 + 远程链接检测 | LNK 是高频钓鱼载体 |
| **URL/二维码提取** | 文档外部链接部件解析 + zxing/opencv 二维码解码 + 恶意 URL 库查询(§4.8.6) | 链接与二维码是常见诱导入口 |
| **open_risk 等级** | 四个等级 + factors + advice 模板(§6.7) | 系统判定与人工提示分离 |
| **例外机制** | 宏行为例外的五道保险 + 审批留痕 + 到期自动失效(§7.7) | 必须支持合法公文模板的受控放行 |
| 策略引擎 | PolicyStore 加载校验 + PolicyEngine 裁决(含零容忍 + 评分 + rule_overrides) | 全部检测信号的裁决中枢 |
| 扫描编排 | 流水线编排 + 递归队列 + 引擎降级处理 | 让各引擎协同工作 |
| API 路由 | 扫描提交 / 结果查询 / health / policies/reload | 对外接口的最小集合 |
#### P1 扩展检测
**目标**:覆盖 P0 未涉及的格式和启发式检测,降低误报率。
| 模块 | 具体工作 | 优先级理由 |
| ------------- | -------------------------------------- | ------------------ |
| ISO 挂载内递归 | 挂载后自动扫描可执行文件(§4.8.2 IsoWithExecutable) | ISO 是"打开即挂载"载体 |
| CHM 复合文档校验 | 类型识别 + 结构完整性校验(§4.8.2 ChmWithScript) | CHM 帮助文件可执行脚本 |
| 内网特征词表引擎 | 词表匹配 + 正则 + 组合规则 | 识别内网特有模板与特征,辅助例外判断 |
| 畸形文件启发式 | 结构完整性校验 + 非标准字段检测 | 降低解析器漏洞可利用性 |
| YARA + pefile | YARA 规则库集成 + PE 节区熵值 / 导入表 / 签名目录分析 | 二进制文件的恶意检测 |
| 同步/异步任务 | 大文件异步处理 + task_id 轮询 + 队列管理 | 避免 HTTP 长连接超时 |
#### P2 控制台与部署
**目标**:让实施人员能操作(配置、查看、调试)、能部署(一键启动)、能通过安全测评。
| 模块 | 具体工作 | 对应章节 |
| -------------- | ---------------------------------------- | ------------- |
| 控制台认证 | 登录 / 失败锁定 / CSRF / 30 分钟会话 | §5.3 |
| **策略配置页面** | 表单+YAML 双模式 / 数据库为准 / 版本历史 / 一键回滚 / 权限分级 | §9.7 |
| 签名调试台 | 实时生成签名头 / 展示验签过程 | §9.3 |
| 历史任务 / 审计查询 | 任务列表筛选 + 审计链自检 | §9.3 / §5.4 |
| 引擎看板 | 各引擎状态 + 签名库版本 + 队列深度 | §9.3 |
| Docker Compose | api + clamav + db + redis + nginx 编排 | §8.1 |
| Nginx TLS | TLS 1.2+ 终止 + 反向代理 + 静态资源 | §8.2 / §5.6.3 |
| 离线签名库同步 | 外网镜像 + 单向导入 + 内网分发 + 超期告警 | §4.3.2 / §8.3 |
#### P3 接口与测试
**目标**:正式交付物完备,对接方可联调,验收可复现。
| 模块 | 具体工作 | 交付形式 |
| --------- | ---------------------------------------------- | --------------- |
| 对外接口文档 | 签名规范 + 校验向量 + 四语言示例(Python / Java / C# / Go) | Markdown(已完成初稿) |
| 单元测试 | 各引擎独立测试 + 策略裁决测试 + 签名/验签测试 | `tests/` 目录 |
| 集成测试 | 端到端扫描链路 + 异常引擎降级 + 热重载 | 测试脚本 |
| 恶意样本回归测试集 | 覆盖零容忍全部规则 + 宏分级 + Linux 专属载体 + 纵深防御 Windows 载体 | 样本库 + 期望结果表 |
### 10.3 阶段出口标准
**P0 出口(核心引擎可用)**
| 检查项 | 通过标准 |
| ------------- | --------------------------------------------------- |
| 零容忍规则集 | 全部正确触发 reject,不走评分 |
| 宏行为分级 | 有害宏(Shell/URLDownloadToFile)触发零容忍,无害宏(仅本地文档操作)放行或标记 |
| LNK 深度解析 | 指向 exe / 远程路径 / 脚本的 LNK 零容忍拦截 |
| URL / 二维码 | 恶意库命中→零容忍;非常规端口→转复核;普通链接→放行但提示 |
| open_risk 等级 | 各等级正确映射,与 action 同时返回 |
| 例外机制 | 指纹匹配 + 文件名匹配 + 到期过期自动失效 |
| 引擎不可用 | `fail_closed` 下拒绝文件 |
| 审计哈希链 | 扫描结果 + 策略变更 + 例外增删全部留痕且链可校验 |
**P1 出口(覆盖全部格式)**
| 检查项 | 通过标准 |
| -------- | ------------------------ |
| ISO 递归扫描 | 挂载后内部 exe/msi 被拦截 |
| CHM 识别 | 类型识别正确,恶意 CHM 零容忍 |
| 畸形文件检测 | 结构异常的文档触发 warning,不崩 |
| 误报回归 | 引入 P1 能力后正常业务文件误报率不高于 P0 |
**P2 出口(可交付)**
| 检查项 | 通过标准 |
| ------------------ | --------------------------------------- |
| 控制台 `always_on` 模式 | 路由表中无 `/console` 和 `/docs`,外部扫描返回 404 |
| 策略配置页面 | 表单模式与 YAML 模式都能正确编辑、保存、热重载;失败时回滚 |
| 版本管理 | 可查历史版本、可一键回滚、回滚后立即生效 |
| 控制台签名链路 | 控制台上传的测试走完整签名链路,审计日志标记 `source=console` |
| Docker Compose | `docker compose up -d` 一键启动,全部容器健康 |
| TLS | 仅 443 暴露,无明文端口 |
**P3 出口(可联调可验收)**
| 检查项 | 通过标准 |
| -------- | ----------------------------------------------- |
| 接口文档校验向量 | 对接方可直接用于单元测试(已预跑通过) |
| 四语言示例 | Python / Java / C# / Go 四套 SDK 骨架 + 可运行的签名/验签示例 |
| 回归测试集 | 全部零容忍规则 + 宏分级 + Linux 专属载体样本,预期结果与实际结果 100% 一致 |
***
## 11. 风险与应对
| 编号 | 风险 | 影响 | 应对 | 责任阶段 |
| --- | --------- | --------------- | ----------------------------- | ---- |
| R1 | 病毒库长期不更新 | 检测能力形同虚设 | 自动化离线同步流程 + 超期告警(§8.3) | P2 |
| R2 | YARA 规则失准 | 误报影响业务 / 漏报造成风险 | 规则版本管理 + 定期回归测试集 | P3 |
| R3 | | 摆渡业务无法开展 | `manual_review` 通道 + 人工复核回写 | P1 |
| R4 | 引擎性能瓶颈 | 吞吐不足 | clamd 常驻 + 异步模式 + 水平扩展 worker | P1 |
| R5 | 大文件解包耗尽资源 | 服务不可用 | 解包配额 + 超时 + 容器资源限制 | P1 |
| R6 | 对接方签名实现错误 | 联调受阻 | 文档校验向量 + 调试台 + SDK | P3 |
| R7 | 审计日志被删 | 合规不达标 | 哈希链 + 链校验自检接口 | P1 |
| R8 | 密钥泄露 | 伪造检测结论 | 环境变量注入 + 用途隔离派生 + 定期轮换 | P2 |
| R9 | 控制台暴露攻击面 | 被探测 / 被利用 | 生产默认关闭 + 登录锁定 + 审计 | P2 |
| R10 | 接口契约变更 | 对接方返工 | 路径版本 + 兼容策略 + 变更记录 | P3 |
| | | | | |
***
## 12. 长期演进预研(非本期实施内容)
### 12.1 本期定位:确定性能力优先
经需求澄清,本期(一期)**不引入大模型 / AI 能力**。所有检测结论均由**确定性手段**产出:
| 特性 | 确定性手段 | 大模型手段 |
| ---- | ------------ | -------------- |
| 可复现性 | ✅ 同输入必同输出 | ❌ 存在随机性 |
| 可举证性 | ✅ 命中哪条规则清晰可述 | ❌ 结论难以向当事人解释 |
| 资源依赖 | ✅ 无需推理算力 | ❌ 需 GPU / 推理服务 |
| 延迟 | ✅ 毫秒\~秒级 | ❌ 秒级\~十秒级 |
| 幻觉风险 | ✅ 无 | ❌ 存在 |
在法院 / 政务场景下,「可举证」与「可复现」是**硬性要求**——检测结论可能需要向当事人出示。因此本期以确定性规则为主是正确取舍。
**代价与补偿**:规则无法覆盖「未知形态」与「语义层面」,这是客观局限。本方案的补偿措施是:
| 局限 | 补偿措施 |
| -------- | -------------------------------- |
| 新型攻击形态滞后 | 规则库版本管理 + 定期回归测试 + 快速更新流程 |
| 无法理解语义 | 本期不做(见 §12.3),依靠用户侧风险提示(见 §6.7) |
| 误报难以根治 | 零容忍 + 分级 + 例外机制 + 人工复核通道(见 §7.5) |
### 12.2 三层能力模型(架构预留)
架构上仍保留三层结构,语义层作为**可插拔扩展点**预留,确保未来引入时无需重构:
```
┌─────────────────────────────────────────────────────┐
│ L-S 语义分析层(长期预研,一期不实现) │
│ 大模型 / 语义规则 / 上下文关联判断 │
│ 产出:语义风险信号 + 解释性结论 │
├─────────────────────────────────────────────────────┤
│ L-R 规则分析层(本期实现) │
│ ClamAV / YARA / oletools / pefile / LnkParse │
│ 产出:确定性的命中信号 │
├─────────────────────────────────────────────────────┤
│ L-D 数据层(本期实现) │
│ 结构识别 / 递归解包 / 哈希 / 类型判定 │
│ 产出:文件的基础属性与容器结构 │
└─────────────────────────────────────────────────────┘
```
**预留的具体形式**:
| 项 | 预留内容 |
| ---- | ---------------------------------------------------------- |
| 引擎接口 | `Engine` 基类的 `layer` 字段已支持 `LS`;未来新增 `SemanticEngine` 即可注册 |
| 信号结构 | `Finding.meta` 中预留 `deterministic` 字段,用于标记信号来源的确定性 |
| 配置 | 策略中预留 `semantic.enabled` 开关(默认关闭) |
| 裁决 | 策略引擎支持按 `deterministic` 设置权重上限,无需改动裁决逻辑 |
### 12.3 长期预研方向(不列入实施计划)
以下方向经评估有价值,但因依赖算力、效果待验证、举证效力待确认,**本期不实施**:
| 方向 | 潜在价值 | 暂缓原因 |
| -------- | ----------------- | -------------------- |
| 诱导话术识别 | 识别"请登录此链接办理"类诱导表达 | 需求已明确本期不需要 |
| 仿冒公文模板识别 | 判断内容是否符合真实公文体例 | 需模板库 + 效果验证 |
| 上下文关联分析 | 识别批量钓鱼、机器化命名 | 纯统计方法即可实现,不需模型,可独立推进 |
| 规则辅助生成 | 缩短新威胁的规则覆盖周期 | 属研发辅助工具,不在运行时链路 |
| 辅助复核摘要 | 降低人工复核成本 | 可先用模板化摘要替代 |
**若未来引入大模型,必须满足的约束**(提前记录,避免后续返工):
| 约束 | 要求 |
| --------- | ------------------------------- |
| 完全离线、本地推理 | 模型权重部署在内网,不调用外部 API(数据外传违反隔离要求) |
| 模型选型 | 优先可商用授权的开源模型(Qwen 系列、GLM 系列等) |
| 只喂提取物 | 仅提供解包后的文本、宏源码、脚本内容,不提供原文件 |
| 不单独裁决 | 模型输出作为信号之一参与评分,权重受限,不可作为唯一拒绝依据 |
| 可一键关闭 | 模型不可用时降级为纯规则模式,主流程不受影响 |
| 决策留痕 | 模型版本、提示词版本、输入摘要哈希、原始输出全部记录 |
### 12.4 沙箱(L3)的定位调整
原方案将动态沙箱列为 P4 可选。结合需求澄清(内网为国产化终端、以文档为主),**建议将沙箱从实施计划中移除**,仅作为长期可选项保留。
| 考量 | 分析 |
| ---- | ------------------------------------------------------- |
| 环境适配 | CAPE / DRAKVUF 依赖 Windows 客体与裸金属虚拟化(VT-x/EPT),与国产化环境不匹配 |
| 场景适配 | 场景以文档为主,静态分析对文档类样本覆盖度已较高 |
| 投入产出 | 一套沙箱环境的投入 ≈ 整个检测服务的开发投入 |
| 替代方案 | 结构完整性校验 + 畸形文件检测,成本低一个数量级,覆盖部分解析器漏洞风险 |
**替代措施**:对高危解析路径(字体、图像、压缩流、复合文档)增加结构完整性校验,检测畸形构造。虽无法根治解析器漏洞,但可显著降低可利用性。
**解析器漏洞风险的定位**:该类风险**无法由检测服务单方面消除**,属于终端侧加固范畴(打补丁、限制字体自动加载、禁用宏)。检测服务的责任是识别出「该格式存在解析器攻击面」并在结论中提示,不给出「检测通过即绝对安全」的暗示。
***
***
## 13. 待确认事项
### 13.2 已确认(方案中已有明确结论)
| 编号 | 事项 | 决定 | 写入位置 |
| ------- | ------------ | ----------------------------------------------------------------------- | --------------- |
| Q1 | 对外文档形式 | 双文档:总体方案(本文档 Markdown)+ 接口文档(对外交付 Markdown) | §9.1 |
| Q2 | 官方 SDK 优先级 | 一期提供 Python SDK;Java / C# / Go 给完整示例代码 | 接口文档 |
| Q3 | 接口版本策略 | 路径版本 `/api/v1/`,v2 路径并存 | §6.6 |
| Q4 | 对外文档规则清单粒度 | 给到"规则名 + 含义 + 严重度"级别,不暴露规则正文 | §9.6 |
| Q5 | 控制台任务标记 | 共用数据库,打 `source=console` 标记 | §9.4 |
| Q6 | 沙箱是否纳入一期 | **不纳入**。架构预留,环境不匹配且投入产出失衡 | §10 总览 + §12.4 |
| Q7 | 审计日志对接集中审计平台 | 一期提供导出接口 | §5.4 |
| Q8 | 大模型接入的算力与选型 | **不纳入一期**。长期预研,架构预留语义层扩展点 | §12.1 / §12.2 |
| Q9 | 语义层信号的证据效力定位 | **不纳入一期**。长期预研时需确认合规意见 | §12.3 |
| Q10 | 内网外发方向的内容审计 | **一期不做**。依赖业务密级规则,作为后续独立需求立项 | §1.3 |
| Q11 | 例外机制的审批方式 | **一期用线下审批 + 写进策略文件**,系统内审批流后续评估 | §7.7.3 |
| Q12 | 配置编辑方式 | **数据库为准**,表单+YAML 双模式,版本历史 + 一键回滚 | §9.7.1 / §9.7.2 |
| Q13 | 等保双因素认证 | **一期依赖部署侧统一身份认证**,服务自身实现 TOTP 列为待补 | §5.6.2 |
| **Q14** | **国产化终端 OS** | **麒麟桌面/UOS(x86_64)+ WPS Office**,纯 Linux 桌面环境 | §4.8.2 |
| **Q15** | **WPS 使用情况** | **内网基本用 WPS,也有用操作系统自带 Office 的**;AutoOpen/Shell 调用在 WPS on Linux 上需实测验证 | §4.8.5 |
### 13.3 待确认(影响实现方向或验收标准)
以下事项需在对应阶段启动前确认,否则会影响实现方案:
| 编号 | 事项 | 为什么重要 | 建议方案 | 需在何阶段确认 |
| ------- | ------------------------- | -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ---------------- |
| **Q20** | **WPS on 麒麟/UOS 宏行为实测结果** | AutoOpen/Workbook_Open 是否自动触发;Shell/CreateObject 是否有效——决定宏相关零容忍规则在 Linux 上的威胁等级 | 制作 3\~5 个测试宏模板(AutoOpen + Shell、AutoOpen + Download、纯本地操作),在 WPS on 麒麟桌面打开验证 | **P0 开发前(必须完成)** |
| **Q16** | **摆渡系统的调用技术栈** | 决定 SDK 实际优先级。若摆渡系统用 Java,则 Python SDK 可以延后 | 摆渡系统开发侧提供技术栈确认 | P3 启动前(影响交付形式) |
| **Q17** | **配置变更是否需要草稿+发布模式** | 当前方案是"编辑 → 立即热重载",变更即时生效。多人协作时可能需要草稿区 + 审核发布两步走 | 单人实施可简化为立即生效;多人协作建议加草稿+发布 | P2 启动前(影响控制台开发量) |
| **Q18** | **ClamAV 签名库的离线同步由谁运维** | 签名库超过 7 天不更新会触发健康检查告警。需明确:外网同步机谁管、单向导入介质谁负责、内网分发谁维护 | 由实施侧运维团队负责,服务只提供版本检查与告警 | P2 部署前(影响运维方案) |
| **Q19** | **是否需要对接内部统一身份认证** | §5.6.2 提到控制台双因素认证的依赖。若对接 UAC/CA,则控制台自身不需实现 TOTP;否则需要 | 优先对接既有统一认证;无则实现 TOTP | P2 开发前 |
***
## 附录 A:已确定的技术选型
| 项目 | 选型 | 说明 |
| ------ | ------------------------- | ---------------- |
| 开发语言 | Python 3.11+ | 检测生态最完整 |
| Web 框架 | FastAPI + Uvicorn | 异步、原生 OpenAPI |
| 数据库 | PostgreSQL 15 | 任务、策略、审计 |
| 缓存/队列 | Redis 7 | nonce、限流、幂等、异步队列 |
| 容器编排 | Docker Compose | 单机足够,无需 K8s |
| 病毒引擎 | ClamAV(clamd) | 签名库离线镜像 |
| 文档检测 | oletools + pypdf + pefile | Python 原生生态 |
| 规则引擎 | YARA 4.5(yara-python) | 可嵌入进程,性能优于命令行 |
| 反向代理 | Nginx | TLS 终止 + 静态资源 |
| 目标系统 | Ubuntu / 麒麟 V10 | 国产化适配 |
## 附录 B:项目结构规划
```
MeshSafe/
├── app/
│ ├── main.py # 应用入口、路由注册、门控
│ ├── config.py # 配置加载
│ ├── db.py # 数据库会话
│ ├── models.py # ORM 模型
│ ├── api/ # /api/v1 路由
│ │ ├── scans.py
│ │ ├── policies.py
│ │ ├── health.py
│ │ └── audit.py
│ ├── console/ # 控制台(可关闭)
│ │ ├── router.py
│ │ ├── auth.py
│ │ ├── views.py
│ │ └── templates/
│ ├── engines/ # 检测引擎
│ │ ├── base.py
│ │ ├── structure.py # L0
│ │ ├── extractor.py # L0 安全解包
│ │ ├── clamav.py # L1
│ │ ├── documents.py # L2
│ │ └── binary.py # L2B
│ ├── security/ # 安全层
│ │ ├── crypto.py # 口令哈希、HKDF
│ │ ├── signing.py # 请求/响应签名
│ │ └── deps.py # 认证依赖、限流
│ ├── services/
│ │ ├── policy.py # 策略引擎
│ │ ├── scanner.py # 扫描编排
│ │ ├── audit.py # 审计哈希链
│ │ └── tasks.py # 异步任务
│ └── templates/ # 模板
├── config/
│ ├── policy.yaml # 全局检测策略
│ └── console.yaml # 控制台门控
├── rules/ # YARA 规则库
├── docs/ # 文档
├── scripts/ # 运维脚本(含签名示例)
├── tests/ # 测试
├── Dockerfile
├── docker-compose.yml
├── nginx/
│ └── nginx.conf
├── requirements.txt
└── .env.example
```
***
**文档结束** · 下一步:《接口文档》(对外交付物)