Postmortem: 关于 xzutil 后门事件的一些事后复盘

• 本文约 1525 字,阅读大致需要 4 分钟 | Security | #xz | #xzutils | #Postmortem | #供应链攻击 | #FreeBSD | #backdoor | #后门 | #liblzma

说明:这是关于北美时间2024年3月28日披露的xzutil后门事件的一些事后复盘。关于漏洞本身的一些更为详细的背景和细节以及其发现过程,在 Bryan CantrillAndres Freund 的这次 访谈 中有相当详尽的说明。由于漏洞并非我们发现,在此便不再赘述漏洞本身的细节。

值得庆幸的是,我们有足够的理由认为这次事件中FreeBSD并没有受到影响,但这里有相当大的运气的成分,整体而言,我们的流程并非无懈可击,因此有必要进行一些总结。

背景

自称叫「Jia Tan」的开发者花费了两年的时间逐渐取得了上游社区的信任,并最终成为了xzutils的维护者。

攻击者在2024年2月23日在源代码中的一处二进制文件中放置了后门,并随后发布了xz 5.6.0。攻击者发布的源代码包中,以巧妙地方式增加了激活后门的脚本。值得注意的是,这些脚本从未进入过xzutils的Git代码库,因此躲过了包括FreeBSD在内的开发者进行的日常代码审计(值得说明的是,由于这些脚本通常是自动生成的,体积庞大且随autoconf等工具的版本变化很大,因此其内容审计难度较大。比较稳妥的做法是从人类易读的autoconf文件中重新生成这些脚本)。

由于后门代码最初版本的bug,攻击者在接下来的两周时间进一步对后门进行了修补以增加其发现的难度。

主要的Linux发行版,包括Debian和RedHat,均在其开发版本中跟进了这些变动。由于systemd的插件设计,这些变动导致后门被插入到了这些Linux发行版中的sshd服务中。由于后门引入了一系列计算密集的代码,人们逐渐注意到了一些奇怪的性能问题。

最终,PostgreSQL开发者,就职于微软公司的Andres Freund在经过了一段时间的性能追踪之后,正式确认了xzutils后门的存在,并立即通知了主流发行版的安全团队。

我本人也在第一时间收到了通知。当时是太平洋时间的中午,我没有携带解密所需的密钥,但由于这一讨论相当热烈,加上邮件标题并不加密,因此我大概知道了发生了什么事。

FreeBSD中的xzutils

xzutils是一款压缩工具,由于其压缩比高、解压缩性能好,因此FreeBSD在2010年就在base system中加入了xzutils。FreeBSD在2024年3月9日将xz 5.6.0合并到了开发主线。

FreeBSD的base system中第三方软件的维护者有责任追踪这些第三方软件的开发,这包括在平时跟进这些第三方软件的代码变动,也包括在引入代码时做最后一次的代码审计。

我是FreeBSD中xzutils的维护者,因此我平时会关注上游的改动,并查看这些commit引入的变动。不过,在引入代码时,我往往会使用上游签名的tarball,和git版本比较一下,而不是从上游的git直接合并代码。

供应链攻击

前面提到,自称「Jia Tan」的人或团队花了两年时间逐步获取了信任,并成为了xzutils的维护者。这意味着此人签名了相关的tarball。通过在联编脚本中植入一个二进制文件后门,这次供应链攻击使得大部分Linux发行版在打包时会引入这个后门,该后门会将RSA_public_decrypt替换为攻击者的入口,允许链接了liblzma的使用该函数的程序运行任意代码。

由于FreeBSD引入第三方代码时会重写整个build部分,并且将用例部分直接删除,因此其实FreeBSD并未受到此问题的影响。不过,由于xzutils导致了一系列公关危机,出于谨慎起见我们于2024年4月4日将版本回退到了5.4.5版本。2024年6月,我们重新引入了经过更多人审计之后发布的xz 5.6.2版本。

暴露的问题和后续补救

尽管我们做了包括比较tarball内容和git内容、逐项审计代码这些操作,但这次供应链攻击还是让我出了一身冷汗,其原因在于我之前会以自己用户的身份而不是在虚拟机中的非特权用户(或者说一个沙箱环境)运行联编所需的脚本。相对来说,供应链攻击其实首先是针对我们这些维护者的攻击,尽管攻击者需要考虑我们这些人所用的各种千奇百怪的环境,但攻克了这些人之后进行更进一步的供应链攻击将变得更加顺利。

为此,我 更新 了FreeBSD的开发流程,并将这部分(在隔离环境中运行任何下载的代码)列入了新的最佳实践。

本次供应链攻击尽管对FreeBSD并未造成任何伤害,但留下的教训是相当深刻的。