freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

开源加密库的大规模漏洞调查
2024-08-12 05:15:07

互联网和许多其他应用程序的安全性依赖于少数几个开源加密库:其中任何一个库的漏洞都可能威胁到大量网页流量的安全,而人们对加密软件漏洞的特征和原因还不是很了解。本文对加密库及其产生的漏洞进行了纵向分析。

在调查中,发现了这些库的复杂性与其安全性之间存在相关性,这证明了日益增长的加密代码库的潜在风险。用 C 和 C++ 编写的库中 48.4% 的漏洞是由内存安全问题引起的,这表明系统级错误是这些安全问题的主要原因。加密设计和实施问题占所有库漏洞的 27.5%,侧信道攻击占 19.4%。核心库组件在复杂程度和产生的漏洞方面存在很大差异:超过三分之一的漏洞位于 SSL/TLS 协议的实现中,这为这些库的代码安全性改进提供了可操作的证据。所有数据可以公开获取:https://github.com/jenny-blessing/cryptographic-libraries 。

0x01 简介

加密库负责保障几乎所有网络通信的安全,但同时也产生了一些臭名昭著的严重漏洞。2014年,OpenSSL的心脏出血漏洞(Heartbleed)使攻击者能够读取服务器的私有内存内容。更近期的2020年6月,GnuTLS遭受了一次严重的漏洞,允许远程攻击者被动解密网络流量。鉴于这些库的关键作用,单一漏洞可能会产生巨大的安全影响——在心脏出血漏洞披露时,多达66%的所有网站都存在漏洞。

应用密码学中的一个常见格言是:加密代码由于其复杂性本质上难以保护;人们不应该自行“开发自己的加密技术”。特别地,“复杂性是安全的敌人”这一理念在安全社区中常被引述。自从这一说法于1999年首次流行以来,它已经在关于软件安全的讨论中被反复引用,并在围绕政府加密要求中额外复杂性的争论中被多次引用。传统观点认为,系统中功能数量越多,这些功能及其与其他组件的交互包含漏洞的风险就越大。

直观地说,有许多原因导致加密代码受到其他系统所没有的漏洞的影响。如时序攻击、加密算法和协议中新的破解、使用不安全的随机源以及其他问题等等。更糟糕的是,由于处理这些独特类型的攻击的需求,可能导致代码更加错综复杂和难以理解,进而导致软件复杂性增加,审查或分析减少,最终产生漏洞。

许多常见加密库中的相当一部分代码并非纯粹的加密性质,还包括经常复杂的网络协议、数据序列化(例如X.509解析)和系统配置代码。随着行业向更新更独特的加密原语、编程语言和用例(如加密货币和零知识证明)的发展,这种分析变得越来越重要。经常被用于提高加密库安全的策略是用内存安全的语言(如 Rust)编写代码,但如果不首先系统地了解安全问题的原因,就无法评估此类提案的实用性。

本文中进行了全面的纵向分析,研究了加密库及其影响这些库的漏洞。共计检查了37个常用的加密库(详细列表见下图),并纳入了 2005 年至 2022 年 18 年间NVD数据库中报告过的 23 个库。在分析中对源于加密软件的漏洞进行了广泛的特征描述,按照根本原因和代码库内的功能位置进行分类。此外还测量了漏洞利用的生命周期和严重性,以更好地理解它们的安全影响。

image

在调查了漏洞本身的特征后,进一步研究了加密软件中这些漏洞的原因。重点关注软件复杂性与漏洞频率之间的关系,记录了每个库的代码库大小和环形复杂度(Cyclomatic Complexity,一种用于衡量程序复杂性的软件度量标准)。还对OpenSSL及其主要的Heartbleed 分支,LibreSSL和BoringSSL进行了深入的案例研究,检查了代码库是如何分化的,并量化了所做更改的安全影响。研究结果表明,虽然加密软件中 27.5% 的漏洞是与加密协议或实现直接相关的问题,但在所有库中 40.0% 的错误与内存管理有关,另外 19.4% 是侧信道攻击,表明开发人员应该将精力集中在系统级实现问题上。深入的子分类显示,552 个漏洞中只有 14 个(即 2.5%)是由于协议或密码被破坏造成的。

