Files
MeshSate/docs/00-总体方案.md

1679 lines
103 KiB
Markdown
Raw Permalink Normal View History

# 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
```
***
**文档结束** · 下一步:《接口文档》(对外交付物)