# 审计证据备份应该包含凭据吗？

事件归档应该帮助你回答：谁在什么时候做了什么，通过哪条获批准的路径完成，以及之后是否有人改动过记录。打开归档的人不应该因此获得可用的 API 令牌、SSH 私钥，或生成这两者的能力。

团队经常在这里出错，因为备份软件会让所有内容看起来都一样。数据库转储、保管库导出和审计日志都可能是静态加密的文件，但它们承担的安全职责不同。保管库备份用于恢复权限，证据备份用于保存责任记录。把两者放进同一个归档，归档就会继承保管库最危险的属性。

随着自主编程代理的出现，这种区别更加重要。代理在一次短暂运行中就能发起大量对外操作：修改代码仓库、调用部署接口、更新工单、管理云资源和执行远程命令。事件发生后，人们需要一份持久的操作记录，却不需要一捆能够让这些操作发生的凭据。

## 证据备份不能恢复权限

无凭据归档是一种证据包，恢复后不能以用户、服务或机器的身份进行认证。它的内容可能具有机密性，但其中任何单独的内容都不能直接引发外部操作。

因此，证据包可以保存这样的记录：

```text
2026-07-22T02:14:09Z
session=ses_8f0d...
process_authority=Developer ID Application: Example Engineering LLC
channel=http
method=POST
host=api.internal.example
path=/deployments
credential_ref=prod-deploy-token
authorization=approved
result=201 Created
entry_hash=2ebc6f...
previous_hash=78dd91...
```

但它不能保存 `credential_ref` 所代表的 bearer token，也不能保存 SSH 私钥、会话 Cookie、OAuth 刷新令牌、恢复代码、解密后的保管库数据库，或与归档放在一起的导出密码。只要出现其中任何一种内容，你就不再拥有纯粹的证据备份。

有人会认为，要完整重建环境，就必须保留一份保管库副本。只有在目标是灾难恢复权限时，这才是必要的。这是另一种操作，也对应不同的威胁模型。把它当作普通事件证据，会产生一个必须按生产访问权限保护的归档，而且保护期限往往比原凭据的有效期还长。

在备份清单中使用两种明确的分类：

- **权限恢复材料**可以恢复执行操作的能力，应放入严格控制的保管库恢复流程。
- **证据保留材料**可以解释并验证已经完成的操作，应放入专为保留和审查设计的归档流程。

不要用“已清理的保管库导出”之类的标签模糊这条界线。只要保管库导出包含加密的机密数据块、封装的数据密钥，或解开它们所需的手段，它仍然属于保管库材料。审查人员今天可能无法使用它，但你已经保留了另一个目标，今后在发生额外入侵后它可能变得可用。

实际测试很简单：把归档恢复到一台无法访问凭据系统的干净机器上。如果用户能把归档中的任何内容变成一次有效的认证请求，就需要修正设计。

## 加密与证据完整性回答的是不同问题

加密回答“谁能读取这个归档？”完整性证据回答“这条记录是否被修改、重新排序或截断？”两个问题都必须回答，任何一方都不能替代另一方。

受密码保护的 ZIP 文件可以让事件时间线保持私密，却几乎不能证明内容一直完整。能够解密、编辑并重新加密它的攻击者，可以留下一个外表整齐的归档，而你没有可靠方法判断它是原件还是改写后的版本。

哈希链采用另一种方式。每个事件都包含前一事件的摘要，以及自身规范化内容的摘要。修改过去的条目，后续哈希就会停止匹配。删除中间条目，后继条目就不再指向预期的前驱。这样，归档可以证明导出序列在内部保持一致，也可以明确显示一致性从哪里开始失效。

但哈希链并不是魔法。如果攻击者在记录发出之前就控制了写入方，哈希链无法证明缺失的事件曾经发生。如果攻击者控制日志的所有副本，并能替换整条链，单独一条链也无法判断哪条是真的。你仍然需要受保护的检查点、受控导出和独立存储。

RFC 5848《Signed Syslog Messages》很有用，因为它区分了人们经常混在一起的几种主张。它讨论了来源认证、消息完整性、防重放、排序和缺失消息检测，也明确指出，经过认证的日志记录并不能证明最初的主机本身是诚实的。这个限制是有益的。日志记录的是记录系统观察到并发出的内容，不是对现实的超自然视角。

