LWN:XZ后门攻击细节!

关注了就能看到更多这么棒的文章哦~

How the XZ backdoor works

By Daroc Alden
April 2, 2024
ChatGLM translation
https://lwn.net/Articles/967192/

版本号 5.6.0 和 5.6.1 的 XZ 压缩工具和库被植入了针对 OpenSSH 的后门。Andres Freund 发现了 这个后门,他注意到在进行一些微基准测试(micro-benchmarking)时,SSH 登录失败时消耗了大量 CPU 时间,并从这一点追踪到了后门。这个后门是由 XZ 的共同维护者 "Jia Tan" 引入的 — 很可能是某个或某些未知人士的化名。这个后门是一个复杂的攻击,包括了多个组成部分:从构建系统、链接时到运行时。

社区对这次攻击的反应和技术的方面一样有趣。关于更多信息,请参考 这篇配套文章。

构建时

后门包括了几个不同的阶段,从软件包开始构建时就开始了。Gynvael Coldwind 写了一篇关于后门构建时部分的深入调查。XZ 的发布是通过 GitHub 提供的,GitHub 已经禁用了维护者的账户并将发布内容下线。像许多使用 GNU Autoconf 的项目一样,XZ 提供了包含源代码和相关文件的自动生成的 tarball 以及包含生成的构建文件的版本。这些额外的文件包括 configure 脚本和项目里的各个 makefile。发布包含生成文件的版本,就可以让软件的下游用户在不需要安装 Autoconf 的情况下进行构建了。

然而,在这种情况下,维护者提供的源 tarball 中的脚本并不是由 Autoconf 生成的。相反,其中一个构建脚本在 m4/build-to-host.m4 中包含了后门的第一步。这个脚本最初来自 Gnulib 库;它提供了一个宏,用于在构建环境和程序的运行时环境之间转换路径名的样式。这些 XZ 发布版中的相应文件被修改,用来提取出后门下一阶段要用的内容,也就是包含在 tests/files/bad-3-1corrupt_lzma2.xz 中的内容。

这个文件被包含在仓库中,表面上作为 XZ 测试套件的一部分,尽管它从未被那些测试使用。它在版本 5.6.0 发布之前就已经提交了。这个文件,据说是一个损坏的 XZ 文件,实际上是一个有效的 XZ 流,其中一些字节被故意交换了 — 例如, 0x20 与 0x09 所出现的地方会互换。解码后,它产生了一个shell 脚本,用于解包并执行后门的下一阶段。

后门的下一阶段位于 tests/files/good-large_compressed.lzma 。也就是 Freund 邮件中附带的 injected.txt 文件。该文件不仅包含脚本的下一段内容,还包含形成实际后门的额外二进制数据。最后的脚本跳过提取它的文件的头部,然后使用 awk 对文件的其余部分进行解密(decrypt)。最后,使用 XZ 命令行程序解压这个解密流,以提取一个名为 liblzma_la-crc64-fast.o 的预编译文件,该文件也附在 Freund 的邮件中了。

链接时

提取出来的文件是一个 64 位的可重定位 ELF 库。构建过程的剩余部分会将其链接到最终的 liblzma 库去,该库最终被一些发行版中的 OpenSSH 加载。那些发行版会对 OpenSSH 打补丁,使用 systemd 来通知守护进程就绪; libsystemd 依赖于 liblzma 来压缩日志文件。Lennart Poettering 已经发布了一些示例代码(由 Luca Boccassi 编写),展示了如何让应用程序使用 systemd 就绪通知,而不需要引入整个库。当动态链接的进程使用恶意的 liblzma 时,它使用 间接函数(indirect function) 机制来把自己加入链接过程。

间接函数是 GNU C 库 (glibc) 的一个特性,它允许开发者包含一个函数的多个版本,并在动态链接时选择使用哪个版本。间接函数对于包含依赖于特定硬件特性的函数的优化版本很有用,例如。在这种情况下,后门提供了自己的间接函数解析器 crc32_resolve() 和 crc64_resolve() ,分别选择要使用的 crc32() 和 crc64() 版本。 liblzma 通常不使用间接函数,但使用更快的函数来计算校验和,这听起来确实也像是这个特性的一个合理用途。这也可能解释了为什么攻击本身存放在一个名为 liblzma_la-crc64-fast.o 的文件中。

当动态链接器排布好那些函数的位置时,它会调用后门的解析器函数。此时,动态链接仍在进行中,因此链接器的许多内部数据结构尚未设置为只读。这会让后门通过覆盖过程链接表 (PLT, procedure linkage table) 或全局偏移表 (GOT, global offset table) 中的条目来操弄已经加载的库。然而, liblzma 在 OpenSSH 的链接顺序中加载得相当早,这意味着后门的最终目标 OpenSSL 加密函数可能还没有被加载。

