Cargo 安全公告

2019 年 9 月 30 日 · Rust 安全团队

注意:这是 官方安全公告 的交叉发布。官方发布版本还包含我们 PGP 密钥的签名版本。

Rust 团队最近收到通知,在使用旧版本 Cargo 构建利用新版本 Cargo 添加的包重命名功能的 crate 时存在一个安全问题。如果您使用的是 2018 年 5 月 10 日发布的 Rust 1.26.0 或更高版本,则不受影响。

此漏洞的 CVE 编号是 CVE-2019-16760

概述

Cargo 可以通过 Cargo.toml[dependencies] 部分进行配置,以依赖不同的 crate,例如来自 crates.io 的 crate。配置如何依赖 crate 也有多种方法,例如如果您依赖 serde 并启用了 derive 功能,它看起来会像

serde = { version = "1.0", features = ['derive'] }

Rust 1.31.0 引入了 Cargo 的一项新功能,其中在此映射中可以指定的可选键之一是 package,这是一种 在本地重命名 crate 的方式。例如,如果您喜欢在本地使用 serde1 而不是 serde,则可以写

serde1 = { version = "1.0", features = ['derive'], package = "serde" }

正是添加了 package 键导致 Cargo 以不同的方式编译 crate。这项功能在 Rust 1.26.0 中首次实现,但在当时是不稳定的。然而,对于 Rust 1.25.0 及更早版本,Cargo 会忽略 package 键,并将依赖行解释为好像它是

serde1 = { version = "1.0", features = ['derive'] }

这意味着当使用 Rust 1.25.0 及更早版本编译时,它会尝试下载 serde1 crate。恶意用户可以在 crates.io 上抢占 serde1 名称,使其看起来像 serde 1.0.0,但在构建时却会恶意行事。

总之,在 Rust 1.25.0 及更早版本中,使用 package 键在 Cargo.toml 中重命名依赖项会被忽略。当使用 Rust 1.25.0 及更早版本时,Cargo 会忽略 package 并下载错误的依赖项,该依赖项可能在 crates.io 上被抢占成为恶意包。这不仅影响您在本地编写的 manifest 文件,也影响发布到 crates.io 的 manifest 文件。例如,如果您发布了一个依赖于 serde1 的 crate 到 crates.io,那么依赖于您的用户在使用 Rust 1.25.0 及更早版本时也可能受到影响。

受影响的版本

Rust 1.0.0 到 Rust 1.25.0 版本受此公告影响,因为 Cargo 会忽略 manifest 文件中的 package 键。Rust 1.26.0 到 Rust 1.30.0 版本不受影响,并且通常会因为 package 键不稳定而发出错误。Rust 1.31.0 及更高版本不受影响,因为 Cargo 理解 package 键。

就 Cargo 版本而言,这影响 Cargo 0.26.0 及之前的版本。未来的所有 Cargo 版本都不受影响。

缓解措施

我们强烈建议受影响版本的用户将其编译器更新到可用的最新版本。防止此问题发生需要将您的编译器更新到 Rust 1.26.0 或更高版本。

我们不会为 1.26.0 之前的 Rust 版本发布补丁。Rust 1.19.0 到 Rust 1.25.0 的用户可以改为应用 提供的补丁 来缓解此问题。

已经对使用 package 键发布到 crates.io 的现有 crate 进行了审计,没有证据表明此漏洞已被在野外利用。我们的审计仅涵盖当前发布在 crates.io 上的 crate:如果您将来发现利用此漏洞的 crate,请随时根据 我们的安全政策 联系 security@rust-lang.org。

事件时间线

  • 2019 年 9 月 18 日星期三 13:54 UTC - Bug 报告至 security@rust-lang.org
  • 2019 年 9 月 18 日星期三 15:35 UTC - 响应确认报告
  • 2019 年 9 月 18 日星期三 - Cargo、Core 和 crates.io 团队商讨如何最佳处理此问题
  • 2019 年 9 月 19 日星期四 - 与 Elichai 确认行动计划并继续审计现有 crate
  • 2019 年 9 月 23 日星期一 - 起草公告,开发补丁,完成审计
  • 2019 年 9 月 30 日星期一 - 发布公告,安全列表获知此问题

致谢

感谢 Elichai Turkel 发现了这个 bug 并根据我们的 安全政策 向我们报告了它。