对于事件归档，要写清楚你实际能够支持的完整性主张：

- 归档字节与导出时创建的清单相匹配。
- 日志序列在签名或外部保留的检查点之前是完整的。
- 捕获后修改条目会导致验证失败。
- 归档不能证明未记录的操作从未发生。

最后一句可以避免错误调查。干净的审计结果只支持关于日志的主张，并不能为绕过记录网关、使用其他凭据路径的管理员开脱。

## 将日志与保管库恢复放在不同的保护域中

分开文件只是起点。真正的要求是分开保护域。不同的访问组、恢复流程、保留周期和删除规则，可以避免便利的备份变成进入生产环境的横向通道。

一种合理的安排包含三个存储区：

1. 在线保管库存放凭据和使用凭据所需的材料。它的恢复流程很少使用，授权严格，并且会被记录。
2. 在线日志保存近期活动记录和完整性状态。运营人员需要它来调查和持续审查。
3. 证据归档保存导出的日志片段、清单、验证说明和保留的检查点。调查人员可以通过另一条审批路径访问它，而不会获得在线凭据权限。

不要为保管库恢复副本和证据副本使用同一个归档加密密码。不要因为“存储桶已经有加密”就把两份副本放进同一个云存储桶。也不要默认让同一个小组负责两者的恢复联系人。这些捷径会在单个管理员账户、备份角色或存储集成遭到入侵时摧毁隔离。

保留期限也应不同。凭据的运营用途结束后，应轮换、过期或撤销。证据可能需要保留更久，因为事件可能在较晚时候才被发现，客户可能要求解释，或者内部审查可能持续数月。当旧证据归档包含旧机密时，更长的保留期会悄悄延长该机密的有效使用时间。

离职时还会出现另一种问题。离职工程师失去了当前保管库的访问权限，但个人恢复硬盘上仍留着旧的加密备份。如果备份包含仍然有效的凭据，离职流程就留下了漏洞。如果硬盘上只有无凭据的日志归档，它仍可能包含敏感证据，却无法让生产身份重新活跃起来。

隔离也让销毁更加容易。你可以按保留计划销毁证据，不必担心同时擦掉唯一可用的恢复副本。你可以轮换或停用凭据，不必进行大规模归档清理。这些工作绝不应绑定在一起。

## 导出验证包，而不是漂亮的报告

PDF 时间线适合会议使用，却不适合作为主要证据。它会丢失记录结构，通常隐藏被哈希的确切字段表示，也让审查人员无法验证源序列是否完整。

请导出一个包含机器可验证内容和人类可读索引的软件包。具体的归档布局可以是：

```text
agent-evidence-2026-07-22/
  manifest.json
  entries.ndjson
  checkpoints.ndjson
  activity-summary.txt
  VERIFYING.md
  hashes.sha256
```

`entries.ndjson` 每行包含一个规范化事件对象。字段要保持稳定。如果必须删减请求正文，应在条目中说明，并在能够安全保留时保存原受保护字段的摘要。不要悄悄把值替换为 `[REDACTED]`，却让审查人员猜测它原本缺失、被隐藏，还是事后被改动。

`checkpoints.ndjson` 保存锚定日志片段的信息。根据设计，它可以包含签名摘要、外部存储的根值、见证回执，或已完成归档传输的记录。没有保留的检查点，哈希链只能证明内部链接彼此一致。

`manifest.json` 应把归档描述为一个对象，而不是依赖目录名称。包含导出标识符、时间范围、最早和最新的序列标识符、记录数量、架构版本、规范化版本、哈希算法、删减策略标识符和预期的最终链值。如果这些信息对调查有意义，也应加入导出器版本和主机身份。

活动摘要只是辅助内容。它可以说明一次运行发起了七次 HTTP 调用和两次 SSH 调用，获得了一次会话审批，并包含一条失败命令。人们可以快速阅读它，但详细条目仍然是权威记录。

清单可以采用这样小的结构：

