互联网首次劫持:一名志愿者差点搞垮了Linux
五百毫秒。
半秒。
这是互联网未被劫持的临界点。
2024年3月。旧金山。
一位名叫Andres Freund的三十八岁Microsoft工程师正在一个Debian开发系统上对PostgreSQL进行基准测试。这是一项例行工作。Freund是PostgreSQL项目的提交者。他定期测试数据库在预发布Linux发行版上的性能,这是他工作的一部分。
测试环境出现了问题。
失败的SSH登录尝试——那种不断冲击每个面向公众服务器的、自动化机器人尝试随机用户名和密码组合的登录——消耗了远超预期的CPU。一次失败的登录应该迅速终止。而这些登录并未迅速终止。
Freund注意到了。
他进一步调查。他自己本地机器上成功的SSH登录,比大约一百毫秒的基线多花费了五百毫秒。
半秒。
Freund在Valgrind(一个内存调试工具)下运行连接。Valgrind抛出了指向liblzma的错误——这是一个SSH守护进程没有合法理由调用的压缩库。
这时,调查变得紧迫起来。
接下来的几天里,Freund追踪了这些错误。他发现测试机器上的sshd进程在认证过程中执行了来自liblzma的代码。他解剖了git仓库中的xz-utils源代码。源代码是干净的。但发布tarball——Debian实际下载并从中构建的压缩源代码归档——包含了一个名为build-to-host.m4的文件,该文件不在git源代码中。
该文件包含一个混淆脚本。该脚本解码了一个隐藏在名为bad-3-corrupt_lzma2.xz的测试文件中的bash脚本——该文件伪装成压缩库错误处理的损坏测试输入。bash脚本使用自定义混淆结合RC4解密,解码了第二个文件good-large_compressed.lzma。
这条链的末端是一个编译后的共享对象。
这个共享对象是一个后门。
2024年3月29日晚上——据他自己描述,在做饭休息时听一个安全播客期间——Andres Freund将他的发现发布到了Openwall的oss-security邮件列表。
24小时内,Red Hat为其分配了一个CVE编号。严重性评分为十点零。最高分。CISA发布了紧急警报。Debian、SUSE、Fedora、Arch和Kali都回滚了受影响的软件包。GitHub暂停了提交后门的维护者的账户。
事实证明,该后门原定在大约两周内随稳定的Linux发行版一同发布。
Freund是偶然发现的。
这是关于发生了什么、差点发生了什么以及此次行动是什么的案例文件。
这次攻击的目标是xz-utils。
xz-utils是一个压缩工具包。其主要工具xz命令,生成.xz文件——相当于Unix的.zip文件,但压缩率更高。命令行工具之下是一个名为liblzma的库,它为其他需要它的程序提供压缩算法。
liblzma被大量Linux系统软件直接或间接加载。软件包管理器链接到它。系统工具链接到它。而且——通过攻击者专门设计的链条——OpenSSH守护进程链接到它。
这条链是这样运行的:在大多数主要的Linux发行版上,sshd经过打补丁以支持systemd的服务通知机制,称为sd_notify。这个补丁导致sshd加载一个名为libsystemd的库。而libsystemd反过来又加载liblzma。
结果是:在大多数生产型Linux服务器上,SSH守护进程——接收远程登录的进程——在启动时加载一个压缩库,尽管SSH并不压缩认证流量。
一旦压缩库被攻破,控制互联网上每台Linux服务器远程访问的守护进程也就被攻破了。
在后门即将部署之时,Linux运行着全球前一百万个网络服务器中大约百分之九十六。全球最强大的五百台超级计算机全部。Amazon Web Services、Google Cloud和Microsoft Azure中大约百分之九十二的虚拟机。驱动全球大约百分之八十五智能手机的Android系统,也是基于Linux内核构建的。
xz-utils后门,如果随稳定发行版发布,将会存在于上述所有设备中的很大一部分。
Facebook前首席安全官Alex Stamos用一句话描述了预期的结果:通往地球上任何SSH服务器的主密钥。
这就是为什么CVE评分为十点零。
后门的技术设计值得精确理解。
攻击者利用了发布tarball包含在版本控制的git源代码中不存在的自动生成文件这一事实。具体来说,tarball中的build-to-host.m4文件包含了一行被修改过的代码,用于在构建过程的configure步骤中注入一个混淆脚本。
这意味着任何阅读git源代码的人都看不到后门。任何从git构建的人都无法触发它。只有从发布的tarball构建的Linux发行版——实际上是所有发行版——才会执行注入。
注入链分为三个阶段。第一阶段从一个伪装成损坏压缩测试输入的文件中提取了一个bash脚本。第二阶段使用该bash脚本将第二个测试文件解码成一个编译的共享对象。第三阶段将该共享对象链接到编译的liblzma二进制文件中。
该共享对象利用了一个合法的glibc特性,称为IFUNC(间接函数解析器),来劫持一个特定的OpenSSH函数RSA_public_decrypt。
RSA_public_decrypt是OpenSSH中在证书认证期间验证RSA签名的函数。每次客户端尝试使用RSA证书连接时,sshd都会调用此函数来验证签名。
当后门激活时,sshd调用的是攻击者的代码。
攻击者的代码检查了RSA公共模数——客户端证书中传递的大整数值。通常,此值用于标准的RSA验证。在后门中,它实际上是一个有效载荷容器。代码使用硬编码的ChaCha20对称密钥解密了有效载荷。然后,它使用硬编码的Ed448公钥验证了解密有效载荷的签名。
如果签名验证成功——意味着有效载荷由攻击者的私钥签名——代码将以root权限执行嵌入的shell命令。
这就是安全研究人员所说的门控远程代码执行。后门仅在攻击者提供有效加密签名时才激活。偶然发现后门的普通攻击者无法利用它。只有Ed448私钥的持有者才能触发它。
这个细节很重要。一个为出售而构建漏洞的犯罪分子会使其可供任何购买者使用。一个构建持久访问能力的国家行为者会使其具有排他性。只有他们,以及他们明确授权的任何人,才能使用该密钥。
xz-utils后门是为独占使用而设计的。它不是一个漏洞。它是一个战略资产。
产生后门的行动始于2021年1月26日。
在那一天,一个名为JiaT75的GitHub账户被创建。显示名称是Jia Tan。该账户没有先前的数字足迹。没有以该名称存在的社交媒体。没有会议演讲。没有以前的开源贡献。没有出现在数据泄露事件中。这个名字似乎是一个化名。
JiaT75对xz-utils的首次公开贡献发生在2021年10月29日——该账户创建九个月后。那是一个针对编辑器配置文件的小补丁。无害的。不重要的。那种在不引起审查的情况下建立存在感的贡献。
在接下来的两年零五个月里,JiaT75向开源项目提交了五百多次。绝大多数都是合法改进——代码审查、翻译、持续集成维护、错误修复。有用的工作。真心实意的帮助。
其中大约八次提交是恶意的。
这个比例很重要。六十比一。每提交一次恶意代码,操作者就会产生六十份真实有用的工作。这使得通过统计异常分析检测这种模式变得不可能。攻击者投入了两年半的专注努力,纯粹为了积累足够的信任,以便提交最终重要的八次更改。
这次行动并非单独进行。
从2022年4月开始,一个自称Jigar Kumar的用户出现在xz-devel邮件列表中。Kumar在2022年4月之前在该列表中没有历史记录。他的全部存在都表现为向项目主要维护者发送施压邮件,抱怨响应时间慢,并要求增加新的维护者。
2022年5月,第二个账户——Dennis Ens——出现,询问xz-utils的Java版本维护状态,并随后发送了额外的施压信息。
这两个账户有相同的特征。2022年之前没有数字存在。除了xz-devel邮件列表外没有其他活动。在施压活动之前或之后没有参与任何其他项目。
2024年2月——在后门被提交的几周前——第三个账户出现了。Hans Jansen。Jansen的角色是向Debian维护者施压,要求他们尽快采用受感染的xz-utils版本。2024年3月25日,Hans Jansen提交了一个Debian错误报告,明确要求升级。
四天后,Andres Freund将他的发现发布到了oss-security。
另外两个支持账户——krygorin4545和misoeater91——在各种讨论中提供了背景压力,遵循相同的模式。操作前没有存在。仅在特定的施压窗口期间参与。在目标实现后消失。
Kaspersky的事件后分析指出,这些“傀儡”账户名称的地理风格不一致——Singaporean、European、Indian——这表明操作者故意分散了掩护身份,以避免出现协调的迹象。但行为模式——出现时机、同步施压点、每个目标达成后的集体消失——表明这是一个单一操作者或紧密协调的团队。
施压奏效了。
2022年6月29日,xz-utils的主要维护者——一位名叫Lasse Collin的Finnish软件开发者——回复邮件列表,表示Jia Tan将在项目未来扮演更重要的角色,实际上已经作为共同维护者行事。
这是移交。
要理解刚刚发生了什么,有必要理解Lasse Collin所处的境况。
Collin自2009年以来一直独自维护xz-utils。这个项目是无偿的。他在业余时间从事这项工作。就在同一个月早些时候,在2022年6月的一封邮件列表回复中,Collin公开承认他正在处理长期的心理健康问题。他用自己的话说,将该项目称为一个无偿的“爱好项目”。
Lasse Collin对发生的一切不负有责任。安全社区在这个问题上意见一致。Collin从事的是无偿的爱好工作。他正在应对有记录的健康挑战。他受到了事实证明是国家级情报行动的持续、协调施压。将他置于这种境地的系统辜负了。他没有辜负系统。
该行动利用的不是Collin的能力。而是他的结构性位置——孤身一人、无偿工作、应对现实压力、负责维护数十亿人使用的基础设施,却没有机构支持。
专业的攻击者识别了这种结构并以此为目标。
移交完成后,基础设施准备工作开始。
2022年10月,Jia Tan被添加到了GitHub上的Tukaani组织。2022年12月,他创建了该仓库的组织结构并进行了首次发布。2023年3月,他将Google的OSS-Fuzz(自动化漏洞扫描平台)的主要安全联系电子邮件从Lasse Collin的地址更改为他自己的。从那时起,任何与安全相关的错误报告都会先到达Jia Tan,然后才能到达其他人。
2023年6月,Jia Tan将IFUNC解析器基础设施引入liblzma。这些提交似乎是合法的性能优化工作。事后看来,它们是最终注入后门的钩子。
2023年7月,Jia Tan在OSS-Fuzz上提交了一个拉取请求,要求禁用xz的IFUNC模糊测试。此更改旨在防止模糊测试流程在后门最终发布时检测到基于IFUNC的异常。
2024年2月,另一次提交破坏了Landlock(一个限制进程权限的Linux内核安全功能)的构建系统检测。此提交禁用了xz在原本会强制执行此功能的系统上的沙盒。
2024年2月23日和3月9日,后门本身分两个阶段提交,作为xz-utils 5.6.0和5.6.1版本发布的一部分。
十九天后,Andres Freund注意到SSH延迟了500毫秒。
研究人员分析了此次行动留下的提交元数据,发现了一个模式。
Jia Tan的提交时间戳主要集中在Central European或Eastern European时区。工作时间大约对应Central European Time上午九点到下午五点。活动在中国主要公共假日期间继续,并在几个European公共假日期间暂停。
名称及其声称的运营地理位置是East Asian。实际工作模式是European。
这就是情报专业分析师所说的特征泄漏。一名操作者花费了三十多个月来维护一个掩护身份。但嵌入在每次git提交中的自动时间戳周期性地揭示了进行提交的机器的实际位置。
在具有相关专业知识的安全研究人员的公开分析中,出现了三种可能的归因。
美国安全研究员Dave Aitel,前NSA计算机科学家,公开评估该行动符合APT29的模式——APT29是被United States和United Kingdom政府归因于Russia's Foreign Intelligence Service的先进持续威胁组织。APT29以长期间谍活动而闻名,包括2020年披露的SolarWinds供应链泄露事件。工作时间与Moscow时区与Jia Tan的模式相符。
Costin Raiu——Kaspersky's Global Research and Analysis Team前负责人,拥有三十年归因复杂行动的经验——在2026年2月的一次播客采访中确定了三个可能的候选者。Russia的APT29是其中之一。China的APT41,与Ministry of State Security相关,是第二个。North Korea的Lazarus Group,已在Fragment Zero早期报道中提及,是第三个。
截至2026年4月,没有任何情报机构公开归因此次行动。没有提出起诉。没有进行逮捕。Jia Tan的真实身份仍然未知。
在具有相关专业技能的研究人员中,毫无争议的是,该行动的耐心、操作安全性、加密复杂性和资源投入,都与国家级情报机构——或其紧密的功能等效体——的行为模式一致,而与个人犯罪或黑客行动主义活动不符。
这不是一个孤立的黑客所为。
xz-utils行动之所以可能,是因为现代技术文明构建其关键基础设施的方式存在结构性特征。
运行互联网的软件在很大程度上是由志愿者利用自己的时间构建的。从这些软件中获利的公司只回馈了其经济价值的一小部分。
xz-utils捆绑在每个主要的Linux发行版中,并运行在全球很大一部分服务器上。它的维护者是无偿的。OpenSSL,为互联网大部分提供加密服务的库,在2014年Heartbleed漏洞爆发之前,人手严重不足是众所周知的。Log4j,2021年Log4Shell漏洞背后的Java日志库,由少数志愿者维护——支撑着全球的企业基础设施。
在所有案例中,被数十亿美元公司视为关键基础设施的库,却仅以“爱好项目”的资源进行维护。
xz-utils行动并未创造这种结构性漏洞。它只是利用了它。
2024年4月11日——Freund披露两周后——U.S. Cybersecurity and Infrastructure Security Agency发布了一份正式声明,承认这个结构性问题。CISA的立场是:确保开源基础设施安全的负担不能落在个人无偿维护者身上,而使用开源软件的公司必须通过财务或开发者时间的方式回馈,以创建一个可持续的生态系统。
这些建议不具约束力。它们是最佳实践。它们依赖于那些激励结构历史上并未奖励此类投资的公司自愿采纳。
一个月内,Linux Foundation和Open Source Security Foundation发布了一份联合警报,警告类似的社会工程接管尝试已在针对其他多个开源项目进行中。OpenJS Foundation——维护Node.js、jQuery和相关JavaScript基础设施——公开披露它收到了一场与xz-utils模式相同的协调施压活动,但由于xz-utils的披露让社区知道了要寻找什么,所以才将其驳回。
2026年的一份Linux Foundation报告记录了整个生态系统中更广泛的模式。该报告的核心发现是:xz-utils事件并非孤立事件。它是一种方法。这种方法正在大规模尝试。大多数成功的检测之所以发生,是因为xz-utils案例提供了一个可供匹配的特征。
究竟有多少未被发现的尝试——即已经进行中但尚未被捕获的行动——从公共来源来看,是无法统计的。
在Fragment Zero前两集,关于Dark Forest假说的案例文件以一个观察结果结束。Liu Cixin在2008年形式化的学说——沉默即生存,隐蔽即战略必需,暴露即生存危险——是人类冲突史上最古老的操作安全原则。
所有在不确定威胁和不对称能力条件下运作的力量,都得出了相同的结论。
保持安静。小心行动。假定被观察。
xz-utils行动是在人类信任关系中执行的Dark Forest。
攻击者没有突破防火墙。攻击者没有利用零日漏洞。攻击者没有绕过任何加密保护。攻击者做了一件简单得多事情。攻击者在光天化日之下潜伏了三年,从事有用的工作,建立真正的信誉,行为举止与任何其他乐于助人的贡献者一模一样,同时——悄无声息地、耐心地、以大多数技术组织难以想象的战略耐心——准备着使用已准备好的基础设施的那一刻。
这次攻击几乎完全因为它的沉默而成功。它不是被任何安全工具、任何审计、任何机构防御所检测到,而是被一位工程师偶然发现的五百毫秒不明延迟。
Andres Freund在披露后几周内发布到Mastodon上关于他自己发现的声明,应该结束这个案例文件。
未来依靠运气是一个糟糕的策略。
xz-utils后门被捕获了。
此次行动的Dark Forest版本——针对信任关系而非计算机系统的版本——正在此刻,针对数量不定的其他关键开源项目进行尝试。这种模式奏效。使其奏效的经济激励并未发生实质性变化。机构层面的回应是真实存在的,但不足够。
发现下一个后门的工程师也需要运气。他们需要在正确的时间,在正确的系统上,查看正确的基准。他们需要足够关心,才能追溯异常的来源。他们需要在行动的主要负责人将有效载荷发布到稳定版本之前,公布他们的发现。
他们具体需要那五百毫秒。
这个时间间隔,正是2024年3月互联网与一个未知行为者持有的单一加密密钥之间的距离,而那个密钥本可以解锁地球上所有运行SSH的Linux服务器。
Fragment Zero将追踪此案例文件。
案例文件不会关闭。它只是等待。