TT Lab
开始
学习 学习路径 课程

闭网现场 — 国防领域

做一张把一条要求接到一个文件的对照表

在 TT Lab 中继续学习

目标

建立一份把每条需求所依据的文件绑定起来的证据索引,用哈希封存,用验证器统计断开的位置,并用经过导出审查的副本来封闭审计应对包。

为什么重要

在审计中被扣分的项目,大多不是没做的事,而是无法展示的事。如果一条要求与一个文件之间没有铺好路,当场就答不上来,而答不上来的项目,会被记为与没做一样。这条路在审计前一天是铺不出来的——因为依据文件会随时间被覆盖或消失。所以索引中放入的不只是路径,还有当时那个文件的哈希,而导出时只要遮盖了值,哈希也会随之改变。本实验中困难的部分不是规则,而是这种一致性。

步骤

  1. 用 python3 在 /root/audit/data 中创建需求、14 个依据文件、策略和上次的索引。直接使用生成脚本。
  2. 读取依据文件的头部,把每条需求的依据清单写入 /root/audit/index.json。
  3. 给每个依据附上 SHA-256,封存为 /root/audit/index-sealed.json。
  4. 验证上次检查时提交的 /root/audit/data/snapshot.json,把结果写入 /root/audit/verify.json。
  5. 把依据分为设计和运行两类,将每条需求的判定写入 /root/audit/strength.csv。
  6. 重新运行同样的收集,生成 /root/audit/index-rerun.json,并把确定性写入 /root/audit/determinism.json。
  7. 按导出审查规则在 /root/audit/submit/evidence/ 中生成遮盖副本,并留下 /root/audit/redaction.csv。
  8. 用遮盖副本的哈希封存 /root/audit/submit/index.json,并通过 /root/audit/submit/verify.json 和 /root/audit/submit/INDEX.md 封闭这个包。

参考

创建需求和依据文件

用 python3 在 /root/audit/data 中创建 requirements.json、policy.json、snapshot.json、asof.txt,以及 evidence/ 之下的 14 个依据文件。直接使用不含随机数的生成脚本。

隔离网络里没有可以下载的样本,所以先亲自创建数据。不使用随机数,才能保证无论谁运行多少次,得到的数据都相同,彼此的判定才能比对。评分器会把数据转换成标准形式并核对指纹,所以如果手工修改数据,后面的步骤会全部被卡住。

建立把每条需求与依据连起来的索引

在 /root/audit/index.json 中放入 generated_at、asof、entries 三个键,entries 为每个需求 id 放入依据条目清单(evidence_id、path、kind、collected_at)。没有依据的需求也要以空列表放入。

依据文件已经在头部写明了自己覆盖哪些需求。扫描目录,读取头部再反过来整理,就成了索引。不要忘了格式有两种。条目按依据 id 排序,path 以 /root/audit 为基准写相对路径。

把依据的哈希固定到索引中

在 /root/audit/index-sealed.json 中原样搬入索引,并为每个依据条目加上 sha256。generated_at 保持第 2 步索引中的值不变。

封存不是重新收集,而是给现有索引加上指纹。所以收集时间不能改变。哈希是对文件全部字节的 SHA-256,用小写十六进制书写。

用验证器过滤上次检查时提交的索引

在 /root/audit/verify.json 中写入对 /root/audit/data/snapshot.json 的验证结果。在 missing_file、hash_mismatch、uncovered 三个键下,分别放入 count 和清单(evidence_ids 或 req_ids)。

三者是不同的故障:指向的文件不存在,文件存在但哈希不一致,以及根本没有任何依据条目的需求。第三种要把索引根本没有写入该需求的情况也统计在内,所以要从需求清单这一边去遍历。只有一个条目、但这个条目是断开的需求,不属于没有依据。

区分依据的强度,找出不足的位置

在 /root/audit/strength.csv 中,第一行写 req_id,needs,has_design,has_operational,verdict,12 条需求各写一行。needs 是 설계 或 설계+운영,是否拥有用 예/아니오 表示,判定是 충족、설계근거없음、운영근거없음、근거없음 之一。

配置和策略文档说明的是“就是这样设置的”,而日志和检查结果说明的是“确实是这样运行的”。哪一类属于哪一边,写在策略文件中。如果根本没有依据,则先判定为没有依据,然后再看所需要的一边是否缺失,先从设计开始看。

看重新收集是否得出相同的索引

用同样的方法重新生成 /root/audit/index-rerun.json,并在 /root/audit/determinism.json 中写入 generated_at_differs、normalized_sha256_first、normalized_sha256_second、same_without_time 四个键。

从两份索引中只去掉收集时间,序列化为标准形式后比较哈希。两个哈希相同,这次收集才是确定性的。反过来,收集时间必须不同才算重新运行过,所以时间要写到微秒。

通过导出审查生成遮盖副本

按规则编号顺序应用策略中的审查规则,在 /root/audit/submit/evidence/ 之下以同样的相对路径生成 14 个依据的副本,并只把命中规则的文件,以 evidence_id,rules,hits,sha256_after 的格式写入 /root/audit/redaction.csv。

没有命中的文件也要生成副本,这个包才完整。rules 用加号连接命中的规则编号,hits 是被改动位置的总数。sha256_after 是遮盖副本的哈希——不要动原件。

封闭这个包,并用验证器自行确认

以遮盖副本为基准封存 /root/audit/submit/index.json(路径以 /root/audit/submit 为基准),把运行同一个验证器的结果留在 /root/audit/submit/verify.json 中,并把按需求整理了依据数量和判定的表格目录留在 /root/audit/submit/INDEX.md 中。

包内的索引必须使用遮盖副本的哈希,接收方的验证才能通过。不存在的文件和哈希不一致会变成 0,但根本没有依据的需求依然存在——这个空白不要隐瞒,要用判定写在目录中。目录的表有三栏:需求 id、依据数量、第 5 步的判定。