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

银行现场的语言

证明是谁提高了额度

在 TT Lab 中继续学习

目标

用数字揭示被原地 UPDATE 抹掉的证据,通过规范序列化和哈希链建立只追加的审计记录,然后找出合作方导出件中的篡改,并加上 HMAC 和关联 ID,提交证据包。

为什么重要

审计中争辩的不是值,而是经过。只保存当前额度的系统,无法回答“谁在什么时候为什么调高了”,没有这个回答,正确的值也会变成无法解释的值。 哈希链不是让记录无法修改的装置,而是让记录一改就暴露的装置。所以首先需要规范序列化,使同一个事件始终得到同样的字节,而要防止把整条链重新计算的伪造,则需要密钥。 评分器不相信你写出来的哈希。它会从原始数据重新从头计算并对照,还会用每次运行都不同的随机向量和新生成的链来测试你的工具。

步骤

  1. 把材料脚本保存为 /root/audit/gen_audit.py 并运行,生成 /root/audit/core.db 和 /root/audit/vendor_chain.jsonl。
  2. 把月初快照与当前额度做对账,把消失的证据以 changed、ticketed、untraceable、mismatched 和 raised_total 写入 /root/audit/lost.txt。
  3. 创建 /root/audit/canon.py,对标准输入中的每一行 JSON 做规范序列化,并逐行输出所得字节的 sha256。
  4. 用 /root/audit/build_chain.py,把 app_log 的 400 行以哈希链的形式移入 /root/audit/audit.db 的 audit_log 表。
  5. 用 /root/audit/verify_chain.py 验证合作方的导出件,并把找到的位置写入 /root/audit/tamper.txt。
  6. 用 /root/audit/hmac.key 和 /root/audit/mac_chain.py 在链上加一层 MAC,生成 /root/audit/audit_mac.jsonl。
  7. 用关联 ID 把事件按请求重新归并,并写入 /root/audit/corr.txt。
  8. 用 /root/audit/evidence/manifest.json 和 /root/audit/audit_report.md 提交证据包。

参考

生成额度快照和合作方导出件

把材料脚本保存为 /root/audit/gen_audit.py 并运行,生成 /root/audit/core.db 和 /root/audit/vendor_chain.jsonl。

先创建 /root/audit,并在其中用 python3 运行。表有 limit_opening、customer_limit、change_ticket、app_log 四个,合作方的链是 399 行。

数一数原地 UPDATE 抹掉了什么

把月初快照与当前额度做对账,把 changed、ticketed、untraceable、mismatched 和 raised_total 写入 /root/audit/lost.txt。

用 customer_id 把 limit_opening 和 customer_limit 连起来,数一数额度不同的客户。其中没有 change_ticket 的件,就是没有人能解释的变更;申请单的 new_limit 与现在的值不同的件,就是批准与落实出现分歧的地方。

让同一个事件始终得到同样的字节

创建 /root/audit/canon.py,让它对标准输入中的每一行 JSON 做规范序列化,并逐行输出所得字节的 sha256。

键排序、无空白的分隔符、不转义非 ASCII 的 UTF-8,就是全部三项。请看 Python json.dumps 的 sort_keys、separators 和 ensure_ascii。嵌套对象的键也必须一起排序。

把 400 行日志用哈希链串起来

用 /root/audit/build_chain.py 把 app_log 移入 /root/audit/audit.db 的 audit_log 表,并填好 prev_hash 和 entry_hash。

列是 seq、ts、corr_id、actor、action、target、amount、prev_hash 和 entry_hash。entry_hash 是把前面七个值和 prev_hash 合在一起的对象做规范序列化后所得字节的 sha256,第一个条目的 prev_hash 是 64 个 0。评分器会从 core.db 重新计算来对照。

找出合作方导出件中被动过手脚的位置

用 /root/audit/verify_chain.py 验证 vendor_chain.jsonl,并把 content_bad_seq、link_bad_seq、missing_seq 和 total_lines 写入 /root/audit/tamper.txt。

合作方链的哈希,是把 prev_hash、seq、ts、actor、action、target、amount 用竖线连成的字符串的 sha256。内容被改的位置,这一行的 entry_hash 会对不上;条目缺失的位置,下一行的 prev_hash 会对不上。两种症状是不同的。

在链上加一把密钥

用 /root/audit/hmac.key(64 个十六进制字符,权限 600)和 /root/audit/mac_chain.py 生成 /root/audit/audit_mac.jsonl。

密钥用 openssl rand -hex 32 生成,并执行 chmod 600。MAC 是对 entry_hash、prev_mac、seq 这三个键做规范序列化后所得字节的 HMAC-SHA256,第一行的 prev_mac 是 64 个 0。密钥字符串不能出现在记录文件里。

把一个事件重新归并成一个请求

用关联 ID 把事件重新归并,并把 no_corr、corr_groups、corr_of_seq140、target_of_seq140、events_in_group 和 actors_in_group 写入 /root/audit/corr.txt。

corr_id 为空字符串的行,日后无法恢复它曾是哪个请求的一部分。seq 140 正是在合作方导出件中内容不一致的那个位置。用那个事件的 corr_id 重新扫描 app_log,看看它经过了几个系统。

提交证据包和报告

在 /root/audit/evidence/manifest.json 中放入 files、chain、verified 和 vendor_findings,并在 /root/audit/audit_report.md 中写一份分五节的报告。

manifest 的 files 是带有 path、sha256 和 bytes 的对象数组,audit.db、audit_mac.jsonl 和 vendor_chain.jsonl 必须全部放进去。chain 中写 rows、genesis 和 head。评分器会从实物重新计算所写的哈希来对照。报告的各节标题是:确认了什么、证据消失的位置、链与验证、合作方导出件、建议。