本系列主要是分析`RustSecurity` 安全数据库库[1]中记录的Rust
生态社区中发现的安全问题,从中总结一些教训,学习Rust
安全编程的经验。
本期主要是侧重于 ` Chrono`[2] 里面的一个情况比较复杂的漏洞分析。
TL;DR : 请使用 time
代替 Chrono
。
本月在 Reddit Rust
频道有人发布了一个帖子,在询问Chrono
库是否还有人在维护。之所以问出这个问题,是该贴作者看到 Rust 安全依赖报告中显式 Chrono
有一个安全问题两年了还没有被修复,所以他不知道是怎么回事。
Chrono
遇到的安全问题在 rustsec.org : RUSTSEC-2020-0159[3] 有描述, 大概内容是:
Chrono
调用 libc
的 localtime_r
,用于将时间转换为本地时间。libc
实现库中大多数都是直接调用 getenv
setenv
和 getenv
在 libc
中都不是线程安全的setenv
的健全性,Rust 的 libstd
为其添加了一个锁libstd
下使用 getenv
将是不健全的。这里面也涉及 Rust 中 std::env
的相关安全问题。目前当你在并发环境下使用 setenv
会存在数据竞争的问题,建议使用 互斥锁来处理,但只能防止 std::env
。建议不要使用 `std::env::set_var`[4]。对此问题更详细的总结参见 [同步 FFI 访问 POSIX 环境变量函数[5]](https://internals.rust-lang.org/t/synchronized-ffi-access-to-posix-environment-variable-functions/15475)
但是,直接调用 libc
的 setenv
和 getenv
是线程不安全的。
发现这个漏洞的是 `tokio-rs/io-uring`[6] 作者 quininer。
time
Chrono
的作者现身回复:
Chrono
必须支持系统本地时区(Local::now()
)等。localtime*
返回的内容相匹配。避免该漏洞有一个解决办法就是用 time
0.3 代替 chrono
最近几天 chrono
也发布了一个公告:no time for chrono[7] ,主要内容是:
chrono
用户可以切换到 time
0.3localtime_r
相当复杂,处理时区被认为是所有开发者的噩梦。time
0.3 通过移除对 localtime_r
的调用来缓解此问题。Rich Felker
(musl
的作者)有另一种观点。他认为,问题不在于调用 localtime_r
函数,而在于修改环境。环境应该是不可改变的。Time 的 0.3 版本添加了许多 API[8],它们涵盖了 Chrono
的诸多 API:
Month
类型还有一些功能仅由较新的Time
支持, Chrono
则没有:
const
函数datetime!
在编译时构造日期时间的宏non-ISO8601
表示因此,您现在可以合理地将 Chrono
替换为 Time
!
https://www.reddit.com/r/rust/comments/qamgyh/is_the_chrono_crate_unmaintained/
https://rustsec.org/advisories/RUSTSEC-2020-0159.html
https://github.com/chronotope/chrono/issues/499
https://passcod.name/technical/no-time-for-chrono.html
[1]
RustSecurity
安全数据库库: https://rustsec.org/advisories/
[2]
Chrono
: https://github.com/chronotope/chrono
[3]
rustsec.org : RUSTSEC-2020-0159: https://rustsec.org/advisories/RUSTSEC-2020-0159.html
[4]
建议不要使用 std::env::set_var
: https://github.com/rust-lang/rust/issues/90308
[5]
[同步 FFI 访问 POSIX 环境变量函数: https://internals.rust-lang.org/t/synchronized-ffi-access-to-posix-environment-variable-functions/15475
[6]
tokio-rs/io-uring
: https://github.com/tokio-rs/io-uring
[7]
no time for chrono: https://passcod.name/technical/no-time-for-chrono.html
[8]
Time 的 0.3 版本添加了许多 API: https://github.com/time-rs/time/blob/main/CHANGELOG.md#030-2021-07-30
[9]
快速检查: https://docs.rs/quickcheck