Cargo 安全公告

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

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

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

此漏洞的 CVE 是 CVE-2019-16760

概述

可以通过 Cargo.toml[dependencies] 部分配置 Cargo 以依赖不同的 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 上被抢占成为恶意包。这不仅会影响您自己在本地编写的清单,还会影响发布到 crates.io 的清单。例如,如果您发布了一个依赖 serde1 到 crates.io 的 crate,那么如果使用 Rust 1.25.0 及更早版本的用户依赖于您,也可能会受到攻击。

受影响的版本

Rust 1.0.0 到 Rust 1.25.0 受此公告影响,因为 Cargo 将忽略清单中的 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 - 向 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,他发现了这个错误并按照我们的安全政策向我们报告了它。