Apt存档透明度:debdistdiff和Apt-carary

我一直觉得apt软件包存储库的操作是个谜。人们访问重要的apt包存储库的方式、自动非人工更新机制的实现方式以及发布的更改似乎缺乏透明度。我在考虑像这样的大型发行版Ubuntu公司Debian公司,但也包括免费GNU/Linux发行版喜欢特里斯克尔PureOS(纯操作系统)从更著名的分布中派生出来的。

据我所知,任何拥有基于apt的GNU/Linux发行版信任的OpenPGP私钥的人都可以签署修改后的Release/InRelease文件,如果我的机器以某种方式下载了该版本的发行文件,我的机器就可以下载并安装发行版不打算我安装的包。此外,似乎任何有权访问主HTTP服务器或其任何镜像的人,或者他们和我的机器之间网络上的任何位置的人(当使用明文HTTP时),都可以在我的机器上暂停安全更新(基于每个IP),或者使用它发送我的机器(同样,基于每个IP以避免检测)修改后的Release/InRelease文件,前提是他们能够获得存档的专用签名密钥。这些都是需要概览的强大力量。

我总是推迟学习保护适当基础设施的过程,在心里将其归类为“如此多的人依赖于此基础设施,以至于有足够多的人可能会花时间审查和改进这些过程”。同时,我一直遵循更自由软件友好的Debian衍生发行版,如gNewSense,并在一些机器上运行它。我从未将它们投入正式的生产使用,因为它们的apt包存储库的信任问题一直是我的一个大问号。我推迟这一点的理由中的“足够的人”部分并不令人信服。即使是“有人在更新apt存储库吗”这个简单的问题,在一个正在运行的gNewSense系统上也不容易理解。从Debian获取安全更新的gNewSense cron作业一定在某个时候停止了工作,我没有任何好的机制来注意到这一点。很可能是在没有任何公告的情况下发生的。我最近在生产机器上转向了Trisquel,这些问题再次困扰着我。

情况令人不满意,我研究了可以做些什么来改进它。我可以试着了解每个项目涉及的关键人员是谁,甚至可以了解使用了什么硬件组件,或者涉及什么软件来更新和签署apt存储库。服务器是否运行非免费软件?专有BIOS或NIC固件?GnuPG私钥在磁盘上吗?智能卡?TPM?YubiKey?HSM?服务器位于何处,谁有权访问它?我试着做了一点,发现了Trisquel在其默认apt信任存储中具有DSA1024密钥(尽管为了公平起见,apt默认不信任此类签名)。然而,我不确定这是否会扩展到保护我的机器免受此基础设施上的攻击。即使是有着最好意图的人,以及最先进的硬件和软件,也会有问题。

为了增加我对Trisquel的信任,我开始了解它是如何工作的。为了更容易找出Trisquel档案中需要进一步审计的有趣部分,我创建了债务差异以产生人类可读的文本输出,将一个apt档案与另一个apt档案进行比较。有一个GitLab CI/CD cron作业每天都在运行输出比较Trisquel与UbuntuPureOS与Debian。使用这些输出文件使我了解了更多有关流程如何工作的信息,我甚至会出错可能是错误的东西其中,Trisquel-aramo是从Ubuntu jammy中导入的,但它包含几个在最终Ubuntu jammy版本中被删除的包(例如,gcc-8、python3.9)。

在以这种方式手动审核Trisquel存档之后,我意识到,无论我从比较Trisque和Ubuntu中可以看出什么,它都只是基于存档的当前快照。明天可能会完全不同。感觉有必要的是持续审计特里斯克档案的差异。我很高兴自己发展了债务差异为了一个目的(比较两个不同的档案,如Trisquel和Ubuntu),发现该工具可以用于另一个目的。这时,我意识到我需要一个包含所有不同apt归档元数据的日志,以便能够生成归档时间差异的审计日志。我使用发布/发布中包装众所周知的发行版Trisquel、Ubuntu、Debian和PureOS的每个体系结构/组件的文件。最后,我编写了脚本来自动完成这项工作,这些脚本现在发布在债务分配项目。

此时,关于发行版文件的per-IP替换的一个早期问题一直萦绕在我的脑海中。然而,有了我现在可用的工具,找到解决这个问题的方法很简单!只需计算刚刚下载的InRelease文件的SHA256校验和,看看我的git存储库是否有相同的文件。此时,我开始阅读Apt源代码现在,我对我的系统安全性的怀疑比以往任何时候都多。哦,孩子,名字怎么了恰当的从未有过这样的感觉…Apt?!哦,好吧,我们必须给学生留一些练习。最后,我意识到我想尽可能少地接触apt代码基础,并注意到SigVerify::复制并验证功能打电话执行GPGV它叫apt-key验证称为GnuPG的通用汽车公司.通过设置Apt::Key::gpgv命令我可以得到apt密钥验证调用其他工具通用汽车公司看到我要去哪里了吗?我认为现在完成这项工作很简单,但由于某种原因,我在本地计算的哈希校验和与服务器上的数据不匹配。我放弃了,转而开始做其他事情。

今天我回到了这个想法,并开始调试我从apt中获得的本地文件的外观,以及它们与我在git存储库中直接从apt存档中获得的文件的差异。最终我追踪到拆分清除签名文件这需要一个InRelease(发布中)文件并将其拆分为两个文件,可能会模仿(旧?)分发这两个文件的方式发布发布.gpg因此,clearsigned InRelease文件被分割为一个cleartext文件(类似于发布文件)和一个OpenPGP签名文件(类似于发布.gpg文件)。但是为什么InRelease文件的明文变量散列到与Release的散列相同的值?遗憾的是,他们在最后一条新线上有所不同。

解决了这个技术性问题后,很容易就把各个部分打包起来,我想出了一个项目适配子的提供脚本apt-canary-gpgv根据我称之为“apt canary witness”的文件验证本地apt发布文件,该文件存储在某个URL中。

我现在正在我的Trisquel aramo笔记本电脑Trisquel nabia服务器和Talos II ppc64el Debian机器。这意味着我已经解决了对per-IP替换的担忧(或者至少使其不太可能发生,必须向GitLab和我的系统发送相同的恶意发布文件),并允许我有一个审计日志,记录我实际用于安装和下载包的所有发布文件。

你怎么认为?显然有很多工作和有待改进之处。这是一个理念的验证实现,但我想发布这篇文章,让其他人思考问题和解决问题的各种方法,而不是将其完善并延迟反馈。

顺便说一下,我要去FOSDEM’23年这个周末,帮助管理安全开发室。如果你想聊这个或其他事情,请找我。快乐黑客!