在能够获取位置数据的数据集中,超过 35% 的漏洞位于 SSL/TLS 协议的实现中,另外 27.9% 来自证书解析实现。加密库中漏洞的平均利用寿命为 3.88 年,为攻击者提供了相当大的利用窗口。通过分析OpenSSL的主要版本发布,发现 OpenSSL 的平均漏洞密度为每千行代码 1 个 CVE。

0x02 方法

为了研究加密软件中漏洞的原因和特征,总共从 23 个开源加密库中收集了源代码存储库和漏洞数据。首先,将加密库定义为加密原语和/或协议实现的通用集合。具体来说,排除了仅充当其他语言库桥梁的库(即wrappers)和为其它库提供接口的库,以及专注于相对小众原语(如多方计算和 zk-SNARK)的库。

A. 目标系统

根据以下要求选择要纳入研究的加密库:

1)开源:一个关键组成部分是测量特定时间点的代码库特性,因此只考虑可访问源代码的系统。

2)CVE 报告:由于使用 NVD 作为漏洞来源,因此研究中包含的所有加密库都必须至少有一个已报告的 CVE。必然会排除少数加密库,例如 libsodium 和 Ring,因为它们在 NVD 中没有记录。

image

检查的 37 个加密库中有 23 个满足这两个要求。上表包含这 23 个库及其各自的 CVE 计数。虽然列出了每个库的 CVE 计数来说明数据集的组成,但需要强调的是 NVD 中报告的绝对漏洞计数并不是系统安全性的有效衡量标准,并且上表中的列表不应被解释为安全性排名—事实上,高 CVE 计数可以表明透明度和强大的安全分析。

B. 漏洞数据源

使用由美国标准与技术研究所(NIST)管理的 NVD 作为漏洞的标准化来源,并从中构建数据集。将漏洞定义为 MITRE 维护的通用漏洞和暴露(CVE)列表中的条目。虽然单个产品错误跟踪器通常提供更详细的信息,但它不允许像 NVD 那样跨系统进行标准化或比较。

创建新的 CVE 时,NVD 会分配严重性评分(CVSS)并在将漏洞添加到数据库之前执行其他分析。从官方 NVD 网站和第三方平台 CVE Details(https://www.cvedetails.com/ )的组合中抓取 CVE 数据,因为通过 CVE Details 按产品和供应商能够检索特定系统的所有 CVE,但缺少某些 CVE 信息。

为了补充和完善 NVD 提供的数据,手动查看各个项目的 bug 跟踪器、邮件列表、博客和其他外部参考资料,以获取有关 CVE 的更详细信息(例如,补丁提交描述、特定漏洞的团队讨论等)和库随时间的功能更改。总的来说,数据集包含 NVD 在 2005 年至 2022 年(含)期间发布的加密库中的 552 个 CVE。

C. 漏洞类型分类

NVD 为每个漏洞分配一个通用弱点枚举 (CWE) ,广泛地对漏洞类型进行分类。然而,在对 CWE 标签的初步审查中,在研究背景下观察到多个问题:

1)缺少 CWE:60 个 CVE(占数据集的 10% 多一点)没有 CWE 标签。

2)过于宽泛:分配的 CWE 标签通常过于宽泛,在问题原因方面含糊不清。例如“输入验证不当”是数据集中 29 个 CVE 的 CWE 标签,代表了从缓冲区覆盖到特定密码的弱参数值,再到由于配置脚本中缺乏 shell 输入清理而导致的命令注入攻击等所有内容。事实上,2006 年的 Bleichenbacher 签名伪造攻击就包含在此类别中。

