RubyGems 导航菜单

博客

返回博客文章

RubyGems 中的非安全对象反序列化漏洞

大家好!RubyGems 中发现了非安全对象反序列化漏洞。遗憾的是,该漏洞可能被用于升级到远程代码执行漏洞。好消息是,这个问题已被 Max Justicz 负责任地报告给 RubyGems 团队,我们能够迅速修复该问题。RubyGems 团队已审核所有宝石,并且根据我们掌握的数据,我们可以高度确信,没有近期发布的宝石会受到影响,但由于该漏洞已在生产中存在了一段时间,因此无法确定 零个 宝石也没受到影响。

您可以在 此处阅读 RubyGems 的 CVE 公告。

该漏洞是什么?

该漏洞属于“非安全对象反序列化漏洞”。这意味着攻击者能够将自己选择的一个对象的实例注入目标系统。机智的攻击者可以注入一个能与该系统以某种方式交互的对象,使其能够执行任意代码。

这个特定情况与 RubyGems 在 Gem 文件中存储校验和的方式有关。校验和存储在 Gem 中的 YAML 内,在此修复之前,它们是使用一个 bare YAML.load 进行读取的。 YAML 就像 Marshal 一样,目的是序列化和反序列化任意 Ruby 对象。当 RubyGems.org 处理 Gem 上载时,它 读取 Gem 规范,然后依次 读取 Gem 中的校验和。机智的攻击者可以将一个格式化为 YAML 的校验和文件写入到一个 Gem 中,以注入任意 Ruby 对象,然后将该对象用作升级点。

影响是什么?

这个 bug 的影响是攻击者可以在 RubyGems.org 上执行任意 Ruby 代码。然而,在对 Gem 文件进行多次审计后,我们发现数据库中的数据和 S3 存储中的 Gem 文件没有任何篡改。Gem 文件存储在版本化的 S3 存储桶中,因此我们能够比较存储在数据库中的校验和与存储在 S3 存储桶中的版本。任何 Gem 篡改都将通过新的 Gem 版本和校验和差异来表示。

时间表是什么?

  • 10 月 6 日:Max Justicz 报告了问题
  • 10 月 6 日:David Radcliffe 验证了问题并热修了服务器
  • 10 月 7 日和 8 日:RubyGems 团队对所有 Gem 进行了审计
  • 10 月 9 日:RubyGems 已发布 修复版本公告

RubyGems.org 已受到怎样的攻击时间?

该 bug 在 2012 年引入到 RubyGems 的 此提交 中,所以 RubyGems.org 从那时起就可能已受到攻击。

我们采取了什么措施来修复它?

为了修复此问题,我们添加了一些用于 Monkey 补丁 RubyGems 的代码,以便只能反序列化安全类型。由于此 Monkey 补丁是修补 RubyGems 而 RubyGems.org,因此我们决定修补 RubyGems 本身。这就是为 RubyGems 发布 CVE 并且针对 RubyGems 创建补丁的原因。

我们是怎样验证 Gem 的?

Gem 存储在版本化的 S3 存储桶中。我们还存储每个 Gem 的校验和,但校验和尚未存储在 2015 年 2 月 8 日之前。我们能够验证 2015 年 2 月 8 日之后创建的 Gem 的校验和匹配。我们还能够验证以前版本的 Gem 没有创建新版本。

由于此漏洞可能自 2012 年以来就已经存在,并且结合 RubyGems.org 开始记录 Gem 校验和的日期,我们无法 100% 自信地说没有一个 Gem 受到攻击。我们只能非常自信地说,没有最近发布的 Gem 受到攻击。

我们将如何防止更多问题?

过去,当 类似的问题出现 时,RubyGems 未被视为“受攻击代码”,并且 RubyGems.org 进行了修补。原因是 RubyGems 通常被用作客户端库,并且 Gem 安装的基本部分是执行任意 Ruby 代码。因此,这种类型的漏洞被视为 RubyGems.org 的一个问题,而不是 RubyGems,即使受攻击代码存在 RubyGems 本身中。

为了今后避免类似问题,我们会将 RubyGems 中触发的 RubyGems.org 中的安全问题视为 RubyGems 本身中的安全问题。 换句话说,如果 RubyGems 中的问题导致了 RubyGems.org 中的故障,我们会修复 RubyGems。此项政策有助于保护 RubyGems、RubyGems.org 和使用 RubyGems 的所有服务器。

Aaron Patterson