博客
2024 年 3 月 31 日
RubyGems 不易受到 xz/liblzma 后门的攻击
作者:塞缪尔·吉丁斯
过去几天,安全世界一直专注于揭露 xz/liblzma 后门。有关更多背景信息,请参阅 此问题的早期撰述、此 GitHub Gist、此详细时间表 和 CVE-2024-3094 的官方详细信息页面。
针对该后门已公开,我们不仅对运行 RubyGems.org 本身的软件进行了内部审计,还针对已发布的每颗宝石进行了内部审计。
我们很高兴地报告,RubyGems.org 不易受到此问题的影响。此外,我们很高兴地确认,当前在 RubyGems.org 上发布的任何宝石都不包含易受攻击的 liblzma
库。
我要感谢 RubyGems.org 安全团队的其他成员在此调查中的支持以及他们对生态系统安全的不懈奉献。我也要感谢 AWS 对 RubyGems 安全的持续支持,包括赞助我作为 Ruby Central 的安全工程师 以及资助 rubygems-research 项目。
感谢该项目中整理的数据(可在 research.rubygems.info 公开获得),我们可以快速确认当前发布的宝石不包含任何指向易受攻击的 liblzma
库的引用。
技术细节
通过 Dockerfile 构建的 RubyGems.org 应用容器 不包含易受攻击的 liblzma
版本或 xz
版本。我们的映像基于 Alpine 3.18 stable,该映像从未包含或访问过易受攻击的库版本。另外,Alpine Linux 使用 musl
libc,该库不包含用于激活后门的(仅适用于 glibc)IFUNC 机制。
我们用来构建已部署到生产环境的容器的流程是公开的,在每次提交到 RubyGems.org 公共代码库后都会通过 GitHub Actions 运行。任何感兴趣的各方均可使用 最新的容器构建作业日志 重现构建。
通过在我们构建的容器中运行find / -name '*lzma*'
进行验证,我们仅依赖 5.4.3 版本,而不会依赖容易受到攻击的版本 5.6.0 或 5.6.1。
完整的命令输出
$ find / -name '*lzma*'
/usr/bin/lzma
/usr/bin/unlzma
/usr/lib/liblzma.so.5
/usr/lib/liblzma.so.5.4.3
/app/vendor/ruby/3.3.0/gems/bindata-2.5.0/lib/bindata/transform/lzma.rb
$ find / -name '*xz*'
/sys/module/xz_dec
/usr/bin/unxz
/usr/bin/xzcat
/app/vendor/ruby/3.3.0/gems/bindata-2.5.0/lib/bindata/transform/xz.rb
截至 2024 年 3 月 31 日,RubyGems.org 上唯一包含liblzma
的 gem 是也称为 liblzma 的 gem。该 gem 只包含库的 0.2 和 0.3 版,它们不包含后门。没有 gem 包含xz
命令行工具。
完整的命令输出
irb(main):005> attrs = ['version_data_entries.full_name', 'rubygems.name', 'versions.number', 'versions.platform', 'versions.uploaded_at']
=> ["version_data_entries.full_name", "rubygems.name", "versions.number", "versions.platform", "versions.uploaded_at"]
irb(main):006> VersionDataEntry.where('version_data_entries.name LIKE ?', 'liblzma%.so').joins(:version, :rubygem).pluck(*attrs).map { |p| attrs.zip(p).to_h }
=>
[{"version_data_entries.full_name"=>"lib/liblzma.so", "rubygems.name"=>"liblzma", "versions.number"=>"0.2", "versions.platform"=>"mingw32", "versions.uploaded_at"=>Sat, 31 Mar 2012 05:57:47.212691000 UTC +00:00},
{"version_data_entries.full_name"=>"lib/1.9.1/liblzma.so",
"rubygems.name"=>"liblzma",
"versions.number"=>"0.3",
"versions.platform"=>"x86-mingw32",
"versions.uploaded_at"=>Thu, 21 Feb 2013 13:21:51.961608000 UTC +00:00},
{"version_data_entries.full_name"=>"lib/2.0.0/liblzma.so",
"rubygems.name"=>"liblzma",
"versions.number"=>"0.3",
"versions.platform"=>"x86-mingw32",
"versions.uploaded_at"=>Thu, 21 Feb 2013 13:21:51.961608000 UTC +00:00}]
irb(main):008> VersionDataEntry.where('version_data_entries.name = ?', 'xz').joins(:version, :rubygem).pluck(*attrs).map { |p| attrs.zip(p).to_h }
=> []