3)标签不一致:类似的问题可能被分配到语义上不同的类别,具体取决于对它们进行分类的个人,特别是对于由一系列错误组成的相对模糊的问题(例如,整数溢出导致缓冲区溢出,到它在一个 CVE 中被归类为“数字问题”,而在另一个 CVE 中被归类为“缓冲区溢出”)。这对于侧信道攻击尤其突出,共统计了 14 个不同的 CWE 来描述此类别在数据集中发现的攻击。

(1)分类法

由于官方 NVD 标签中存在大量不一致和差异,因此开发了一种针对加密软件中发现的问题定制的新分类法,并手动重新分类所有 CVE。分类法由下表的六个大类组成。这种手动标记有几个好处,能够包括 NVD 中没有标签的 CVE,它还提供了更适合加密软件的更精确的分类,包括每个类别内的子分类。具体方法如下:

类别描述示例
加密问题由于设计或实现加密原语、协议和算法(即,加密性质的源代码)中的直接缺陷而产生的漏洞。未遵循推荐的RFC实践、使用了弱或缺陷协议、协议降级攻击、使用不安全素数生成加密参数、允许错误的参数输入来构造密码(例如,一个参数应始终大于另一个参数)
内存管理由内存管理引起的漏洞,具体包括分配、读取、写入和释放数据。此类别还包括可以影响非内存安全语言的问题,如无限循环和其他内存耗尽问题。源代码未检查输入是否为空就进行访问、读取缓冲区时缺少边界检查(如从X.509证书中读取一个字段)。
侧信道攻击利用完成操作或物理硬件所需时间的变化进行的攻击,包括时序和缓存记忆攻击。非常量标量乘法、填充预言机攻击。
数值错误错误的数值计算或转换,特别是在大数算术中,这些并不特定于任何一个加密密码或算法。整数溢出、传递错误、位计算错误、不同架构上的整型大小变化。
系统问题由库与本地操作系统的交互产生的漏洞。文件存储在可写子目录中、命令注入到shell脚本中、线程安全/并发问题。
杂项其他问题。通配符字符串匹配(例如,匹配两个域名)、缺失文档,以及其他各种实现错误。

(2)漏洞生命周期

将漏洞生命周期定义为其可被攻击者利用的时间长度,即从存在缺陷的源代码发布到漏洞补丁发布的时间段。计算此生命周期的下限需要确定受影响的第一个版本的发布日期和补丁的发布日期。从 NVD 中抓取受影响的版本,并从项目安全公告中收集可用的版本。

NVD 描述在实践中通常只包括补丁版本,将受影响的版本描述为“版本 X 及之前”。在这些情况下,如果无法从项目自己的安全公告中验证这是一个基础漏洞,就将引入的版本标记为未知并将其排除在生命周期计算之外。经过彻底的工审查,共确定了四个系统(OpenSSL、GnuTLS、Mozilla NSS 和 Botan),它们在项目安全公告或错误跟踪器中一致报告初始版本和补丁版本。

一旦知道 CVE 的初始版本和补丁版本,就会确定这些版本的发布日期以计算生命周期。对于每个系统,通过手动查看各个系统网站和开发人员邮件列表来构建版本和发布日期的数据集,以查找版本发布日期。虽然大多数系统都明确发布了主要版本的发布日期,但次要版本的发布日期更难追踪,尤其是十多年前发布的版本,需要大量手动搜索各种邮件列表。在三种情况下,只能找到漏洞发布日期的月份和年份。

D. 漏洞严重性

使用NVD CVSS评分来研究跨系统的漏洞严重程度。这里有一些考虑因素,因为NVD在2015年修改了CVSS分类,创建了CVSS v3(与之前的CVSS v2相反)。由于NVD的策略是不对2015年12月20日之前发布的漏洞进行追溯评分,因此数据集中的大多数漏洞只有v2评分,而最近的漏洞只有v3评分。为了保持一致性,在计算中使用了可用的v2评分,并且只有在没有提供v2评分时才使用v3。

E. 漏洞位置

