4

Rust 生态安全漏洞总结系列 | Part 3

 2 years ago
source link: https://paper.seebug.org/1731/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Rust 生态安全漏洞总结系列 | Part 3

2021年10月08日2021年10月08日漏洞分析

作者:张汉东
原文链接:https://mp.weixin.qq.com/s/RsfEKl7FAGs2L9vXKC0rWQ
相关阅读:
Rust生态安全漏洞总结系列 | Part 1
Rust生态安全漏洞总结系列 | Part 2

本系列主要是分析RustSecurity 安全数据库库[1]中记录的Rust生态社区中发现的安全问题,从中总结一些教训,学习Rust安全编程的经验。

本期分析了下面十一个安全问题:

  • RUSTSEC-2021-0110: Vulnerability in wasmtime[2]

  • RUSTSEC-2021-0098: Vulnerability in openssl-src[3]

  • RUSTSEC-2021-0082: Unsoundness in vec-const[4]

  • RUSTSEC-2021-0093: Vulnerability in crossbeam-deque[5]

  • RUSTSEC-2021-0077: Vulnerability in better-macro[6]

  • RUSTSEC-2021-0106: Vulnerability in bat[7]

  • RUSTSEC-2021-0073: Vulnerability in prost-types[8]

  • RUSTSEC-2021-0078: Vulnerability in hyper[9]

  • RUSTSEC-2021-0072: Vulnerability in tokio[10]

  • RUSTSEC-2021-0070: Vulnerability in nalgebra[11]

  • CVE-2021-31162: Vulnerability in std[12]

看是否能给我们一些启示。

RUSTSEC-2021-0110: Vulnerability in wasmtime[13]

在 Wasmtime 中发现多个代码缺陷。包括 UAF(use-after-free)、越界读写等。

漏洞描述:

  • 漏洞类型:Vulnerability
  • 漏洞分类:memory-corruption/ memory-exposure
  • CVE 编号:CVE-2021-39216[14]、CVE-2021-39219[15]、CVE-2021-39218[16]
  • 详细:https://rustsec.org/advisories/RUSTSEC-2021-0110.html
  • 补丁:>=0.30.0
  • 关键字:use-after-free / out-of-bounds read /out-of-bounds write / Wasm/ garbage collection

背景:externref 是 WebAssembly 引用类型(Reference Types)中引入的概念,用于表示 Host 引用。

Use after free passing externrefs to Wasm in Wasmtime[17]

当从 Host 传递给 Guest externrefs 时会引发 UAF 。满足下列条件之一可触发此 Bug :

  1. 同时明确地从Host传递多个 externrefswasm 实例
  2. 通过将多个 externrefs 作为参数从 Host 代码传递给 wasm函数
  3. 从Host定义的多值返回函数中返回多个 externrefswasm

如果 WasmtimeVMExternRefActivationsTable在传入第一个externref后容量被填满,那么传入第二个externref可能会触发垃圾回收。然而,在把控制权传给Wasm之前,第一个externref是没有根(root)的,因此,如果没有其他东西持有对它的引用或以其他方式保持它的live,就会被GC回收。然后,当控制权在垃圾收集后被传递给Wasm时,Wasm可以使用第一个externref,但这时它已经被释放了。

Out-of-bounds read/write and invalid free with externrefs and GC safepoints in Wasmtime[18]

Wasmtime运行使用externrefsWasm时,存在一个无效释放和越界读写的错误。

要触发这个错误,Wasmtime需要运行使用externrefsWasm,Host 创建非空的externrefsWasmtime执行一个垃圾收集(GC),并且堆栈上必须有一个Wasm帧,它处于GC Safepoint(安全点就是指代码运行到这个地方,它的状态是确定的, GC就可以安全的进行一些操作),在这个安全点上没有 Live 的引用,这种情况下 Wasmtime 会错误地使用 GC Stack map 而非 安全点。这就会导致释放一些不应该释放的内存,以及潜在的越界读写。

Wrong type for Linker-define functions when used across two Engines[19]

Engine,是在 wasmtime 中被用于跨线程管理wasm模块的全局上下文。Linker,是用于支持模块链接的结构。

Linker::func_* 安全函数中发现了一个问题。wasmtime 不支持函数的跨 engine 使用,这可能导致函数指针的类型混乱,导致能够安全地调用一个类型错误的函数。这种情况应该 panic!

RUSTSEC-2021-0098: Vulnerability in openssl-src[20]

openssl-src[21] 是用于构建 OpenSSL 给 openssl-sys 库使用的。OpenSSL 最近又发现了很多新的安全缺陷,也记录到这里了。

