注意:这是 官方安全公告 的交叉发布。官方帖子还包含使用我们的 PGP 密钥签名的版本。
Rust 团队最近被告知,在使用旧版本的 Cargo 构建使用 Cargo 新版本中添加的包重命名功能的板条箱时存在安全问题。如果您使用的是 2018 年 5 月 10 日发布的 Rust 1.26.0 或更高版本,则不受影响。
此漏洞的 CVE 为 CVE-2019-16760。
概述
Cargo 可以通过 Cargo.toml
和 [dependencies]
部分进行配置,以依赖于不同的板条箱,例如来自 crates.io 的板条箱。还有多种方法可以配置您对板条箱的依赖方式,例如,如果您依赖于 serde
并启用 derive
功能,它将看起来像
serde = { version = "1.0", features = ['derive'] }
Rust 1.31.0 引入了 Cargo 的一项新功能,其中您可以在此映射中指定的可选键之一是 package
,这是一种 在本地重命名板条箱 的方法。例如,如果您希望在本地使用 serde1
而不是 serde
,您可以编写
serde1 = { version = "1.0", features = ['derive'], package = "serde" }
正是添加了 package
键导致 Cargo 以不同的方式编译板条箱。此功能是在 Rust 1.26.0 中 首次实现 的,但当时它是不稳定的。然而,对于 Rust 1.25.0 及更早版本,Cargo 会忽略 package
键,并将依赖项行解释为
serde1 = { version = "1.0", features = ['derive'] }
这意味着当使用 Rust 1.25.0 及更早版本编译时,它将尝试下载 serde1
板条箱。恶意用户可以在 crates.io 上抢占 serde1
名称,使其看起来像 serde 1.0.0
,但在构建时却恶意行事。
总之,在 Rust 1.25.0 及更早版本中,忽略了在 Cargo.toml
中使用 package
键重命名依赖项。当使用 Rust 1.25.0 及更早版本时,Cargo 会忽略 package
并下载错误的依赖项,该依赖项可能在 crates.io 上被抢占,成为恶意软件包。这不仅会影响您自己编写的本地清单,还会影响发布到 crates.io 的清单。例如,如果您发布了一个依赖于 serde1
的板条箱到 crates.io,那么如果他们使用 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 直到 Cargo 0.26.0。所有未来的 Cargo 版本都不受影响。
缓解措施
我们强烈建议受影响版本的使用者将其编译器更新到最新版本。要防止此问题发生,需要将您的编译器更新到 Rust 1.26.0 或更高版本。
我们不会为 Rust 1.26.0 之前的版本发布补丁。Rust 1.19.0 到 Rust 1.25.0 的使用者可以改为应用 提供的补丁 来缓解此问题。
已经对使用 package
键发布到 crates.io 的现有板条箱进行了审计,没有证据表明此漏洞在野外被利用。我们的审计仅涵盖当前发布在 crates.io 上的板条箱:如果您在将来注意到利用此漏洞的板条箱,请不要犹豫,根据 我们的安全策略 向 [email protected] 发送电子邮件。
事件时间线
- 2019 年 9 月 18 日星期三,协调世界时 13:54 - 错误报告给 [email protected]
- 2019 年 9 月 18 日星期三,协调世界时 15:35 - 响应确认报告
- 2019 年 9 月 18 日星期三 - Cargo、Core 和 crates.io 团队协商如何最好地处理此问题
- 2019 年 9 月 19 日星期四 - 与 Elichai 确认行动计划并继续审计现有板条箱
- 2019 年 9 月 23 日星期一 - 公告草案、补丁开发、审计完成
- 2019 年 9 月 30 日星期一 - 公告发布,安全列表收到有关此问题的通知
致谢
感谢 Elichai Turkel,他发现了此错误并根据我们的 安全策略 向我们报告了此错误。