为了跟踪代码库中漏洞的位置,需要收集每个补丁提交中的文件路径。总共能够恢复 359 个 CVE 的补丁,因此拥有三分之二数据集的位置信息。如果无法获得特定漏洞的补丁提交或文件路径,就将其排除在实验之外。由于收集的文件路径来自当时的库版本,并且多年来已重构了多个项目,因此根据一般位置类别标记每个文件路径。

F. 复杂性指标

有多种机制可以近似软件复杂性。最终选择了两个特定的复杂性指标来研究不同系统的安全结果:总代码行数 (LOC,Lines of Code) 和环形复杂度,并将环形复杂度定义为系统源代码中线性独立路径的数量。这两个指标是非加密软件中漏洞的最佳复杂性预测指标之一。

1)代码行数:使用命令行工具 cloc来计算代码库中每种语言的总代码行数。在整个过程中,仅计算库的主要实现语言中的源代码行数,并排除空行、注释行和头文件。

2)环形复杂度:使用单独的命令行工具 lizard 来计算每个单独函数的循环复杂度。在跨语言比较结果时,使用 Lizard 输出的修改版本来更好地标准化结果值。具体而言,从计算中排除了单行函数(例如面向对象语言中的 getter 和 setter)。还排除了测试代码和其他不会包含在编译二进制文件中的组件。通过对所有函数取平均值来计算给定文件集的平均环形复杂度数 (CCN,cyclomatic complexity number),而不是计算每个文件的 CCN 并对所有文件求平均值。

0x04 结果

A. 漏洞特征

(1)漏洞类型

下图显示了六种主要漏洞类型各自的 CVE 计数。一般内存管理问题占 CVE 总数的 221 个,占 552 个中的 40.0%,是最大的单个类别。这包括 202 个内存安全问题(越界写入、越界读取、缓冲区大小计算不正确等)以及 19 个其他内存相关问题,例如无限递归和内存耗尽。

image

加密问题是第二大单个类别,占 27.5%。各种侧信道攻击(例如定时或内存缓存攻击)进一步产生了 19.4% 的加密库 CVE。将侧信道攻击与一般“加密问题”类别分开列出,因为它们利用的是系统物理硬件或定时和缓存访问数据的弱点,而不是加密实现中的直接缺陷,但侧信道漏洞也可以广泛地视为加密性质的漏洞。另外 7.8% 的漏洞源自数值错误(即数值计算或转换中的错误,不特定于任何一种密码或算法,例如进位传播错误或对非常大的数字进行平方),各种系统问题占 2.9%。

C/C++ 代码中的内存安全问题。前图显示了所有语言的所有库中的根本原因漏洞数据,但这里还有一个值得关注的问题:在用 C/C++ 编写的库中,有多少漏洞是由使用内存不安全的语言导致或加剧的?总共发现 512 个 C/C++ CVE 中的 248 个,即 C/C++ 库中 48.4% 的 CVE 可以通过使用其他语言来预防或缓解。

(2)加密相关漏洞

结果表明,加密软件中只有 27.5% 的 CVE 与加密设计和实施直接相关。为了验证这一趋势在各个库中是否一致(而不是由于某个特定库的数据有偏差),计算了数量最多的五个加密库中加密与非加密 CVE 的比例,发现各库的百分比一致,在 25-35% 的范围内。由于另外 19.5% 是侧信道漏洞,因此与源代码的加密性质广泛相关的漏洞总百分比为 47%,几乎占一半。

image

上表更详细地显示了加密设计和实施问题的特定子类型。最值得注意的是,只有 9.2% 的加密 CVE(“协议攻击”和“对破坏性或危险算法的支持”)是由于理论算法或协议规范中的缺陷造成的。绝大多数是由单个库实现中的各种错误引起的,特别是在 TLS 状态机逻辑和证书验证中。证书验证源代码(包括 X.509 ASN.1 解析)特别难以正确处理,实现逻辑错误产生了超过四分之一的加密问题。杂项还包括少量 CVE,由于缺乏足够的信息来做出更详细的评估。

(3)漏洞来源

加密库的哪些组件会产生大量漏洞?总共选择了 367 个 CVE,可以通过它们的补丁从而确定 CVE 在代码库中的位置。下图显示了库组件之间的 CVE 分布。 TLS/SSL 协议实现产生了超过 1/3 的 CVE,而加密和数字签名算法产生了 18.1% 的 CVE,各种原语仅产生了 3.1% 的 CVE。证书解析也值得注意,X.509 和 ASN.1 实现总共产生了约 27.9% 的 CVE。

image

(4)漏洞生命周期

下表显示了四个系统的中位数和平均可利用寿命以及样本标准差。由于只能获得四个加密图形库(共 258 个 CVE)的准确版本报告数据,因此仅计算这些系统的漏洞寿命。总体而言,加密软件中漏洞周期的中位数为 3.85 年,标准差为 4.04 年,为攻击者提供了相当大的利用窗口。事实上,由于客户经常继续使用过时的版本而不进行更新(即使在发生重大安全漏洞之后),这些计算代表了实际可利用寿命的下限。此外,我们必然只包括已发现和报告的漏洞,因此代码库中未发现的漏洞可能会进一步增加平均利用窗口。

image

(5)漏洞严重性

数据集中 CVE 的平均严重性得分为 5.37,标准差为 1.80。从定性上看,观察到库之间的漏洞严重性差异很小,这表明加密库报告的漏洞具有代表性,而不仅仅是最严重的漏洞。

B. 复杂性与安全性

(1)整体库复杂度

下图显示了 2010 年至 2022 年 12 年期间研究的所有加密库的环形复杂度。可以观察到不同系统的结构代码复杂度存在显著差异,最复杂的库(MatrixSSL,平均 CCN 为 9.0)的平均 CCN 几乎是最不复杂的库(Sodium Oxide,平均 CCN 为 1.74)的平均 CCN 的五倍。

image

基于语言的结果差异尤其值得注意:与用 Java、Python 或 Rust 编写的代码库相比,用 C 或 C++ 编写的加密库的结构复杂度明显更高。事实上,在 14 个主要用 C 或 C++ 编写的库中,只有两个(Botan 和 Nettle)始终保持与非 C 库相当的复杂度水平。

(2)特征复杂性

这些库中这种复杂性的来源是什么?要回答这个问题,总共选择了八个库中共有的特征,这些特征共同涵盖了加密库的典型组件(例如,密钥交换、证书解析、认证加密、数字签名等)。为了近似特征复杂性,不区分标准或原始的不同版本,而是选择测量中包含所有版本。例如,有些同时实现 SHA-256 和 SHA-512,而另一些只实现其中之一,而还有一些包括较旧的版本,例如 SHA-1。同样,集中测量并包括库在“TLS”下提供的所有版本的 SSL 和 TLS。在 X.509 下包括 ASN.1 解析和证书撤销逻辑,因为有些项目将这些组件存储在同一个文件中,这使得它们很难分离。

下图显示了跨库的功能复杂度的热力图,这些库实现了所选功能中的至少一个版本。在功能集中,PKCS 脱颖而出,具有始终较高的相对复杂性。其他 PKI 组件(包括 ASN.1 和 X.509 解析)也表现出高于平常的复杂性。相反,SHA 算法系列以相对于其他组件具有非常低的结构复杂性而著称。

image

(3)LOC

在研究了加密软件及其来源中的结构复杂性之后,现在要问的是复杂性会产生什么样的安全结果。这需要检查版本中引入的代码行数与引入的 CVE 数量之间是否存在相关性。为了控制漏洞报告实践的变化,不考虑不同的系统,而是对比同一系统 OpenSSL 的不同版本中引入的 CVE。此处只考虑 OpenSSL,因为它是唯一一个具有足够数量和质量的 CVE 条目的加密库,迄今为止它仍然是使用最广泛的加密库。

选择了四个 OpenSSL 版本(0.9.8、1.0.0、1.0.1 和 1.0.2),它们的发布日期大致跨越从 2005 年到 2015 年的 10 年期间。OpenSSL 0.9.8 于 2005 年 7 月发布,1.0.2 于 2015 年 1 月发布。在此时间范围内发布的版本足够旧,漏洞有足够的时间被发现,但又足够新,结果仍然与当代软件开发相关。由于 OpenSSL 平均每两到三年发布一次主要版本,因此可以纳入研究的版本数量必然有限。

对于这四个版本中的每一个,通过测量相关主要版本和最新的先前版本(在这四个情况下都是次要版本)的总体大小并取差值来近似计算版本中增加的净代码行数。所有版本的源代码均从存储在 OpenSSL 源代码存储库中的版本中获得。由于缺乏版本发布中包含的精确提交的数据,因此有必要以这种间接的测量版本中添加的 LOC,但版本与紧接在它之前的版本之间的 LOC 差异可以非常接近地估计版本的大小。

image

上表中的第 5 列给出了每个版本的 LOC 变化,平均每个版本增加了 19,921.5 行 C 代码。进一步使用 OpenSSL 项目跟踪的漏洞数据计算每个版本中引入的 CVE ,通过取第 5 列和第 6 列的比例来估算每千行代码引入的 CVE 数量。

平均而言,每添加一千行代码,OpenSSL 就会引入大约 1 个 CVE。此比率应解释为下限,因为这必然仅包括已发现的漏洞。考虑到尚未发现的漏洞,每千行代码库中存在的漏洞比率很可能更高,尽管不可能知道具体高多少。只根据净行代码差异(考虑到删除的行代码)来计算这些大小,而不是仅考虑添加的行代码,因为这样可以更完整地说明版本中所做的更改。

C. CVE报告

1)CVE 数量:加密库的 CVE 数据有多可靠? OpenSSL 的 CVE 数量远远超过任何其他加密库,在统计时间范围内发布了 203 个 CVE,而 GnuTLS 中发布的 CVE 数量排名第二,为 62 个。一个重要的问题是,这种差异是由于库之间的安全性、关注度、内部报告政策的差异还是三者的某种线性组合造成的。

在对 NVD 的手动审查中,发现 OpenSSL 项目通常被用作与加密源代码相关的漏洞的综合存储库。针对知名协议攻击(例如 Logjam)的 CVE 通常只归入两个或三个最广泛使用的库,有时只归入 OpenSSL。例如,在研究的 23 个库中,2015 年的“FREAK”协议漏洞仅归入 OpenSSL。

OpenSSL 的绝对漏洞数为 190 个 CVE,而 LibreSSL 和 BoringSS 这两个 OpenSSL 的分支在同一时间段内分别记录了 9 个和 1 个 CVE。可以确认影响 LibreSSL 和 BoringSSL 的漏洞的 NVD 计数远低于影响这些库的实际漏洞数量。这似乎在很大程度上是由于这些库的正式政策。总体而言,这一发现进一步证实了绝对漏洞计数作为项目安全性指标的不可靠性。

2)CVE 类型:虽然最初依靠 CWE 数据对剩余漏洞进行分类,但经过仔细检查后发现 CWE 标签不够一致,因此需要手动检查描述和提交,以便更准确地了解存在哪些漏洞类别。CWE 标签与加密软件中出现的问题类型不太匹配。例如,虽然 NVD 为定时侧信道攻击提供了标签(“CWE-385:隐蔽时序信道”),但此 CWE 仅用于 5 个 CVE,开发人员通常选择为定时攻击选择更通用的标签。此外,NVD 没有为利用其他环境因素的侧信道攻击提供 CWE 标签。侧信道攻击是加密软件特有的重要攻击类别,但由于缺乏标准的标签约定,这些漏洞被报告在各种通用的 CWE 标签下。在数据集中观察到了 14 个用于对侧信道攻击进行分类的独特 CWE 标签。

0x05 讨论

