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

闭网现场 — 国防领域

把沾着人的日志变成可以送出网外的样子

在 TT Lab 中继续学习

目标

从沾染着人和组织信息的运营日志中筛出标识符,区分应用挂在密钥上的确定性假名化与掩码,用泛化降低剩余的重新识别风险,然后由机器对导出包进行自检再导出。

为什么重要

在隔离网络中遇到解决不了的故障时,总有必须把日志发送到外部的时刻。这时如果用星号盖住工号,审查虽然通过,分析却死了。因为故障分析所使用的事实,大多不是值本身,而是值相同这一关系。所以需要的是一个始终把相同的值变成相同的假名、却无法还原的函数,而这个位置由带密钥的哈希来担任。本实验中困难的部分不是假名函数,而是清点什么是标识符。带标签的字段很容易,而在消息正文中像句子一样嵌入的值,以及藏在编码背后的值,会使导出物泄露。

步骤

  1. 用 python3 在 /root/deid/data 中创建六个数据文件。直接使用生成脚本。
  2. 把每个字段的分类、唯一值数量和处理方式写入 /root/deid/classify.csv。
  3. 把正则表达式在字段中找到的值和漏掉的值写入 /root/deid/scan.json。
  4. 编写挂在密钥上的假名函数,留下 /root/deid/vault/map.csv 和 /root/deid/vault/proof.json。
  5. 区分假名化与掩码分别应用,生成 /root/deid/out/access.deid.log 和 /root/deid/out/app.deid.log。
  6. 统计由准标识符组合而变得唯一的行,写入 /root/deid/risk.json,并把泛化后的分析表留在 /root/deid/out/events.csv。
  7. 把用原始标识符清单核对导出物的结果,写入 /root/deid/selfcheck.json。
  8. 在 /root/deid/release 中创建只包含假名数据、方法说明和完整性校验的导出包。

参考

创建去标识化所用的数据

用 python3 在 /root/deid/data 中创建 access.log、app.log、roster.csv、policy.json、key.hex、asof.txt 六个文件。直接使用不含随机数的生成脚本。

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

区分各个字段是什么

在 /root/deid/classify.csv 中,第一行写 field,category,distinct_values,action,然后为 policy.json 的每个 fields 各写一行。distinct_values 是该字段在数据中的唯一值数量,action 是 action_by_category 为该分类规定的处理方式。

分类是由组织规定的,所以 policy.json 中已经写好了。你要做的是附上与该分类相符的处理方式,并实际统计数据,填入唯一值数量。唯一值数量少的列,单独不能指向一个人,但与其他列合在一起就可以——这就是准标识符。

同时统计正则表达式找到的与漏掉的

在 /root/deid/scan.json 中写入 field_values(按类型统计的字段唯一值数量)、message_only(只存在于 msg 中、而不在任何字段中的值)、encoded(把 payload 用 base64 解码后得到的值)、note_only(只存在于 note 中的值)四项。后三项是排序后的列表。

带标签的位置,用 종류=값 来找。接下来是这一步的关键——单独扫描 msg 和 note 中双引号之间的内容,而 payload 要先解码再扫描。任何正则表达式都无法在原文状态下找到编码后的值。

创建挂在密钥上的确定性假名

在 /root/deid/vault/map.csv 中,第一行写 kind,value,pseudonym,为数据中找到的每个标识符各写一行;在 /root/deid/vault/proof.json 中写入 values、pseudonyms、collisions、stable、key_sensitive、alt_key_overlap 六项。

假名用 HMAC-SHA256 生成。把类型和值用竖线连接后放进去,即使工号和地址碰巧是同一个字符串,假名也会不同。测试有三项——同一个值计算两次是否相同,不同的值是否不会变成同一个假名,用 policy.json 中的另一把密钥计算时,假名集合是否完全没有重叠。这个保险库留在网络内。

区分应用假名化与掩码

创建 /root/deid/out/access.deid.log 和 /root/deid/out/app.deid.log。自由叙述字段整个替换成 policy.json 的 mask_token,编码字段替换成解码值的假名,其余模式全部替换成假名。行数和行的顺序必须与原始文件一致。

顺序会改变结果。如果不先做掩码,自由叙述中的值会被换成假名后留下来,该删除的东西就在没有被删除的情况下发了出去。编码字段要先解码,判定是哪种类型,再附上该类型的假名——同一个人必须与以原文出现的位置得到同样的假名。

统计把直接标识符全部替换后仍然残留的风险

在 /root/deid/risk.json 中写入 rows、k、groups_before、unique_before、groups_after、unique_after 六个数,并按访问日志的行顺序,在 /root/deid/out/events.csv 中留下以 pseudo_emp,dept,grade,hour 为第一行的泛化分析表。

准标识符组合写在 policy.json 的 quasi 中。部门和职级来自名册,时间来自访问日志。先按以分钟为单位的时间归组,统计相同组合的行少于 k 个的行,然后把时间舍弃为以小时为单位,再统计一次。减少的部分,就是靠泛化换来的安全,而失去的精度就是它的代价。

由机器核对导出物中是否还残留原始值

在 /root/deid/selfcheck.json 中写入 files_checked、forbidden_values、hits、pseudonyms_found 四个数。forbidden_values 是数据中全部标识符的数量,hits 是其中在导出物中被发现的笔数,必须为 0。

禁止清单比假名保险库更宽。被掩码去掉的值没有假名,但也不能出现在导出物中。连自由叙述中的值也要放进清单。核对的对象是 out 目录中的文件,而禁止清单和 selfcheck 结果要放在它之外——清单本身就是最危险的文件。

保险库留在内部,只导出包

在 /root/deid/release 中创建 access.deid.log、app.deid.log、events.csv 三个文件,以及 /root/deid/release/method.md、/root/deid/release/SHA256SUMS。方法说明有五个小节:## 무엇을 바꿨나、## 가명은 어떻게 만들었나、## 무엇을 지웠나、## 남은 위험、## 무결성,映射表和密钥不放入导出包。

接收方只会看到假名。所以,如果不同时附上说明哪些内容按什么规则被替换,这份数据就成了无法阅读的数据。完整性哈希要在文件最后一次修改之后再计算。并且要再用清单看一遍导出包里装了什么——把保险库一起放进去的事故最常见。