我们需要从 XZ 后门中吸取的教训
2024年4月12日 | Dirk Mueller | CC-BY-SA-3.0
在过去几周里,关于 XZ 后门 已经写了很多,所以现在是时候展望未来了。在这样做之前,我们分享更多关于 openSUSE 方面发生的事情的细节。关于它如何影响 openSUSE 用户,请 参考之前的帖子。
幕后情况
在公开披露 XZ 后门的前几天,SUSE 产品安全团队收到了一些提示,表明 XZ 5.6.x 版本存在一些异常情况。我是 SUSE 员工和 openSUSE 软件包维护者,负责更新并将此版本包含到 openSUSE Tumbleweed 中,所以我很早就参与其中了。当时,我们无法获得最初公开披露中分享的任何上下文和信息。然而,这个提示是我们所需要的一切信息。它改变了我们看待一个成熟的、核心的开源项目的态度。如果没有它,构建系统“configure”阶段的那个奇怪的小差异很容易被忽略。
在披露前一天,星期四晚上,SUSE 产品安全团队通过共享发行版安全披露列表收到了来自 Andres Freund 的更长、更详细的报告。发行版列表是一个加密邮件列表,发行版商可以在其中协作和协调安全问题的披露。这份报告带来了新的信息,即 XZ 后门专门针对 OpenSSH,而 OpenSSH 是几乎每个 Linux 系统中面向网络的组件之一。这进一步提高了我们的威胁等级,使其成为一个远程访问后门,并促使我们扩大计划中的沟通力度。
SUSE 安全团队和我开始分析。SUSE 产品安全是各种私有安全论坛的成员,例如发行版列表和 CERT VINCE 等,这使我们能够在软件供应商之间协调修复,并在披露日期准备好更新。有了初步信息表明存在一些可疑之处,相对容易地发现更多可疑之处,而且没有特定的顺序。
-
openSUSE 和 SUSE 使用受信任签名密钥环来跟踪发布工件的签名。我们注意到,工件签名所用的密钥在一段时间前已经更改,因此我们必须更新 XZ 项目的受信任密钥环。我们验证了维护者变更,并且新维护者具有直接提交访问权限以及签名发布和发布的能力。这个新的签名密钥的信任网络连接不够完善,本应引起警报,但它是由之前的维护者签名的,这对于我们来说已经足够了。
-
查看提交历史记录,在最后一个 5.5 beta 和 5.6.0 版本之间,新维护者在很短的时间内进行了大量的提交;没有通过 Pull Request,也没有明显的审查或讨论。这立即引起了我们的担忧。通常,项目不会在主要新版本发布之前这样做。立即审查每个提交都显示了 5.6.1 中提交和更新的奇怪测试文件,而这些文件在测试框架或项目代码中没有相应的更新,因此这些文件是“未使用的”。通常,测试文件会与代码修复一起提交,或者与先前的 issue 关联,或者与测试用例所解决的提交关联。对于一个上游项目的经验丰富的维护者来说,这似乎是一个很大的疏忽。提交消息大致合理,但实际上没有意义,尤其是在比较 5.6.0 和 5.6.1 之间的(小)差异时。
进一步调查导致发现了嵌入在构建系统中的“stage zero”,并借此我们能够逐步穿过混淆层,解开第二和第三阶段。几分钟内,我们清楚地意识到,开发它花费了大量的精力。这不是一个开发者在雨天下午完成的工作。此外,第二阶段暗示这是一种专门针对特定环境(使用 GCC 和 glibc 构建的 Debian 或 RPM 包)的后门。从后门化的 tarball 或从 git 构建的普通用户永远不会受到影响。这提高了警报。所以在我们进一步进行逆向工程之前,我们评估了影响。
一段时间以来,openSUSE 已经停止使用 XZ 来压缩我们的发行版 rpm 包;我们已经切换到 Zstd。然而,XZ 在发行版中被广泛使用,包括压缩我们的 GCC 编译器源代码,我们用它来构建发行版中的所有内容。我们检查了,发现可疑的恶意 XZ 版本正在被用于构建我们的活动 openSUSE GCC 编译器,它被用于发行版的每个构建中。在这里,最坏的情况是,恶意 XZ 修改了 GCC 编译器构建源代码的解包过程,我们拥有一个不再可信的系统编译器。虽然我们对源代码进行签名检查(并且已经安全地保存了我们曾经在任何地方使用的每个源代码输入),但我们无法检查解包后的源代码是否真的是在解包之前经过签名检查的源代码。
因此,即使没有关于后门的进一步信息,我们也明白最坏的情况可能是灾难性的。所以我们开始识别受影响的项目、产品和发行版。幸运的是,这个列表最终并不大。一个临时团队被组建起来,以处理后门的移除。
为我们的用户初步移除后门
openSUSE Tumbleweed 拥有一个紧急更新通道,我们可以使用它来从常规 Tumbleweed 快照中的致命回归中恢复。这非常罕见,这要归功于我们的自动化测试管道,但它们确实会发生。我们将 XZ 的降级注入到该紧急更新通道中,并开始构建一个临时 openSUSE 快照版本,该版本移除了恶意的 XZ 更新。然而,由于后门的混淆性质未知,我们正在以最坏的假设进行规划。我们开始收集使用可疑的 GCC 编译器构建和发布的软件包数量。这是一个非常长的列表。此外,使用 Ghidra 反编译恶意的后门对象代码需要我们花费几个小时。经过简短的同步,我们决定采取安全路线,丢弃所有使用潜在恶意 XZ/GCC 构建的软件包,并开始使用仅来自安全备份的软件包重新构建所有软件包,以尽快恢复发行版的完整性。openSUSE 定期将“bootstrap 模式”作为我们发行版开发的一部分进行测试,并依赖 Open Build Service 提供的重建自动化,因此这并不是大量的人工工作。这只是对我们的构建集群的巨大负载。我们不得不等待几个小时,这让我们有时间进一步分析后门。
后门分析
对象代码的分析结果非常耗时。虽然第二阶段检查正确的构建条件(是发行版构建吗,是否具有预期的编译器环境等)很容易解码,并且帮助我们了解潜在的影响,但最初我们并不清楚注入的混淆对象代码在做什么。
通过使用 Ghidra,我们能够从注入的机器代码中恢复出某种可读的 C 代码,所以我们开始尝试破译这个谜题。发现 _get_cpuid 函数的入口点,它是 IFUNC 处理的一部分,是第一个发现。只需在 Google 上搜索这个词的组合,就引出了一个上游讨论,关于 oss fuzz 项目中禁用 ifunc,以及 Fedora 社区的一个有趣的 bug 报告,其中报告了 XZ 5.6.0 的 Valgrind 问题,并且上游显然通过更新不相关的代码(包括“测试文件”)来修复这些问题。不仅仓库中有提交,而且还存在与这些提交直接相关的误导性沟通,这使得很明显,我们不是发现了一个无辜的维护者不幸被黑客入侵,而是一个由当前上游维护者策划的行动。如果警报声还不够响亮,这使它们的声音加倍。
准备公开披露
结合我们学到的所有信息,情况变得更加清晰。有人花费了多年的准备时间来奠定基础,建立良好的维护者声誉,接管项目,然后在几个发行版项目的关键窗口期,以及农历新年和其他节假日期间,发布一个带有精心设计的混淆后门的新版本,该后门专门针对使用 GCC、Binutils、Glibc 和 RPM 或 Debian 构建过程的特定发行版。
考虑到所有这些,我们意识到这将会有大量的公众报道。它将在新闻中持续数天甚至数周。所以我们开始一个新的工作流来准备与沟通团队进行沟通。
公开披露
在公开披露时,所有工作流都已经完成。我们确定了受影响的产品列表,并且已经发布了所有受影响产品的更新。准备好将沟通内容发布到网上并发送给相关方。这一切都归功于许多人超越了职责范围,将所有其他事情放在一边,及时且投入地做出反应,以确保我们没有遗漏或忽视任何事情;这一切都发生在漫长的公共假期周末已经开始的时候。向所有为此工作的人致敬。
故事的英雄
之所以没有发生更糟糕的事情,这完全归功于 Andres Freund,他是 PostgreSQL 社区的一名开发者,他没有忽视最近升级到 Debian unstable 安装后 SSH 登录的奇怪性能下降。这证明了,不放弃其他人可能在未来几个月甚至几年内忽略的事情,正是英雄成为英雄的原因。
然而,依赖英雄不是一种可持续和可靠的策略。所以,为了未来,我们都需要从发生的事情中吸取教训,并成为一个由许多小英雄组成的团队。
事件的 TLDR
Linux 发行版被滥用来向其用户交付后门。后门的具体目的是仍然在推测中。它可能从一个想要通过公共云托管虚拟机出售访问权限的个人开始,这些虚拟机具有开放的公共 SSH 端口。这是不太可能,但仍然有可能的一个极端情况。另一个极端情况是,一家公司向国家行为者出售后门,这些行为者利用这些后门来远程和秘密地访问任何 Linux 机器。虽然犯了一些错误,但它几乎实现了这个目标。真相在哪里?需要进一步的证据来识别和分析。
展望未来
在仔细观察三月底发生的事情之后,本文的其余部分将转向展望未来。
Linus 定律和发行版
“有足够的眼睛,所有的 bug 都是浅层的”。在开源社区中,这经常被引用为开源可以信任的原因之一。对于吸引足够多技能贡献者的开源项目,这个“定律”可能至少有一些道理。然而,我们从 Heartbleed 事件中了解到,这些先决条件并非普遍成立。有许多项目绝对是必不可少的,但被认为是无聊的,并且无法吸引大量的维护者或贡献者,而那些在项目上工作的人已经被大量的工作淹没了,并且无法花费大量精力来引导新的加入者。
XZ 后门的设计目标仅限于发行版。首先,通过后门在展开之前执行的预检查,其次是因为植入所需的条件仅在这些发行版的下游存在。Debian 以及其他受影响的发行版,如 openSUSE,都承载了大量仅存在于下游的补丁,应用于关键开源项目,例如本例中的 OpenSSH。事后看来,这应该为发行版的工作带来另一个与 Heartbleed 级别相当的教训。这些补丁构建了嵌入后门的必要步骤,并且可能没有像各自的上游维护者那样受到严格的审查。无论你是否信任 Linus 的法则,这里甚至没有给它发声的机会。上游并没有对用户造成失败,而是发行版对上游和他们的用户造成了失败。
开源及其社区
能够检查开源软件的源代码,使社区相对于专有单一供应商的替代方案具有无与伦比的优势。然而,审计源代码需要耗费大量时间,并且通常需要具有高度领域和安全专业知识的专家。商业发行版应该并且正在发挥重要作用;但他们并没有识别到这一点。从这个意义上说,XZ 项目是安全审计工作通常如何分配精力的完美盲点。它深深嵌套且对每个发行版都至关重要,原因并不明显,并且多年来只有一个维护者和极少的贡献者或审查者。它不是吸引数千名开发人员或安全研究人员的闪亮的新型云原生或其他花哨的开源项目,但它对于现代计算的完整性和安全性同样重要。如果说这里有什么要学习的,那就是需要根据这些经验调整关注重点的选择标准。
此外,其他人已经强调,最初的攻击向量并非技术性的。它不是一个古老的 tar 包。实际的初始攻击是社会工程学,并使用了社区中的有害行为。这是真实存在的,并且不仅在本例中影响着开源项目的现有维护者。许多故事都讲述了维护者压力或倦怠与项目社区中的有害参与者有关。虽然我相信发行版并非参与这些活动的一部分,但我们并没有为此做好预防措施。发行版开发者专注于他们的问题和他们的用户,并且由于时间有限,有可能会忽视(上游)开源社区。这是我们还需要牢记的另一件事。
像 CHAOSS 和 Open Source Security Foundation 这样的倡议之所以成立,是因为否则这些情况很容易被忽视。它们为分析“公交车因素”或“共谋因素”提供了基本服务,即需要多少参与者才能破坏一个项目,从而允许其他人专注于将帮助导向最重要的地方。
自由的代价
FLOSS 并非关于成本,也不是关于免费使用,而是关于检查和(再)使用的自由。这种自由的代价是什么?在专有世界中,软件是付费的。在开源世界中,这种自由需要得到应有的认可和重视。当有人将 XZ 后门称为软件供应链安全事件时,这并不是完整的图景。软件供应链是指一端存在供应商的情况。但开源项目和社区今天并不是供应商。他们与任何消费者之间没有具有法律约束力的合同,也没有资金交换。存在一个社区,规模各异,贡献和协助,无论是作为志愿者还是作为有偿工人。大多数项目收到的资金都不够。
作为一个开放性的思考:发行版是否应该主动构建和管理他们的供应链,并将“他们的供应商”视为具有具有法律约束力的互惠条款和约定补偿的真实供应商?
安全的信任网络是新的供应链安全
在本例中,签名的 tar 包被用于发布后门的启动器。关于这一点已经有很多讨论。我们需要意识到这是一种干扰。一个陷阱。在代码大小方面,后门的 99.9% 都在源代码仓库中。tar 包中的启动器是为了限制后门的影响范围,仅限于预期的受害者,在技术上不需要任何东西或任何东西。将剩余的 0.1% 也提交到项目代码仓库中,以略有不同的方式,同样容易嵌入并且同样难以发现。
对于大多数其他可想象的攻击场景,签名的发布制品提供了重要的质量。它们满足了仅发布已确定可以发货的产品的期望。它们提供了一条到来源(“供应商”)的独立可验证的链。然而,每个发行版都从这个可验证的第一部分链开始,然后在顶部添加内容。通常(或者现在几乎总是)以一种透明的方式验证这些更改(以符合 SLSA 的程序的形式),所有这些都是隔离的。这些不连贯的链有多可靠?目前,发行版偶尔会在上游项目发布之上重用相同的或类似的补丁,但除此之外,大部分时间都在隔离工作,并且很少主动协作。激活后门的必要下游补丁在发行版中存在了近 10 年,但尚未在上游中看到。
我们认识到 XZ 后门构建得非常巧妙。然而,它在执行方面存在令人惊讶的缺陷。任何对嵌入进一步的后门感兴趣的人都从对所有错误发生情况的广泛公开报道中学习。这些错误已经被指出,发表并学习。我们为这个后门的幕后黑手提供了未来攻击的免费培训。现在是发行版也从中学习并接受培训课程的时候了。我们需要积极协作,并与开源项目和彼此建立一个强大、可靠的信任网络,以便为应对未来不可避免的挑战做好准备。让我们一起构建一个安全的信任网络!
这篇文章中的图片由 Matthias Pastwa 拍摄,并根据 CC-BY-ND 2.0 DEED 使用