1)复杂性:当今许多加密库中异常高的结构复杂性使这些库更难测试和维护,这反过来对库安全产生了重大影响。在分析中甚至发现至少 11 个漏洞补丁无意中引入了新漏洞的情况(并且此计数仅包括在项目安全公告或讨论线程中指出的 CVE)。

image

上图中一个更有趣的趋势是,自 2014 年分叉以来,OpenSSL、LibreSSL 和 BoringSSL 这三个项目的规模都在逐渐增加。即使是像 LibreSSL 和 BoringSSL 那样以极简主义和注重安全为宗旨的项目,也会随着时间的推移自然积累额外的源代码和功能。虽然一些项目可能需要出于向后兼容的原因保持这种复杂性,但结果表明,在可能的情况下,开发人员需要特别注意防止这种增长,例如对代码库进行年度审核,以便在添加新密码时删除对过时或弃用的密码的支持。

2)侧信道攻击:侧信道攻击经常被库开发人员忽视,部分原因是它们经常需要物理硬件访问。例如,CryptLib 对内存缓存侧信道 CVE 提出异议,因为它“在其威胁模型中不包括侧信道攻击”。加密软件中大约 20% 的漏洞是侧信道攻击,这为开发人员提供了实证支持,使他们能够根据产生的安全威胁数量对这些类型的攻击给予一定程度的关注。

3)库内漏洞:并非所有功能组件都以相同的速率产生漏洞,超过 1/3 的漏洞是由 SSL/TLS 源代码产生的,这一事实就证明了这一点。本研究的结果为开发人员提供了实证数据,使他们能够相应地集中精力进行调试、测试和模糊测试。此外,虽然这些库的公开讨论通常集中在广为人知的 TLS/SSL 协议漏洞上,但此类攻击仅占这些库中漏洞的 1.3%。实际上,缺少边界检查比使用弱协议更有可能使库变得不安全。

4)内存安全语言:大多数加密库(尤其是使用最广泛的库)都是用 C 和/或 C++ 编写的,这一直是高性能软件的首选语言,很大程度上是因为它们允许开发人员直接控制内存分配。然而结果表明,C/C++ 库中超过一半的漏洞是由语言的内存限额导致或加剧的,其中许多内存限额非常原始。例如,在计算稍后用于确定分配多少内存的值时出现的偏差本质上是一个简单的数值错误,但这种错误可能会对非内存安全的语言造成灾难性的影响。

需要注意的是,“内存安全”语言并不是解决内存相关漏洞的灵丹妙药,而且与其名称所暗示的相反,它们会产生内存泄漏和其他问题。此外,加密实现仍需要应对许多类型的系统漏洞,例如降级攻击和各种侧信道问题,而这些问题无法仅通过使用不同的语言来解决,Rust 无法阻止这类攻击。尽管如此,用内存安全语言编写的几个较新的加密库很有前途,作为 C 语言的替代品应该认真对待。

5)不同语言复杂性差异:除了内存安全语言可以减少内存安全错误的原始数量之外,研究中用内存安全语言编写的库的循环复杂度明显低于绝大多数用 C/C++ 编写的库,这表明语言本身可能是复杂性的来源。少数 C 库能够实现非常低的复杂度,这表明这种趋势至少部分归因于某些 C 系统的软件开发实践薄弱,尽管对各种与内存相关的条件的需求也可能使 C 源代码本质上比 Python 和 Rust 更复杂。

0x06 结论

本文分析了现代加密软件库中发现的安全问题及其根本原因,包括 (1) 加密软件的漏洞特征和 (2) 各种指标与漏洞数之间的相关性。总体而言,研究结果说明在加密软件中保留过多的遗留源代码(特别是 C 或 C++ 代码)是危险的,并提供了证据说明需要注重减少这些库的增长。结果进一步表明,Rust 和 Go 等内存安全语言的兴起将大大提高安全性,开发人员应考虑在可能的情况下采用这些语言。

# CVE # openssl # 心脏滴血 # 加密库 # 漏洞管理
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录