# 操作手册 — CVE-2026-111497 修复

这是脚本所实现的流程，写法上保证人工审计员能复现、审计或推翻每一步。每个阶段都指明其证据：
即那条输出可以支撑该决策的命令。

## 阶段 0 —— 周界清点

确定哪些主机在范围内，并确认可以通过密钥取得 root 访问。

```bash
for h in <host-alias-1> <host-alias-2>; do
  ssh "$h" 'grep PRETTY_NAME /etc/os-release; dpkg -l libbrotli1 2>/dev/null | tail -1'
done
```

验收：每台主机都返回操作系统名称，以及一行软件包信息或空。

## 阶段 1 —— 检测（只读）

`detect.sh` 在不改动系统的前提下收集：

1. 主机身份与操作系统。
2. `libbrotli1` 版本及其在受影响版本矩阵中的分类。
3. 是否已应用发行版回溯移植（变更日志提及该 CVE）。
4. `apt-get update` 之后来自 `-security` 的 apt 候选版本。
5. 来自 `/proc/*/maps` 的 `libbrotlidec` 活跃消费者。
6. 解码面：libcurl、Node、Python、PHP、`ngx_brotli`、`mod_brotli`。
7. 真实 `.so` 文件的 inode 快照，用于后续的陈旧映射比对。

判定：`SAFE`（0）、`VULNERABLE`（1）、`NOT_INSTALLED`（3）、`ERROR`（10）。

验收：`state.before` 存在，并包含 `installed`、`candidate` 与三个 inode。

## 阶段 2 —— 修复

`remediate.sh` 按严格顺序执行，并在第一个不变量失败处停止：

1. **备份** —— 旧 `.deb`、当前 `.so`、`dpkg -l` 快照存入
   `/root/cve-2026-111497-fix-<timestamp>/`。
2. **真实性闸门** —— 下载候选版本，并要求其打包变更日志中出现 `CVE-2026-111497`。
   仅仅是看起来更新的候选版本会被拒绝。
3. **试运行** —— `apt-get install --only-upgrade --dry-run`；预期集合恰好是 Brotli 相关
   软件包，别无其他。
4. **安装** —— `libbrotli1`，若此前安装了 `libbrotli-dev` 则一并处理。
5. **重启消费者** —— 所有进程映射了 `libbrotlidec` 的 systemd 单元，解析到
   `/system.slice/` 下最内层的单元，以便捕获模板实例；以瞬时 scope 启动的面板守护进程
   通过其自身控制工具重启。
6. **inode 检查** —— 任何服务器侧消费者都不得仍映射补丁前的 inode。

验收：退出码 0，并输出一行 `REMEDIATED:`，指明旧版本与新版本。

## 阶段 3 —— 验证

`verify.sh` 确认五项事实：

1. 软件包版本已改变。
2. 已安装的变更日志引用 `CVE-2026-111497`。
3. 没有服务器进程映射补丁前的 inode。
4. `systemctl --failed` 为空。
5. 功能性解码往返成功（本地 `br` 端点或 `brotli` CLI）。

验收：`VERIFY: PASS`，退出码 0。

## 人工交叉核对（独立于脚本）

```bash
dpkg -l | grep -E 'brotli'
apt-cache policy libbrotli1
zgrep -i CVE-2026-111497 /usr/share/doc/libbrotli1/changelog.Debian.gz
# no process may map the pre-patch decoder:
grep -l libbrotlidec /proc/[0-9]*/maps 2>/dev/null | wc -l
```

## 回滚

```bash
dpkg -i /root/cve-2026-111497-fix-<timestamp>/deb/libbrotli1_*.deb
# then restart every service listed in phase 2, step 5
```

按定义，回滚会恢复存有漏洞的版本。只有当已打补丁的软件包破坏了某个依赖时才使用它，并记录
该决策。

## 无回溯移植时的临时缓解

在反向代理或 WAF 上，于请求到达应用之前拒绝携带 `Content-Encoding: br` 的请求（包括
`gzip, br` 这类复合值），并以 `415 Unsupported Media Type` 作答。这是权宜手段，不能替代
更新：它只保护入站请求体，而每一次出站的 libcurl 抓取仍然暴露。

## 结案标准

- 重新运行 `detect.sh` 返回 0，或在修复之后 `verify.sh` 返回 `VERIFY: PASS`。
- 备份目录存在且非空。
- 所托管站点以变更前的状态作答。
- 被延迟的桌面消费者记录在报告中，并注明它们将在下次登录或重启时重新加载已打补丁的库。
