2024 年 3 月,Linux 核心压缩软件xz
被发现存在后门,由名为Jia Tan的恶意维护者在三年时间内秘密插入。此事件震惊开源社区,因其影响巨大(允许在安装ssh
的受影响机器上远程执行代码)且难以检测,仅因微软的 Postgres 开发者 Andres Freund 的勤奋(或许还有运气)才避免了灾难。Andres Freund 在调查ssh
在多台Debian unstable机器上的 500ms 性能回归时,追踪到liblzma
库,识别并记录了后门。
攻击工作原理
- 主要意图是通过劫持
ssh
程序实现目标机器的远程代码执行,替换ssh
的一些函数行为(如RSA_public_decrypt
),以便在特定 RSA 密钥登录时攻击者可在受害者机器上执行任意命令。 组合两部分安装并激活后门:
- 解密并安装恶意对象文件的脚本:后门未包含在
xz
源代码中,而是包含在恶意维护者Jia Tan构建并签署的xz
5.6.0 和 5.6.1 版本的 tarball 中,此 tarball 包含从存储库中某些测试的.xz
文件中提取恶意对象文件的细微修改。该脚本在xz
构建过程中解密/反混淆几个假的.xz
测试文件,最终生成一个在xz
构建期间运行的 shell 脚本和一个恶意二进制对象文件。 - 挂钩
RSA_public_decrypt
函数的过程:xz
后门利用glibc
的ifunc
机制,在ssh
加载时修改RSA_public_function
的地址,从而在特定条件下运行恶意代码。在一些 Linux 发行版中,ssh
与libsystemd
链接,而libsystemd
又与liblzma
链接,当sshd
执行时,动态加载器加载libsystemd
和liblzma
,后门可在liblzma
加载时运行任意代码,修改RSA_public_decrypt
函数的地址,赋予攻击者 RCE 权限。
- 解密并安装恶意对象文件的脚本:后门未包含在
避免未来的xz
灾难
- 从社会问题角度,应在开源生态系统中建立更好的抵御恶意实体接管基础开源项目的弹性;从技术角度,应采取措施降低此类攻击再次发生的风险。
- 从可信源构建软件:应从由最可信方认证的源构建软件,如 GitHub 自动生成的存档。NixOS 虽有使用 GitHub 源存档的文化,但
xz
作为 Nixpkgs 引导的一部分被构建,此时只能依赖维护者提供的 tarball,存在信任风险。 在不受信任的发布 tarball 中构建信任:
- 比较源:想法是作为发行版,应易于验证使用的源 tarball 与 GitHub 上的源相同,但实际操作中维护者提供的 tarball 与源的差异是常见的,这给软件供应链安全带来挑战。
利用按位可重复性:
- 可重现地构建 tarball:PostgreSQL 项目采用此方法,使 tarball 生成过程可重现,用户可独立验证维护者提供的 tarball 是否从原始源代码生成,但此方法需上游项目维护者实现,在 FOSS 社区中的采用可能较慢。
- 检查各种起始资产之间的构建收敛性:假设
xz
是按位可重现的,在引导后使用 GitHub tarball 再次构建xz
,如果两次构建的工件不同,则怀疑存在供应链妥协。通过在nixpkgs
中重写xz
包,使用fetchFromGitHub
函数从 GitHub 获取源代码,在构建后添加compareArtifacts
阶段比较生成的liblzma.so
文件,可检测到被篡改的xz
源 tarball。此方法需在nixpkgs
中为每个作为引导阶段一部分构建的包实现类似的安全防护,并可选择性地应用于长期具有良好可重复性的包。
作者感谢[Théo Zimmermann]、[Pol Dellaiera]、[Martin Schwaighofer]和[Stefano Zacchiroli]的反馈和讨论。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。