Mingshen Sun, Yulong Zhang, Tao Wei
DEF CON China [Beta], May 2018.

Availability:

Abstract:

Fatal bugs introduced by non-memory-safe languages (C/C++/etc.) are one of the oldest yet persistent problems in computer security. To alleviate this issue, there has been an emerging trend to re-implement programs using memory-safe languages (Rust/Go/Swift/etc.). By using such languages, developers usually have an illusion that they have obtained 100% guarantees of type soundness, memory-safety, and thread safety.

However, through our assessment of a wide range of open-source projects, we found that this assumption is not correct and sometimes can lead to dangerous consequences. We collected and analyzed more than 10,000 Rust programs. All of these programs rely on libc, and at least 25% depend on extra unsafe C/C++ libraries. These libraries break Rust's memory-safety promise and also expose users to great threats. Unfortunately, the inclusion of C/C++ libraries are agnostic to developers, leaving the issue unnoticed. What's more, some of the C/C++ libraries are statically linked. This leads to fragmentation and makes it challenging to carry out a scalable patching.

Even if a program is fully developed using memory-safe languages, memory security issues can still occur. Rust allows developers to write unsafe code using "unsafe" keyword, but some libraries wrap unsafe code and re-export as "safe" functions. If developers use these "safe" functions, they are not aware of the unsafety introduced by these libraries. Moreover, we will show that some of the memory-safe languages fail to zero-out memory regions on object destruction, which can lead to secret memory leakages.

To illustrate the real-world threats, we will provide a few detailed case studies and live demos where programs developed by memory-safe languages can still be exploited via memory bugs. Finally, we will offer suggestions and provide tools for developers/users to achieve a sustainable ecosystem.

内容摘要:

由非内存安全的编程语言(例如 C 和 C++ 等)带来的致命 bug 是计算机安全史上最古老、最长久的安全问题。近年出现了使用内存安全语言(例如 Rust、Go、Swift 等)重构安全要求高的组件的趋势。但是开发者在使用这些语言的时候会有一种错觉:认为只要用这些语言编写的程序就能 100% 保证类型安全、内存安全以及线程安全。

但是我们的研究表明上述假设并不成立,并且有可能导致危险的后果。我们收集并分析了 10,000 个使用 Rust 编写的程序或库。我们发现几乎所有的 Rust 程序都依赖 libc 库,并且至少 25% 的 Rust 库都依赖其它 C/C++ 的库。这些库破坏了 Rust 的内存安全特性,暴露了一些潜在的威胁。更加不幸的是,开发者并不知道程序使用了这些 C/C++ 库,也没有注意这些威胁的存在。除此之外,因为一些静态链接的 C/C++ 库的存在,引起了库依赖的碎片化,使大规模的更新升级更有挑战。

近一步的研究表明,即使完全使用内存安全语言做开发,内存安全问题依然存在。比如,Rust 允许开发者使用“unsafe”关键字编写非内存安全的代码以绕过编译器的限制。但是,一些库使用了这些“unsafe”代码,并把这些代码重导出为“安全”的函数给其它开发者使用。其他开发者使用这些“安全”的函数的时候并不知道“非内存安全”代码的存在,埋下了内存安全的隐患。

为了说明这些威胁,我们将详细展示几个案例。这些程序使用内存安全代码编写,但是仍然有安全问题的。为了内存安全生态的可持续发展,我们提供了一些使用内存安全语言的建议,并同时给开发者提供工具检测上述问题。

BibTeX Record:

@article{sun2018unsafe,
  author = {Sun, Mingshen and Zhang, Yulong and Wei, Tao},
  title = {When Memory-Safe Languages Become Unsafe},
  journal = {DEF CON China},
  year = {2018},
}