具体这个漏洞是指 处理ASN.1字符串时的读取缓冲区超限问题。

漏洞描述:

ASN.1字符串在OpenSSL内部被表示为一个ASN1_STRING结构,它包含一个容纳字符串数据的缓冲区和一个容纳缓冲区长度的字段。这与普通的C语言字符串不同,后者表示为一个字符串数据的缓冲区,以NUL(0)字节结束。

虽然不是严格的要求,但使用OpenSSL自己的 "d2i "函数(和其他类似的解析函数)解析的ASN.1字符串,以及任何用ASN1_STRING_set()函数设置值的字符串,都会在ASN1_STRING结构中以NUL结束字节数。

然而,应用程序有可能直接构建有效的ASN1_STRING结构,通过直接设置ASN1_STRING数组中的 "data "和 "length "字段,不以NUL方式终止字节数组。这也可以通过使用ASN1_STRING_set0()函数来实现。

许多打印ASN.1数据的OpenSSL函数被认为ASN1_STRING字节数组将以NUL结尾,尽管这对直接构建的字符串来说是不保证的。如果应用程序要求打印一个ASN.1结构,而该ASN.1结构包含由应用程序直接构建的ASN1_STRING,而没有以NUL结束 "data "字段,那么就会发生读取缓冲区超限。

如果一个恶意行为者可以使一个应用程序直接构建一个ASN1_STRING,然后通过受影响的OpenSSL函数之一处理它,那么这个问题可能会被击中。这可能导致崩溃(造成拒绝服务攻击,DOS)。它还可能导致私人内存内容(如私人密钥或敏感明文)的泄露。

其他 OpenSSL 问题

OpenSSL 缺陷列表:https://rustsec.org/packages/openssl-src.html

RUSTSEC-2021-0082: Unsoundness in vec-const[22]

vec-const试图从一个指向常量切片的指针构造一个Vec

漏洞描述:

这个crate 违反了Rust的规则,使用起来会有危害。你不应该使用这个crate。这个crate不应该存在。它创建了不健全的抽象,允许不安全的代码伪装成安全代码。

这个crate声称要构造一个长度和容量都不为零的const Vec,但这是做不到的,因为这样的Vec需要一个来自分配器(allocator)的指针。参见:https://github.com/rust-lang/const-eval/issues/20

RUSTSEC-2021-0093: Vulnerability in crossbeam-deque[23]

crossbeam-deque中发生了数据竞争。

漏洞描述:

在受影响的版本中,队列的一个或多个任务会被弹出两次,如果在堆上分配,会导致 dobule free 和 内存泄漏。如果不是堆上分配,则会引起逻辑错误。

修复PR :https://github.com/crossbeam-rs/crossbeam/pull/726

问题是因为任务窃取相关条件判断错误导致的,是逻辑 Bug。

RUSTSEC-2021-0077: Vulnerability in better-macro[25]

better-macro 是一个假的 crate,它在 "证明一个观点",即proc-macros可以运行任意的代码。这是一个特别新颖或有趣的观察。

它目前打开的https://github.com/raycar5/better-macro/blob/master/doc/hi.md,似乎没有任何恶意的内容,但不能保证会一直如此。

这个 crate 没有任何有用的功能,不应该被使用。

