注意:这是官方安全公告的交叉发布。官方帖子也包含使用我们的 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,他发现了这个错误并按照我们的安全政策向我们报告了它。