关于 C 和 C++ 的安全性,科学可以告诉我们什么(2020 年)

2021-08-03 00:27:37

在编程语言领域没有很多非常有力的实证结果。这可能是因为有大量的变量需要控制,而且研究人员可用的大多数科目都是 CS 本科生。然而,我最近发现了一个在众多代码库中复制的结果,据我所知,这使其成为该领域最可靠的发现之一:如果您有一个非常大(数百万行代码)的代码库,用内存不安全的方式编写编程语言(例如 C 或 C++),您可以预期至少 65% 的安全漏洞是由内存不安全引起的。 Android(引用):“我们的数据显示,像释放后使用、双重释放和堆缓冲区溢出等问题通常占 Chrome 和 Android 中高危安全漏洞的 65% 以上。” Android 的蓝牙和媒体组件(引用):“释放后使用 (UAF)、整数溢出和越界 (OOB) 读/写构成了 90% 的漏洞,其中 OOB 是最常见的。” iOS 和 macOS(引用):“在整个 iOS 12 中,Apple 修复了 261 个 CVE,其中 173 个是内存不安全。这是所有漏洞的 66.3%。”和“在整个 Mojave Apple 修复了 298 个 CVE,其中 213 个是内存不安全。这是所有漏洞的 71.5%。” Chrome(引用):“Chromium 项目发现我们大约 70% 的严重安全漏洞是内存安全问题。”微软(引用):“微软每年分配给 CVE 的漏洞中约有 70% 仍然是内存安全问题”

Firefox 的 CSS 子系统(引用):“如果我们有一台时间机器,并且可以从一开始就用 Rust 编写这个组件,那么 51 (73.9%) 个错误就不会发生。” Ubuntu 的 Linux 内核(引用):“过去六个月 Ubuntu 对 Linux 内核的安全更新背后的 CVE 中有 65% 是内存不安全。”这些数字与我们在 0days 中看到的被发现被利用的情况一致。这一观察结果已在由不同公司构建、开始于不同时间点并使用不同开发方法的众多非常大的代码库中重现。我不知道任何反例。它们的一个共同点是用一种内存不安全的编程语言编写:C 或 C++。基于这些证据,我准备得出结论,使用内存不安全的编程语言对安全性不利。这将是一个令人兴奋的结果!用于改进软件的经验证明的技术干预很少见。内存不安全漏洞是我们知道如何通过选择内存安全语言来完全消除的唯一类型之一。然而,我们作为理性的经验主义者来处理这个问题是至关重要的,看看这些证据是否真的值得得出内存不安全编程语言对安全不利的结论。有些漏洞只能存在于内存安全的语言中(例如,在不受信任的输入上使用 eval;eval 往往只存在于非常高级的语言中,它们都是内存安全的)所以第一组包含至少 65% 的漏洞在这些类型的代码库中,逻辑上第二组必须包含 35% 的漏洞。因此,如果我们将编程语言更改为内存安全的语言,我们至少可以消除 65% 的漏洞。但是其他集合的大小会改变吗?

我假设第二组保持相同的大小:没有理由或证据认为将 C++ 移植到内存安全语言会导致额外的 SQL 注入。我们的第三组是特定于内存安全语言的漏洞。根据我的经验,在生产代码中实际使用 eval 是非常罕见的,但它的近亲“不安全反序列化”确实发生在现实世界中。为了调查它的频率,我调查了Java 在Android 上的不安全反序列化。根据我回顾的研究,Android 作为一个整体似乎有十几个这样的。基本上每个月它都有比它一直以来的此类漏洞更多的内存不安全问题。所以我相信这个班级比我们的第一个班级小几个数量级。总之,实证研究支持这样的命题,即在这些项目中使用内存安全编程语言将导致漏洞总数的大幅减少。像所有经验论断一样,随着我们获得更多数据,这可能会被修改。你可以通过以下任一方式证明我是错的:内存不安全性漏洞的比率要低得多,或者 b) 找到具有可比规模的内存安全特定漏洞的代码库(每个版本修复了数十个)。除非你有证据,否则不要为有人可以编写 10 个假设性概​​念而烦恼数百万行 C 没有无处不在的内存不安全漏洞——这只是软件工程师的平面理论。