```json
{
  "archive_id": "evd_2026_07_22_001",
  "window_start": "2026-07-22T00:00:00Z",
  "window_end": "2026-07-22T23:59:59Z",
  "entry_count": 184,
  "canonicalization": "journal-json-v1",
  "hash_algorithm": "SHA-256",
  "first_sequence": 9012,
  "last_sequence": 9195,
  "final_entry_hash": "2ebc6f...",
  "redaction_policy": "evidence-redaction-v3"
}
```

报告可以从这个软件包重新生成，反过来却很少成立。保留结构化证据，需要时再制作报告。

## 备份失败，往往是因为事件发生后才导出

常见的失败过程在真正需要记录时才暴露问题。凌晨 1:40，代理进行了一次异常部署。当天上午晚些时候，维护人员发现客户受到影响。团队开始检查主机、重启应用、轮换凭据，并复制附近能找到的日志。到了午餐时间，本地日志已经滚动覆盖，原始进程状态消失，复制的文件没有清单，也没有检查点。

没有人一定是恶意行事，但团队仍然无法建立一份可辩护的历史记录。他们拥有的是不完整的片段，而不是证据归档。

NIST SP 800-92 将日志管理描述为不止收集，还包括生成、传输、存储、访问和处置日志数据。这个范围更准确。如果计划只停留在“应用会写日志”，那你计划的只是生成，而不是保留。NIST 也提醒，毫无选择地记录日志会带来运营问题，甚至造成日志数据丢失。记录足够重建代理操作的信息，但不要把原始机密、完整响应正文和任意文件内容散落到每个事件中。

在事件发生前，把导出纳入日常运营。具体周期取决于操作量和可接受的损失窗口，但必须明确负责人并进行测试。高影响代理运行结束后、可能影响本地状态的系统维护前，以及普通活动的固定周期，都应触发导出。

测试最糟糕的情况。先在另一台机器上恢复归档，不要给测试人员保管库访问权限。要求他们只使用软件包回答这些问题：

- 哪个代理进程发起了操作？
- 哪个授权决定允许或拒绝了它？
- 它针对的目标和操作是什么？
- 日志序列是否能通过归档的检查点验证？
- 哪些条目被删减，依据的是哪条明确规则？

如果测试需要重新打开原应用、寻找某位缺席的同事、回忆密码，或从在线系统复制机密，那么这个归档对于事件使用来说并不完整。

## 删减必须保留操作的形状

团队经常在两个糟糕的极端之间选择：把每个请求和响应都倒进日志，或者删掉太多内容，让记录无法解释事件。第一种做法会把日志变成另一个机密存储，第二种则会把日志变成合规摆设。

保留识别和评估操作所需的事实。对于 HTTP 调用，通常包括会话身份、代码签名权限或等效的进程身份、目标主机、方法、路径、凭据引用、审批结果、时间戳、结果状态，以及适当表示的请求和响应。对于 SSH，应记录目标、账户身份或凭据引用、命令或经过谨慎设计的命令表示、审批结果、退出状态和相关输出分类。

“适当表示”需要判断。包含发布标识符和环境名称的 `POST /deployments` 请求，可能适合以明文保留。携带访问令牌、客户记录或私钥的请求正文则不适合。若日后需要比较，可以保存固定的删减标记和原字段摘要。摘要让调查人员能判断两个受保护值是否相同，却不会暴露它们。

要小心各种标识符。授权请求头显然是机密，URL 查询参数同样可能危险。命令行中可能包含密码、云访问令牌或客户数据路径。响应正文经常包含临时下载地址、个人数据或服务配置。日志工具并不了解你的业务语义，不能替你做出所有删减决定。

把规则写进归档。例如：

```text
redaction_policy=evidence-redaction-v3
request_body=retained only for allowlisted JSON fields
authorization_header=omitted
query_parameters=names retained, values digested
response_body=classified and omitted unless allowlisted
ssh_command=stored after secret argument filtering
```

这段说明能让审查人员理解信息为什么缺失，也能为工程师提供具体的测试依据，尤其是在 API 发生变化时。

不要仅仅因为授权结果、目标身份或失败细节令人不舒服，就把它们删掉。被拒绝的请求、失败的认证尝试和意外主机，往往正是解释事件的关键。

## 干净的链仍然需要独立保留

哈希链可以防止保留序列中的隐蔽修改，却不能阻止控制源系统的人删除整个序列并重新开始。严肃的归档计划应为哈希链提供一个外部参考点。

最简单的方法是定期导出检查点。在规定的间隔，将最终日志摘要、序列号和时间戳写入单独控制的归档。保留多份副本，并使用彼此独立的写入权限。攻击者若之后修改本地日志，就还必须修改每一个保留的检查点，否则会留下不一致。

你可以使用签名检查点、可信时间戳流程或只追加存储来进一步加强保护。正确选择取决于环境，但如果还无法运行恢复和验证测试，就不要直接上复杂基础设施。有人真正检查的简单、重复检查点，比没人演练过的宏大设计更可靠。

让验证流程能够离线运行。这正是 Sallyport 审计设计有用的地方：它的写入盲加密哈希链日志可以在密文上通过 `sp audit verify` 检查，不需要保管库密钥。无凭据验证器避免了这样的荒谬局面：检查代理是否滥用了机密的人，必须先取得该机密的访问权限。

证据流程应保留验证器本身，或记录获取与归档格式完全匹配版本的方法。在清单中记录验证器二进制文件的加密摘要或源代码版本。未来的审查人员不需要一台古董电脑，但需要足够的信息，避免用已经改变的规则悄悄验证旧数据。

预期的验证结果应当明确无歧义：

```text
$ sp audit verify evidence/journal.enc
verified: 184 entries
chain: intact
range: sequence 9012 through 9195
checkpoint: matched
```

验证失败时，保留失败输出，并停止把归档当作干净的序列。失败不一定证明存在恶意行为，也可能暴露传输损坏、导出器故障、格式不匹配或蓄意修改。关键在于，归档让分歧变得可见，而不是悄悄接受一段被改写的历史。

## 证据访问应足够广泛以支持调查，也足够狭窄以保护相关人员

证据比凭据更安全，但默认并不等于公开。审计记录可能泄露仓库名称、内部服务拓扑、员工操作、客户标识符和运营失误。先从归档中移除权限，再根据剩余内容的敏感程度控制证据访问。

让调查人员拥有软件包和验证器的只读权限，而不是权威归档位置的写入权限。为系统运营人员提供有文档记录的导出角色，并尽可能让每次导出都出现在同一条审计轨迹中。外部法律顾问、客户或评估人员不需要原始内部细节时，应提供删减后的派生软件包。

避免建立一个同时能够读取保管库恢复材料、修改保留设置和下载证据的“安全归档”小组。这个小组会因为紧急情况更方便而不断积累权限，但也会让一个被攻破的账户同时具备抹掉恢复能力和解释事件能力。

定义归档保管记录，不需要摆出法庭戏剧，只要记录基本事实：归档 ID、创建者、导出时间、源范围、存储位置类别、访问授权、传输事件、验证结果和销毁批准。如果通过文件共享系统把软件包交给调查人员，要记录传输前后的软件包哈希。

真正发生棘手事件时，这种安排的价值就会显现。工程师可以检查代理是否调用了生产端点，却不必拿到生产令牌。安全审查人员可以验证哈希链，却不必取得保管库的 Touch ID 访问权限。管理人员可以收到易读的事件说明，而不必接触原始请求正文。每个人都只获得完成工作所需的最少信息和权限。

## 在真正需要之前，让归档变得乏味

最好的证据备份，是团队在一切正常时就能创建和验证的备份。它拥有固定的软件包布局、明确的删减规则、独立的检查点，以及不依赖在线保管库的恢复测试。

用一份故意损坏的副本进行演练。修改条目中的一个字节，删除一条中间记录，并修改清单中的计数。验证器应当在每种情况下都失败，而且失败信息要让疲惫的响应人员也能理解。然后用同样的流程验证干净副本，确认证据包能回答谁批准了操作、发生了什么，以及序列是否保持完整。

把凭据恢复放在其他地方。当事件迫使你保留历史记录时，归档应该帮助你调查，而不是悄悄增加一个可以访问生产环境的位置。
