C 不再是安全相关软件的好选择吗?

信息安全 加密 审计 C
2021-08-28 23:19:32

C 是一种坚如磐石且广泛使用的编程语言,特别是在 FOSS 社区中非常流行。

许多与安全相关的软件(例如加密库)都是用 C 编写的,并且将来可能也会用 C 编写。其主要原因之一是 C 程序的出色性能和可移植性。但关键是,即使是非常有经验的软件开发人员也无法防止像缓冲区溢出这样的错误。每年都会在非常流行和经过审查的软件中发现很多与内存管理相关的安全漏洞。

所以我的问题是:现在用 C 语言编写与安全相关的软件仍然是一个好主意吗?或者选择像 Rust、Go 这样的现代语言或更高级的语言(如 Python)不是“设计的安全性”吗?

4个回答

Linux 生态系统中的大多数软件都是用 C 编写的主要且几乎独特的原因是传统开发人员看到用 C 编写的软件,以及带有基于 C 的 API 的库,因此他们使用 C,因为这很方便。编译器已经存在,并且运行良好,因为整个操作系统都是用 C 编写的。

这些都不是说 C 语言有利于开发健壮的软件。事实上,C 在这方面非常糟糕。对于 C,开发人员必须始终对许多事情保持警惕。C 有许多陷阱随时准备在最小的错误上出现,包括:

  • 未经检查的数组访问,从而允许溢出。
  • 手动内存管理,导致释放后使用或双重释放错误,以及内存泄漏。
  • 使看似合理的表达式运行异常的可怕“未定义行为”(特别是超出可表示范围的签名操作)。
  • 转到具有不同长度的整数类型和指针的体系结构时的可移植性问题。

C真正擅长的是以下几点:

  • 与提供 C API 的现有库集交互。C 是通用语,它允许在许多平台上的软件组件之间进行互操作。

C 比较擅长的是:

  • 编写非常低级的代码(例如,通过固定的内存访问模式抵抗定时攻击的加密代码),同时试图保持一定程度的可移植性。

我的结论是,对于编写安全相关的软件来说,C 语言并不是一个好主意而且已经有很长一段时间(至少十年)了。C 在某些特定情况下仍然是合理的,特别是如果您针对嵌入式平台(不是像“智能手机”那样嵌入,而是像“智能卡”那样嵌入)。与其寻找放弃 C 的理由,不如寻找继续使用 C 的具体理由。

可以在 C 中编写安全代码。只是该语言默认情况下是不安全的必须使用额外的代码手动添加安全性(当然,这些代码本身可能包含错误)。

出于这个原因,C从来都不是安全关键软件的最佳选择。无论如何,它在 FOSS 中被使用,因为它的免费编译器在历史上几乎可以在每个平台上使用(根据定义,每个平台都支持 gcc)。

如果您不依赖于特定语言(如 C),则对安全关键软件的一般建议是使用 Ada。该语言与 C 或 C++ 处于相似的抽象级别,但默认为安全(例如:所有数组的自动边界检查),能够添加代码以关闭检查,而不是相反。

特别是,有一个名为SPARK的 Ada 子集,专为安全和安全关键软件而设计。如果您喜欢那种东西,它也可以用于软件的形式验证。

首先,对于诸如加密性能之类的事情

这是能够为数百名用户或一次只能为 10 名用户提供服务的区别。这确实具有一定的安全相关性:如果您的服务器正在挣扎,那么它们很容易被 DOS 攻击摧毁。

如果您曾经对纯 Python 代码与本机代码进行基准测试,您会惊讶于差异之大。

其次,没有 C 就没有 Python/Java无论您看到哪种“现代”语言,它都使用了大量的库。你猜怎么着,其中大部分是 C 库。

现在,如果您用这种语言编写“安全关键”库,您必须担心 1. 您自己的代码中的问题 2. 您使用的 Java/Python 代码中的问题 3. 底层 C 代码中的问题(经常出现安全问题) Java 的更新!)和 4. 下面的 C 库中的问题可能会在您不知情的情况下发生变化(例如操作系统更新)。如果您想要与安全相关的代码,请尽量减少依赖关系。

下面的 C 量是增加,而不是减少这似乎并不明显。但是numpy、tensorflow、JavaFX……这些都在底层使用了大量的C代码,因为性能原因

许多问题可以通过仔细的工程和冗长的编程来避免。例如,OSX“goto fail”错误是由程序员遵守始终使用括号的最佳实践引起的......

if (a)
  goto fail;
  goto fail;
somethingelse

在大多数语言中是一个容易错过的错误(Python 除外,对于同一个问题,您需要少两个空格),可以简单地通过冗长来避免:

if (a) {
  goto fail;
  goto fail;
}
somethingelse

似乎 python 在避免此类问题方面并不是很有帮助(事实上,Java 编译器会警告您有关无法访问的代码 - Python 不会,如果用户启用,C 编译器可以)......最终,开发人员纪律仍然是关键因素。

C 代码通常需要更加谨慎的编写;这对质量来说并不是一件坏事。主要缺点是开发速度较慢。

C 已被数百万人使用了 20 多年。它的安全漏洞,例如带有scanf()的漏洞是众所周知的,并且有文档记录,并且已经建立并经过大量测试的解决方法。

一种较新的语言,比如 perl 6 或 python 3 只使用了很短的时间,很少有人精通它们,可能存在尚未发现的安全漏洞,并且批判性审查和文档很少。

这两种较新的语言都比 C 语言“大”得多,具有更多的功能,并且可能需要 20 多年的时间才能使用所有可能的编程结构,我们可以对它们的安全性充满信心。