#[proc_macro]
pub fn println(input: TokenStream) -> TokenStream {
    if let Ok(_) = Command::new("xdg-open").arg(URL).output() {
    } else if let Ok(_) = Command::new("open").arg(URL).output() {
    } else if let Ok(_) = Command::new("explorer.exe").arg(URL).output() {
    }
    let input: proc_macro2::TokenStream = input.into();
    let out = quote! {::std::println!(#input)};
    out.into()
}

RUSTSEC-2021-0106: Vulnerability in bat[26]

bat[27] 中存在不受控制的搜索路径元素,可能会导致非预期代码执行。

0.18.2之前的windows系统中的bat会从当前工作目录中执行名为less.exe的程序。

漏洞描述:

修复 PR:https://github.com/sharkdp/bat/pull/1724

对传入的 Path 进行了合法验证。使用的库是 grep_cli

RUSTSEC-2021-0073: Vulnerability in prost-types[29]

prost_types::TimestampSystemTime的转换可能导致溢出和恐慌。

漏洞描述:

prost-types 0.7.0中,从TimestampSystemTime的转换使用UNIX_EPOCH上的+-运算符。如果输入的Timestamp是不被信任的,这可能会溢出和恐慌,造成拒绝服务的漏洞。因为 SystimeTime 内部实现的 +- 使用 checked_add/checked_sub会发生 panic。

use prost_types::Timestamp;
use std::time::SystemTime;

SystemTime::from(Timestamp {
    seconds: i64::MAX,
    nanos: 0,
}); // panics on i686-unknown-linux-gnu (but not x86_64) with default compiler settings

SystemTime::from(Timestamp {
    seconds: i64::MAX,
    nanos: i32::MAX,
}); // panics on x86_64-unknown-linux-gnu with default compiler settings

另外,转换涉及到调用Timestamp::normalize,它使用了+-运算符。这可能会引起恐慌或环绕(wrap around,取决于编译器设置),如果应用程序被编译为溢出时恐慌,也会产生拒绝服务的漏洞。

解决问题的思路是:

Timestamp::normalize可能应该使用 saturating_{add,sub}[31] 方法,如果时间戳的nanos字段超出了范围,这可能会默默地改变时间戳,最多3秒,但这样的时间戳可以说是无效的,所以这可能是好的。

SystemTime 没有Saturating_{add,sub}方法,也没有MINMAX常数,应该再次使用 SystemTime::checked_{add,sub} 进行转换。

修复 PR:https://github.com/tokio-rs/prost/pull/439

RUSTSEC-2021-0078: Vulnerability in hyper[32]

对Content-Length进行宽松的 header 解析,可能会使请求被偷渡(走私,smuggling)。

背景:请求偷渡 不合法的请求被夹杂在合法请求中被得到处理。需要通过 content-lengthTransfer-Encoding 两个header 来构造攻击。

漏洞描述:

hyper的HTTP/1服务器代码存在一个缺陷,即错误地解析和接受带有前缀加号的Content-Length头的请求,而这一请求本应作为非法请求被拒绝。这与上游HTTP代理不解析这种Content-Length头而转发的情况相结合,可能导致 "请求偷渡("request smuggling) "或 "去同步攻击(desync attacks)"。

修复代码:https://github.com/hyperium/hyper/commit/06335158ca48724db9bf074398067d2db08613e7

需要判断 content-lenght 是不是可以正常转换为有效数位。

RUSTSEC-2021-0072: Vulnerability in tokio[33]

当用JoinHandle::abort中止一个任务时,对于 LocalSet上生成的任务不正确, 容易导致竞态条件。

漏洞描述:

>=1.5.1, <1.6.0 >=1.6.3, <1.7.0 >=1.7.2, <1.8.0 >=1.8.1

当用JoinHandle::abort中止一个任务时,如果该任务当前没有被执行,那么在调用abort的线程中,Future会被 Drop。这对于在LocalSet上生成的任务是不正确的。

这很容易导致竞态条件,因为许多项目在它们的Tokio任务中使用RcRefCell以获得更好的性能。

修复 PR:https://github.com/tokio-rs/tokio/pull/3934

RUSTSEC-2021-0070: Vulnerability in nalgebra[34]

nalgebra 库中VecStorageDeserialize实现没有保持元素数量必须等于nrows * ncols的不变性。对特制的输入进行反序列化时,可能会允许超出向量分配的内存访问。

漏洞描述:

这个缺陷是在v0.11.0(086e6e)中引入的,因为为MatrixVec增加了一个自动派生(derive)的Deserialize实现。MatrixVec后来在v0.16.13(0f66403)中被改名为VecStorage,并继续使用自动派生的Deserialize实现。

修复 PR :https://github.com/dimforge/nalgebra/pull/889

在反序列化的过程中,对 nrows.value() * ncols.value() == data.len()进行校验。

CVE-2021-31162: Vulnerability in std[35]

在 Rust 1.52.0之前的Rust标准库中,如果释放元素时出现panic ,在Vec::from_iter函数中会出现 double free。

漏洞描述:

漏洞复现代码:

use std::iter::FromIterator;

#[derive(Debug)]
enum MyEnum {
    DroppedTwice(Box<i32>),
    PanicOnDrop,
}

impl Drop for MyEnum {
    fn drop(&mut self) {
        match self {
            MyEnum::DroppedTwice(_) => println!("Dropping!"),
            MyEnum::PanicOnDrop => {
                if !std::thread::panicking() {
                    panic!();
                }
            }
        }
    }
}

fn main() {
    let v = vec![MyEnum::DroppedTwice(Box::new(123)), MyEnum::PanicOnDrop];
    Vec::from_iter(v.into_iter().take(0));
}

// Output : free(): double free detected in tcache 2

因为枚举MyEnum在 析构的时候panic,导致资源泄漏,而引发了双重 free 的问题。

修复 PR:https://github.com/rust-lang/rust/pull/84603

Vec::from_iter 中执行 forget_allocation_drop_remaining,即,忘记已经被drop的src的元素分配的内存,即便 drop 发生了 panic,也不会泄漏资源。

[1]RustSecurity 安全数据库库: https://rustsec.org/advisories/

[2]RUSTSEC-2021-0110: Vulnerability in wasmtime: https://rustsec.org/advisories/RUSTSEC-2021-0110.html

[3]RUSTSEC-2021-0098: Vulnerability in openssl-src: https://rustsec.org/advisories/RUSTSEC-2021-0098.html

[4]RUSTSEC-2021-0082: Unsoundness in vec-const: https://rustsec.org/advisories/RUSTSEC-2021-0082.html

[5]RUSTSEC-2021-0093: Vulnerability in crossbeam-deque: https://rustsec.org/advisories/RUSTSEC-2021-0093.html

[6]RUSTSEC-2021-0077: Vulnerability in better-macro: https://rustsec.org/advisories/RUSTSEC-2021-0077.html

[7]RUSTSEC-2021-0106: Vulnerability in bat: https://rustsec.org/advisories/RUSTSEC-2021-0106.html

[8]RUSTSEC-2021-0073: Vulnerability in prost-types: https://rustsec.org/advisories/RUSTSEC-2021-0073.html

[9]RUSTSEC-2021-0078: Vulnerability in hyper: https://rustsec.org/advisories/RUSTSEC-2021-0078.html

[10]RUSTSEC-2021-0072: Vulnerability in tokio: https://rustsec.org/advisories/RUSTSEC-2021-0072.html

[11]RUSTSEC-2021-0070: Vulnerability in nalgebra: https://rustsec.org/advisories/RUSTSEC-2021-0070.html

[12]CVE-2021-31162: Vulnerability in std: https://rustsec.org/advisories/CVE-2021-31162.html

[13]RUSTSEC-2021-0110: Vulnerability in wasmtime: https://rustsec.org/advisories/RUSTSEC-2021-0110.html

[14]CVE-2021-39216: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-39216

[15]CVE-2021-39219: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-39219

[16]CVE-2021-39218: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-39218

[17]Use after free passing externrefs to Wasm in Wasmtime: https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-v4cp-h94r-m7xf

[18]Out-of-bounds read/write and invalid free with externrefs and GC safepoints in Wasmtime: https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-4873-36h9-wv49

[19]Wrong type for Linker-define functions when used across two Engines: https://github.com/bytecodealliance/wasmtime/security/advisories/GHSA-q879-9g95-56mx

[20]RUSTSEC-2021-0098: Vulnerability in openssl-src: https://rustsec.org/advisories/RUSTSEC-2021-0098.html

[21]openssl-src: https://crates.io/crates/openssl-src

[22]RUSTSEC-2021-0082: Unsoundness in vec-const: https://rustsec.org/advisories/RUSTSEC-2021-0082.html

[23]RUSTSEC-2021-0093: Vulnerability in crossbeam-deque: https://rustsec.org/advisories/RUSTSEC-2021-0093.html

[24]CVE-2021-32810: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-32810

[25]RUSTSEC-2021-0077: Vulnerability in better-macro: https://rustsec.org/advisories/RUSTSEC-2021-0077.html

[26]RUSTSEC-2021-0106: Vulnerability in bat: https://rustsec.org/advisories/RUSTSEC-2021-0106.html

[27]bat: https://rustsec.org/packages/bat.html

[28]CVE-2021-36753: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-36753

[29]RUSTSEC-2021-0073: Vulnerability in prost-types: https://rustsec.org/advisories/RUSTSEC-2021-0073.html

[30]CVE-2021-36753: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-36753

[31]saturating_{add,sub}:https://doc.rust-lang.org/stable/std/time/struct.Duration.html#method.saturating_add

[32]RUSTSEC-2021-0078: Vulnerability in hyper: https://rustsec.org/advisories/RUSTSEC-2021-0078.html

[33]RUSTSEC-2021-0072: Vulnerability in tokio: https://rustsec.org/advisories/RUSTSEC-2021-0072.html

[34]RUSTSEC-2021-0070: Vulnerability in nalgebra: https://rustsec.org/advisories/RUSTSEC-2021-0070.html

[35]CVE-2021-31162:Vulnerability in std: https://rustsec.org/advisories/CVE-2021-31162.html


Paper 本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1731/


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK