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

面对陌生系统

按易失性顺序收集,然后封存

在 TT Lab 中继续学习

目标

把按 RFC 3227 易失性顺序收集证据的计划固化成文件,并编写严格遵循该顺序的收集器。把收集时间、收集者、命令和 sha256 写进清单,封存清单后,再编写检查封存是否被破坏的验证工具,并在含有客户个人信息的项目上划出界线。

为什么重要

进入现场后,手会先伸向日志。在下载日志的这 10 分钟里,进程列表会变,连接会关闭,临时文件会被删除。日志明天还在原地,而那些东西只存在于此刻,一旦消失,就再也回答不了“当时那个进程在运行吗”这个问题。 RFC 3227 的第 2.1 节写道要从易失性高的向易失性低的推进,并给出了七组示例顺序。这个顺序给出的不只是优先级,还有判断的依据:被问到为什么先取那个时,可以用等级而不是凭感觉来回答。 光有收集还不够。几周之后,会有人问“这个文件确实是那天从那台服务器上取出来的吗”。要为每个项目记录何时、谁、用什么收集的,以及内容指纹,并且把清单本身也封存起来。因为只写文件哈希的话,改掉清单就万事大吉了。 反过来,想全部收集的话,就会把客户个人信息整个带走。要划出界线,但不要悄悄去掉,而要把“已去掉”这一事实和原因留在记录里。 评分器不会相信你写下的文字。它用自己的计划和自己的范围文件真实运行你的收集器,核对顺序、时间和哈希,还会悄悄修改生成的证据包中的一个文件,看你的验证工具能否指出它的名字。

步骤

  1. 创建并运行 /root/evidence/gen_scene.py,生成 /root/evidence/host/。其中包含 2 个配置文件、2 个日志、1 份中央日志副本、6 个临时文件,以及生产数据库(customer 120 行、charge 360 行)。
  2. 在 /root/evidence/plan.json 中,按易失性从高到低依次写入八个项目。每个项目写明 id、volatility_class、command 和 why。
  3. 创建 /root/evidence/collect.py,让它严格按计划的顺序收集并留下清单。
  4. 让它为每个项目写入 sha256 和字节数,并在清单中写入收集者。为此增加 --collector。
  5. 封存清单本身,留下 MANIFEST.sha256。
  6. 创建 /root/evidence/verify.py,检查封存是否被破坏,并打印出被破坏文件的名称。
  7. 在 /root/evidence/scope.json 中写明决定不收集的项目和原因,并为此增加 --scope,使被排除的项目仍然留在记录中。
  8. 在 /root/evidence/bundle/ 中生成真正的证据包并验证,然后在 /root/evidence/evidence_report.md 中分四节书写。

参考

id 是什么 从哪里读取
proc_table 当前正在运行的进程列表 此 Pod 的进程表
net_state 路由表和已打开的连接 /proc/net/route、/proc/net/tcp
kernel_stats 内核统计和内存 /proc/stat、/proc/meminfo
tmp_files 临时文件系统中留下的内容 host/tmp
app_logs 应用日志 host/var/log
app_db 生产数据库 host/var/lib/app.db
remote_logs 从中央日志服务器取得的副本 host/remote
host_config 配置和物理配置 host/etc

掌握现场

创建并运行 /root/evidence/gen_scene.py,生成 /root/evidence/host/。其中包含 etc 2 个文件、var/log 2 个文件、remote 1 个文件、tmp 6 个文件,以及 var/lib/app.db(customer 120 行、charge 360 行)。

在实验 Pod 里不可能触碰真正的客户服务器,所以只准备磁盘这一侧。易失性高的内容不需要模拟,因为这个 Pod 的 /proc 就是真的。创建完成后,用 tree 浏览一遍。

按易失性顺序制定计划

在 /root/evidence/plan.json 中,按易失性从高到低依次写入八个项目。每个项目写入 id、RFC 3227 的 volatility_class(1..7)、实际要运行的 command,以及说明为什么排在这个位置的 why。

直接把 RFC 3227 第 2.1 节的七组作为等级使用。进程表、内核统计和路由表属于同一组,接下来是临时文件系统,再接下来是磁盘,再接下来是远程日志数据,最后是物理配置。command 必须真正运行并输出内容。

按计划收集

创建 /root/evidence/collect.py,让它严格按计划的顺序收集,并留下 <묶음>/manifest.json(占位符为证据包目录)。每个项目写入 id、order、volatility_class、command、collected_at、file、exit_code 和 status。

不要把计划按等级重新排序,一旦排序,判断就藏进了代码里。命令用 bash 运行,标准输出原样保存到 <id>.txt。时间必须逐项分别记录,顺序才能得到证明。

记录何时、谁、用什么

增加 --collector <이름>(占位符为名称),并让它为每个已收集的项目写入 sha256 和 bytes,在清单中写入 collector。

几周之后,会有人问“这个文件确实是那天从那台服务器上取出来的吗”。那时能回答的,就是收集时间、收集者、实际执行的命令,以及内容指纹。sha256 要读取整个文件来计算。

清单也要封存

让收集器在清单写完后计算该文件的 sha256,以 <해시> manifest.json 的形式写成一行,保存到 <묶음>/MANIFEST.sha256(占位符依次为哈希值与证据包目录)。

只把文件哈希写进清单的话,改掉清单就万事大吉了。封存无法防止伪造,但能发现在不知不觉中发生的变化:用编辑器打开后保存了,或者复制过程中被截断了,这种情况实际上常见得多。

指出被破坏的文件名称

创建 /root/evidence/verify.py。用 --bundle <묶음>(占位符为证据包目录)把封存和文件哈希进行比较,完好时以 0 结束,被破坏时以非 0 结束,并在标准输出中打印含有被破坏文件名称的行。

只打印“封存已被破坏”的验证工具,会让人一直守在那里。必须指出是什么被破坏了,才会有下一步行动。清单被改动和收集到的文件被改动这两种情况都要能发现,而被排除的项目没有文件才是正常的。

把决定不收集的内容留在记录里

在 /root/evidence/scope.json 中写入 policy 和 excluded,排除 app_db,并给 collect.py 增加 --scope <파일>(占位符为文件名)。被排除的项目不生成文件,而是在清单中以 status excluded 和 reason 留下记录。

支付服务器的生产数据库里有姓名、邮箱和电话号码。一旦把它转储下来带走,我们就不再是调查者,而成了新的风险。重要的是不要悄悄去掉:只有“已去掉”这件事留在记录里,之后才知道该申请什么。

生成证据包并出具报告

在 /root/evidence/bundle/ 中生成真正的证据包(同时给出计划和范围),用 verify.py 验证后,在 /root/evidence/evidence_report.md 中分 ## 무엇을 어떤 차례로 모았나 ## 무엇을 모으지 않았나 ## 봉인과 검증 ## 남은 위험 四节书写(韩文标题,依次意为“按什么顺序收集了什么”“没有收集什么”“封存与验证”“剩余风险”)。

报告不要手写,而是从清单生成。项目名称和等级、被排除的项目及原因、封存值和验证命令都要包含在内,下一个人才能原样重新验证。