为了处理这个问题,这个后门里添加了一个审计钩子(audit hook)。动态链接器在解析符号时调用所有注册的审计钩子。后门使用这个机制来进行等待,直到它看到 RSA_public_decrypt@got.plt 符号可以解析出来。尽管名字如此,这个函数实际上是处理 RSA 签名(这是一个解密操作)的一部分 — OpenSSH 在验证客户端在连接期间提供的 RSA 证书时调用它。

运行时

一旦后门检测到这个函数被链接上来,它就会用自己实现的函数来替换它。这个被修改的版本具体做了什么仍在调查中,但至少它的一个功能是尝试从提供的 RSA 证书的公钥字段中提取命令(这意味着用于这种攻击的证书实际上不能用于正常认证)。后门检查命令是否由攻击者的私钥签名并且格式有效。如果是,那么后门会直接以运行 sshd 的用户身份执行给定的命令,这通常是 root 用户。

Anthony Weems 编写了一份解释,介绍了利用的运行时部分的,其中包括一个用于检测漏洞利用尝试的蜜罐,以及生成命令有效负载的代码。使用后门涉及使用私钥签署要执行的命令,但攻击者的私钥不可用,所以需要修补被植入后门的服务器,从而使用另一个私钥。这也意味着远程检测被植入后门的服务器几乎是不可能做到的,因为它们对于不使用攻击者私钥的连接不会有任何特别的反应。

最终,这个后门的效果似乎是被攻击的 SSH 服务器在接收到一个手工制作的 RSA 证书用于认证的连接时,可以执行攻击者控制的代码。

反分析

后门的设计使其在没有直接检查 liblzma 时很难被注意到。例如,选择启用远程代码执行而不是绕过认证,意味着利用该漏洞不会被人看到可以通过传统管理工具注意到的登录会话。后门的代码还使用了多种技术来使发现变得更加困难。例如,字符串 "RSA_public_decrypt@got.plt",它被审计钩子使用,但在利用的二进制文件中从未出现。相反,它使用了一个trie来保存各种字符串。Serge Bazanski 发布了一个列表,其中包含了以这种方式编码的恶意 liblzma 中的字符串。

对该列表进行检查后,看起来 RSA_public_decrypt 可能不是唯一被干扰的函数;还有其他几个加密例程也在其中。它还显示了用于干扰 OpenSSH 日志记录的各种函数和字符串。这尚未得到证实,但似乎被危害的 SSH 服务器实际上不会记录任何使用该漏洞的连接。

后门还包括许多检查,以确保它在预期的环境中运行 — 这是现代恶意软件的标准预防措施,旨在使逆向工程变得更加困难。后门只在特定情况下激活,包括:在非图形化环境中运行, 作为 root 用户 (参见 Freund 的这条评论),在位于 /usr/sbin/sshd 的二进制文件中, sshd 具有预期的 ELF 头,并且其函数没有被调试器插入断点。尽管有这些障碍,社区仍在努力逆向工程并解释后门代码的其余部分,工作仍在进行中。

后门还包括代码,用于修补 sshd 本身的二进制文件,以禁用seccomp()并防止程序为其子进程创建chroot 沙箱 (参见这条评论)。总的来说,后门代码有 87KB,这足以容纳更多的做坏事的动作。许多人已经写出了自己的关于如何利用的总结,包括 Sam James 编写的这个全面的 FAQ,它链接到了其他资源。

保持安全

这个漏洞被及时发现,所以几乎没有用户受到影响。Debian sid、Fedora Rawhide、Fedora 40 测试版、openSUSE Tumbleweed 和 Kali Linux 都短暂地发布了受危害的软件包。NixOS 不稳定版也发布了受危害的版本,但由于它没有修补 OpenSSH 以链接 libsystemd ,所以没有受到影响。Tan 还对 XZ 代码做了一些其他更改,使检测和缓解后门变得更加困难,例如破坏沙箱措施和主动尝试重定向安全报告。尽管这个漏洞没有影响到它们的稳定版本,但有几个发行版正在采取步骤迁移到一个不包含 Tan 提交的 XZ 版本,因此用户应该会很快看到相关的安全更新。读者也可以查阅他们发行版的安全通知,以获取更具体的信息。

总结一下,这个后门事件是供应链攻击的一个复杂的例子,它涉及到多个阶段,包括构建时、链接时和运行时。它展示了攻击者如何利用软件供应链中的弱点,以及一旦发现漏洞,社区如何迅速响应。这个事件也强调了安全性和透明性的重要性,以及在面对复杂威胁时,合作和共享信息的重要性。

全文完
LWN 文章遵循 CC BY-SA 4.0 许可协议。

欢迎分享、转载及基于现有协议再创作~

长按下面二维码关注,关注 LWN 深度文章以及开源社区的各种新近言论~

84b66569cfb47d68dd9e5e0d60cba316.jpeg

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值