Enhancing Security in Third-Party Library Reuse Comprehensive Detection of 1-day Vulnerability through Code Patch Analysis
增强第三方库重用的安全性:通过代码补丁分析全面检测 1-day 漏洞
链接:原文链接 https://arxiv.org/abs/2411.19648

摘要—如今,软件开发迅速推进以整合新功能。为了促进这种增长,并为开发者在创建和更新软件时提供便利,重用开源软件(即第三方库重用)已成为最有效且高效的方法之一。
然而,不幸的是,由于第三方库(TPLs)的维护力度较低,重用这些库也可能引入漏洞(称为 1-day 漏洞),导致许多易受攻击的版本仍然在使用中。如果使用这些 TPLs 的软件未能检测到引入的漏洞并导致更新延迟,这将加剧安全风险。然而,复杂的代码依赖关系以及 TPL 重用的灵活性使得 1-day 漏洞的检测变得极具挑战性。
为了帮助开发者在软件开发过程中安全地重用 TPLs,我们设计并实现了一个名为 VULTURE 的高效检测工具,旨在识别因使用易受攻击的 TPLs 而产生的 1-day 漏洞。VULTURE 首先执行一种数据库创建方法 TPLFILTER,该方法利用大型语言模型(LLM)自动为目标平台构建独特的数据库。与依赖代码级相似性比较不同,VULTURE 使用基于哈希的比较方法来探索所收集的 TPLs 之间的依赖关系,并识别 TPLs 与目标项目之间的相似性。鉴于开发者既可以选择完全重用 TPLs,也可以选择自定义方式重用,VULTURE 分别进行基于版本的比较和基于代码块的分析,以捕获函数级别的细粒度语义特征。我们将 VULTURE 应用于 10 个真实项目中,以评估其在检测 1-day 漏洞方面的有效性和效率。VULTURE 成功从 178 个重用的 TPLs 中识别出 175 个漏洞。
I. 引言
随着软件如今不断发展出各种创新功能(例如,基于 AI 的分类、无人操作),由于其庞大功能之间复杂的依赖关系,软件的开发与维护变得愈加复杂且具有挑战性。开源软件(OSS)的重用使开发者能够更快地集成功能,从而促进更高效的开发和代码维护。同时,重用 OSS 支持功能的灵活开发,因为开发者既可以直接将 OSS 部署为第三方库(TPLs),也可以根据需求进行自定义部署 [46]。
然而,这种便利性也使得开发者更容易通过 TPL 重用无意中引入漏洞,这些漏洞被称为 1-day 漏洞 [21] [43]。这类安全问题通常源于以下原因:1)一些 TPL 可能不再被积极维护,导致其功能不完整或容易受到安全威胁,尤其是在漏洞被利用时;2)OSS 的去中心化特性使得跟踪所有贡献者所做的代码更改变得困难,这在重用 TPL 时增加了实施安全审查和实践的复杂性;3)TPL 并非总是按照最佳实践开发,这可能使其更加脆弱。例如,文件传输项目 MOVEit Transfer 因 2023 年 6 月发生的 SQL 注入漏洞而遭遇安全入侵,这使得所有依赖该软件的系统都面临未经授权访问的风险;因此,依赖软件需要安装修补版本以及时保护其数据 [35]。
为了探索由 TPL 重用引发的 1-day 漏洞,一些研究 [26] [28] [48] 仅通过相似性比较分析未作任何修改的重用(即完全重用),以确定目标程序是否调用了 TPL 中的功能。不幸的是,由于软件开发过程中功能性限制的存在,完全重用仅占 TPL 重用的一小部分。
这种自定义 TPL 重用的灵活性增强了功能定制能力,但同时也带来了识别 TPL 重用以及检测由 TPL 重用引发的 1-day 漏洞的挑战。尽管一些现有工具(如 V1SCAN [46] 和 MVP [51])声称能够分析自定义 TPL 部署,但这些工具只能处理简单且改动较小的自定义重用,远未能彻底解决问题。更复杂的是,开发者可能会以自定义方式修复易受攻击的 TPL 功能,而不是使用官方更新或升级整个 TPL [19]。
为了弥合上述差距,我们提出了 VULTURE,一种新颖的漏洞检测工具,旨在有效且高效地探索由 TPL 重用引发的潜在 1-day 漏洞。由于针对不同目标平台设计的 TPL 存在显著差异 [54],VULTURE 首先采用了一种相互促进的方法 TPLFILTER,通过启发式方法筛选适合特定目标平台的 TPL,从而优化现有的 OSS。它通过基于 LLM 的提交切片构建了一个多面数据库,包含所有易受攻击和已修补的 TPL。PLFILTER 并未保留每个 TPL 的所有信息(例如,项目代码、描述、修复提交),而是将每个 TPL 版本提炼为若干独立功能,并使用 LSH 算法 [25] 将这些功能转换为紧凑的数值元组。 根据 TPLFILTER 生成的 TPL 数据库,VULTURE 使用基于相似性的方法检测目标程序中的 TPL 重用,识别出重用的 TPL 及其版本。
随后,它进行双重 TPL 分析,细致检查完全重用和自定义代码重用。具体而言,VULTURE 首先进行基于版本的分析,通过识别目标项目中的易受攻击 TPL 版本来探索完全 TPL 重用。然后,它通过代码标记化和基于代码块的分析进行细粒度重构,以识别自定义 TPL 重用。为了保留语义和上下文信息,VULTURE 在从易受攻击代码过渡到修补代码的过程中,通过过程内分析生成每个代码块,收集涉及代码修改的变量信息(即值、操作和相对位置)。通过将这些代码块与目标程序进行比较,VULTURE 报告是否存在任何 1-day 漏洞,并精确定位其位置。
为了评估 TPLFILTER 和 VULTURE 的有效性,我们通过手动分析 68 个真实项目创建了一个基准,标记了 200 个 TPL 重用,并从中识别出 200 个易受攻击的重用功能。通过整合 TPLFILTER 创建的数据库,VULTURE 成功识别出 184 个易受攻击的重用功能,达到 F1 值 95.8%,而最先进的工具 V1SCAN 仅检测到 100 个易受攻击的重用功能,F1 值为 66.7%。VULTURE 不仅优于最先进的学术工具,还超越了商业工具。我们将 VULTURE 和商业检测工具 SNYK [12] 应用于大规模分析 10 个真实项目中的 TPL 重用。VULTURE 从 178 个 TPL 重用中识别出 175 个漏洞,而 SNYK 识别出 111 个漏洞,V1SCAN 仅识别出 13 个。我们的研究结果表明,TPL 的自定义适配非常普遍,约占所有重用的 55%。此外,大多数 1-day 漏洞是由于使用过时的 TPL 引发的,这一问题通常因维护不善和公共安全公告缺乏详细的修复指导而加剧。
贡献:
- 一种自动构建可扩展数据库的新方法,专为目标平台上的 TPL 分析量身定制。 我们设计了一种相互促进的方法 TPLFILTER,将关键词搜索与 LLM 结合,探索常用 TPL 及其相关的漏洞和补丁代码。所有漏洞和补丁信息被汇总以创建 TPL 漏洞数据库。
- 一种有效的 1-day 漏洞检测工具,用于发现重用的 TPL 及其潜在的已被利用的漏洞。 我们设计了 1-day 漏洞检测工具 VULTURE,该工具利用局部敏感哈希(LSH)比较和双重过程内分析,对目标程序进行语义和语法上的挖掘。它可以通过识别 TPL 所有者提供的官方补丁以及开发者创建的自定义补丁来区分易受攻击的 TPL。
- 对 TPLFILTER 和 VULTURE 进行全面评估。 我们通过与最先进的工具在真实项目上进行比较,评估了 TPLFILTER 和 VULTURE。VULTURE 从 10 个真实的物联网项目中发现了 175 个漏洞,并提供了 154 个补丁提交。
可用性。 VULTURE 的源代码和实验数据集可在以下链接获取:https://anonymous.4open.science/r/Vulture-17BC。
II. 背景
A. 第三方库重用
开发者广泛使用第三方库(TPLs)来满足不同用户的多样化需求。例如,多个 MQTT 客户端库被设计用于简化连接远程设备(如物联网设备)的部署和实施,而 zlib 则常用于管理文件压缩和解压缩。
为了识别使用的 TPLs,最先进的检测工具通常分为三个阶段运行。首先,构建一个包含已知库白名单的 TPL 数据库。这些白名单通常通过手动分析生成,并需要定期更新。在拥有数据库的基础上,检测工具随后收集目标程序中用作 TPL 重用检测目标的开源软件(OSS)的代表性特征/签名(例如,调用的函数 [30]、[48]、[49],关键字标记 [37]、[44],函数依赖关系 [18]、[27]、[31]、[42]、[53])。为了提高 TPL 重用检测的有效性,一些检测工具通过消除冗余函数和语句 [48] 或定义每个函数的重要性级别 [42]、[49] 来优化流程。接着,计算收集到的代表性特征/签名与数据库中存储的库之间的相似度得分。如果相似度得分超过预定义阈值,则确认为重用。检测重用 TPL 的主要挑战在于不同目标程序中 TPL 重用的不一致性。
TPL 数据库构建。 在缺乏统一标准的情况下,不同平台(例如,物联网固件、移动操作系统、开源软件)的开发者会定制不同的基础设施以满足特定目标。因此,TPL 提供者有时会提供专门版本的 TPL,以更好地适应特定平台。例如,CocoaMQTT [2]、Paho Android Service [10] 和 Paho MQTT C/C++ 客户端 [11] 分别是针对 iOS、Android 和嵌入式平台的 MQTT 客户端库。因此,用于重用匹配的 TPL 数据库必须具备以下特性:
- 全面性: 必须包含目标平台内常用调用的 TPL。
- 特定性: 不同平台可能有其他平台无法使用的独特库。为了避免误报,在检测过程中应排除对目标平台无关的库、不必要的项目或未作为库使用的项目。
- 可维护性: TPL 通常是为了加速开源软件的开发周期而开发的,并会定期更新以修复漏洞并集成新功能。因此,数据库中的库也应具有扩展性——以容纳新创建的库,可更新性——以包含最新版本的库,以及可追溯性——以跟踪所有先前的修订细节。
遗憾的是,现有的 TPL 数据库 [27]、[48]、[49] 未能达到必要的标准,因为它们既不够全面也不够具体,并且缺乏有效的更新机制以纳入额外的白名单。在更新这些数据库时,必须通过细致地重复所有步骤(包括库收集和冗余消除)来重建它们。这一过程耗时较长,特别是因为冗余消除通常成本较高,大约需要 100 小时 [48]、[49]。因此,亟需构建一个强大且自适应的数据库。
TPL 重用检测。 除了平台多样性之外,每个 TPL 都包含多种功能以服务于不同目的,使开发者能够选择符合其独特需求的特定 API。例如,coreMQTT [3] 提供了两个 API,MQTT_ProcessLoop() 和 MQTT_ReceiveLoop(),用于从传输接口迭代接收数据包。如果不需要保持接收端口的活跃状态,可以选择 MQTT_ProcessLoop();否则应选择 MQTT_ReceiveLoop()。因此,有必要通过将目标程序中调用的函数与库中声明的函数进行匹配来检查调用的函数。然而,这种基于相似性的判断是启发式的,并高度依赖于通过手动观察建立的阈值。高阈值可能会遗漏某些情况;而低阈值则会导致许多误报。由于基础设施的多样性,开发者可能会修改 TPL 中的一些函数以更好地适应其代码结构,而不是完全重用 TPL,这进一步复杂化了相似性比较过程。因此,采用了诸如每个 TPL 版本创建时间等附加信息作为辅助信息 [48]。单靠辅助信息可能不足以验证 TPL 和依赖软件之间的复杂依赖关系。

以图 1 中展示的实际 TPL 重用为例,它说明了 zlib、Linux、TrinityCore 和 TizenRT 之间的依赖关系以及每个项目的创建时间。具体而言,zlib 于 1995 年 5 月在 zlib.net 创建,并于 2011 年 9 月镜像到 GitHub。Linux、TrinityCore 和 TizenRT 分别重用 zlib 进行压缩和解压缩;因此,这三个项目共享了一些从 zlib 调用的通用函数。由于 zlib 最初是在其自有网站上发布的,仅在晚于 Linux 和 TrinityCore 的时间出现在 GitHub 上,因此通过函数相似性比较和创建时间排序 [48] 的验证错误地表明 TizenRT 从 Linux 和 TrinityCore 中重用了函数。
结论 1: 比较过程应通过整合充分且准确的 TPL 信息进行优化,以实现有效的 TPL 重用检测。
TPL 内部的 1-day 漏洞检测。 在开源软件(OSS)的开发周期中集成 TPL 不仅为实现常见功能提供了便利,还通过引入安全问题带来了安全和隐私隐患。其中一些漏洞源于集成了易受攻击的 TPL 版本 [16]、[28]、[46]、[50]、[58],而另一些则是由于违反了特定使用要求 [19]、[56]、[60]。1-day 漏洞通常由前者引起。
类似于 TPL 重用检测,某些易受攻击的特征需要进行语法和语义比较,以识别由重用 TPL 引入的潜在漏洞。根据重用 TPL 的类型,完全 TPL 重用通常可以通过特征比较 [19]、[50]、[58] 甚至仅通过 TPL 版本比较来进行分析。
或者,TPL 重用可以通过修改特定部分来自定义,以实现功能目标。虽然一些研究考虑了自定义重用,但它们高度依赖于广义语义分析,以确定易受攻击代码和补丁中出现的共同特征(例如,变量名 [28]、核心语句行 [46]、粗粒度函数抽象 [51])。因此报告了许多误报。因此,区分导致漏洞的根本原因的关键语句和操作对于漏洞识别至关重要。

以 ReactOS 中的 TPL 重用(如图 2 所示)为例,ReactOS 最初重用了 libjpeg-turbo 和 mbedtls 的易受攻击版本。然后,它以自定义方式修补了这些漏洞。尽管语句内容保持不变,但语句所在的行号和格式发生了变化,这种改变挑战了现有方法 [28] [46] 准确识别自定义补丁的能力。
结论 2: 选择对漏洞生成和缓解起关键作用的脆弱特征可以提高 1-day 漏洞检测的有效性和效率。
B. CVE 和提交分析
软件评估依赖于公开的漏洞和安全补丁信息,这些信息通常由 CVE [5] 和 NVD [8] 提供。然而,许多由 CVE/NVD 披露的漏洞要么附带模糊的安全补丁信息,要么完全没有补丁信息 [45]。
提交排名是一种常见的过程 [20]、[40]、[41]、[45],用于标记与安全补丁相关提交和漏洞之间的直接引用。为了识别漏洞的补丁提交,会收集与提交候选和漏洞相关的特定特征集(例如,漏洞位置、漏洞标识符)。然后,使用预训练的排名模型估算每个提交与漏洞之间的相关性。与安全补丁最相关的提交应优先考虑。然而,排名结果高度依赖于所选相关特征的质量以及从 CVE/NVD 收集的信息,这些通常是手动过程。虽然手动工作是一次性成本,但人类收集的数据质量参差不齐会影响提交排名的准确性和可靠性。鉴于 GPT-4.0 等公共大型语言模型(LLM)经过大量在线数据(包括文档、博客和论坛)的广泛训练,LLM 已经在理解自然语言的语义方面表现出高度熟练的能力 [13]。
结论 3: LLM 可以协助自然语言处理,以语义和语法的方式分析提交和 CVE 描述。它减少了手动工作量,提高了识别安全相关信息和评估代码变更影响的数据质量。
III. 概述

图 3 展示了 VULTURE 检测因重用 TPL 而引入的 1-day 漏洞的工作流程。VULTURE 包括三个阶段:TPLFILTER 构建、TPL 重用识别和 1-day 漏洞检测。
TPLFILTER 构建。 VULTURE 使用 TPLFILTER 构建一个专为目标平台量身定制的独特数据库。该数据库由两个部分组成:组件部分和漏洞部分。组件部分包含 TPL 的详细信息(例如,TPL 名称、TPL 版本和代码信息),而漏洞部分则包括每个 TPL 的先前版本和当前版本中曾经存在或当前存在的漏洞信息。
TPL 重用识别。 针对目标程序,VULTURE 进行函数级别的 TPL 重用检测。通过提取目标程序中所有函数的哈希值,VULTURE 借助基于函数的相似性比较,识别出目标程序所重用的 TPL 及其版本。为了消除因自定义 TPL 重用导致的误报,VULTURE 分析 TPL 之间的依赖关系以优化结果,并生成一份 TPL 重用报告。
1-day 漏洞检测。 由于 TPL 以两种不同方式被重用,即完全重用和自定义重用,VULTURE 分别利用基于版本的匹配和基于代码块的分析来处理每种类型的重用。通过基于版本的匹配,VULTURE 具体识别出被完全重用的函数,并通过搜索 TPL 贡献者提供的官方补丁,验证这些函数是否易受攻击。在自定义重用的情况下,VULTURE 将修改后的函数重新生成为代码块代表,并分析每个代码块内的代码修改。它可以在细粒度级别上判断这些修改是否引入了任何漏洞。由于 TPLFILTER 包含某些易受攻击 TPL 的官方补丁,VULTURE 还会根据报告的漏洞进一步提供修复建议。
IV. VULTURE
A. TPLFILTER
为了检测因 TPL 重用而引入的 1-day 漏洞,VULTURE 必须完成以下任务:1)识别目标程序中重用的 TPL;2)验证重用的 TPL 版本是否易受攻击;3)建议是否存在潜在的补丁。因此,VULTURE 需要构建一个数据库,其中包含平台上常用 TPL 及其对应的漏洞和补丁信息,作为检测参考。
1) TPL 选择: 由于不同平台上的 TPL 各不相同,VULTURE 执行 TPLFILTER 来构建一个包含特定于目标平台(例如,物联网固件、Android、iOS)的 TPL 数据库。由于大多数开源项目都在 GitHub 上维护和运行,TPLFILTER 首先从 GitHub 或现有的 TPL 数据库(如 OpenWRT [9] 和 Awesome Android [1])收集所有流行的库。为了选择特定于目标平台的 TPL,我们手动创建了一个最常用于描述目标平台的关键词列表。通过该关键词列表,TPLFILTER 进行关键词匹配,以确定每个收集到的 TPL 的标题、标签和描述是否包含指定的关键词。此外,TPLFILTER 扫描项目元数据、项目的官方网站和 README 文件,以识别非库项目的关键词(例如,系统、服务器、固件),从而排除这些项目。
2) 组件部分构建: 在数据库中,TPLFILTER 收集每个选定 TPL 的详细信息以构建组件部分。GitHub 仓库和官方网站可能提供有关 TPL 的各种信息,包括功能详情、文件名、许可证信息以及每个库的创建时间(即出生时间)。然而,我们观察到并非每个 TPL 的文件名都是唯一的,且并非所有目标程序都正式组织了许可证信息,这可能会对 TPL 重用检测的有效性产生负面影响。为此,TPLFILTER 分析每个 TPL 中声明的函数及其出生时间来构建数据库。为了提高效率,TPLFILTER 不存储函数的所有复杂细节,而是为每个函数计算哈希值并将其存储在组件部分中。
对于每个选定的 TPL,TPLFILTER 从 GitHub 克隆它们,并通过 git tag 列出所有发布的版本。为了减少在处理自定义补丁时因字符串匹配而导致的误报,TPLFILTER 使用 LSH 处理每个函数。LSH 是一种模糊哈希技术,能够以高概率将相似的输入项哈希到相同的“桶”中,从而提高数据比较的准确性 [25]。因此,TPLFILTER 分析每个 TPL 版本,并使用 ctags 提取所有函数。然后,它计算每个函数的哈希值。
同时,它执行 git log 以从提交历史中识别每个函数的出生时间。每个函数被表示为 ( f_c = <H, Birth> ),其中 ( H ) 是函数的哈希值,( Birth ) 表示其出生时间。因此,每个 TPL 版本由一组函数组成,表示为 ( F_C = {f_{c(i)} | 1 \leq i \leq n} ),其中 ( n ) 是该 TPL 版本中包含的最大函数数量。由于一个 TPL A 可能调用另一个 TPL B 的函数(即 A 依赖于 B),这种依赖关系可能导致在分析函数相似性时出现冗余比较。
尽管一些先前的工作(如 Centris [48] 和 OSSFP [49])也利用 LSH 计算哈希值,但这些工作通过哈希值相似性比较而非精确匹配来识别冗余函数。当大规模比较函数时,这种方案变得低效。
为了消除冗余比较,TPLFILTER 采用了一种基于哈希索引的消除方法,通过搜索具有相同哈希值的函数来缩小范围。具体而言,TPLFILTER 首先通过比较哈希值 ( H(i) ) 和 ( H(j) ) 识别函数 ( f_{c(i)} ) 和 ( f_{c(j)} )。在所有具有相同哈希值的函数中,它选择出生时间最早的函数,并移除其他函数。
3) 漏洞部分构建: 为了支持判断重用的 TPL 版本是否包含漏洞,TPLFILTER 收集与组件部分中每个 TPL 版本相关的所有漏洞。由于一些开发者可能自行修补漏洞而不更新 TPL 版本,TPLFILTER 评估安全补丁而非 TPL 版本,以确定漏洞是否影响目标程序。因此,TPLFILTER 收集每个已收集漏洞的安全补丁,并在漏洞部分编译这些漏洞及其各自的安全补丁。
漏洞详情收集: 由于大多数漏洞报告通常列在 CVE 和 NVD 上,VULTURE 从这些网站抓取漏洞报告。在这些报告中,每个漏洞都被分配了一个唯一的 CVE ID 用于标识,并使用 CPE(通用平台枚举)描述受影响的软件版本。
对于存储在组件部分中的每个 TPL,VULTURE 首先通过调用 NVD API 并使用关键词搜索粗略过滤包含 TPL 名称的漏洞报告。然而,漏洞描述不仅包含易受攻击库的名称,还包含受这些库影响的其他软件的名称,这使得关键词搜索不够精确。因此,VULTURE 进行基于 CPE 的匹配以过滤漏洞报告,从而实现有效的漏洞识别。具体而言,为了确定漏洞是否影响目标 TPL,它检索漏洞报告中的 CPE 信息,并检查目标 TPL 名称是否是 CPE 字符串的子字符串。如果目标 TPL 名称匹配,VULTURE 认为该漏洞影响目标 TPL,并记录相应的 CVE ID、CPE 和受影响的 TPL 版本信息。通常,CPE 通过两种方式管理易受攻击的软件版本:枚举或版本区间。对于枚举,VULTURE 直接提取所有易受攻击的版本号。对于区间指定,VULTURE 首先获取并按升序排列 TPL 的所有版本,然后确定属于特定易受攻击版本区间的起始和结束版本。
遗憾的是,我们发现一些漏洞报告编写得不够规范,因此这些漏洞可能被关键词搜索和 CPE 匹配忽略。为了解决这些问题,VULTURE 从公共数据库(包括 SNYK [12] 和 TPL 的官方网站 [7] [4])中提取额外的漏洞报告,以进行进一步的详细匹配。
安全补丁收集。 VULTURE 收集每个漏洞的安全补丁,以支持精确的 1-day 漏洞检测,并检查目标程序中重用的 TPL 是否已被修补。尽管 CVE/NVD 包含了一些漏洞的补丁信息,但很大一部分补丁信息未能及时更新或妥善维护 [6]、[36]。相比之下,GitHub 上维护的 TPL 通常会以 GitHub 提交的形式发布安全补丁,这些提交通常包括漏洞描述以及详细的代码更改。
为了有效且全面地获取漏洞补丁,VULTURE 构建了一种基于 LLM 的多切片补丁搜索方法,以定位每个漏洞的具体安全补丁。基于 CVE/NVD 维护的 CVE 描述和 GitHub 维护的每个 TPL 的仓库提交记录,VULTURE 执行以下四个步骤:
1) 基于 LLM 的描述解析: CVE/NVD 提供的漏洞详情通常包括漏洞描述(例如,漏洞类型、易受攻击的文件、易受攻击的函数、易受攻击的变量以及一些特定的脆弱特征)和描述受影响 TPL 信息的 CPE(例如,TPL 的供应商、TPL 名称和版本)。相应地,VULTURE 通过调用 GPT-3.5 来解析漏洞描述,并提取受漏洞影响的脆弱元素,即易受攻击的文件、易受攻击的函数和易受攻击的变量。
2) 基于切片的提交过滤: 由于易受攻击的 TPL 仓库可能包含大量提交,涵盖文档更改、常规错误修复、功能修改和漏洞补丁,逐一分析这些提交既耗时又容易出错。因此,VULTURE 进行基于日期的提交切片,以在粗粒度级别排除确认与漏洞无关的提交。具体而言,VULTURE 首先从漏洞描述和 CPE 信息中识别所有易受攻击的版本。由于紧接最后一个易受攻击版本之后发布的版本通常是漏洞的第一个修补版本,VULTURE 提取最后一个易受攻击版本和第一个修补版本的发布时间戳。相应地,所有在这两个时间戳之间生成的提交都被视为潜在的补丁提交。然后,它根据平均分区将潜在的补丁提交划分为多个切片(即每个切片包含 k 个提交)。在每个切片 i 中,VULTURE 计算第一个和最后一个提交之间的代码差异 ( \text{diff}_i )。如果 ( \text{diff}_i ) 包含任何脆弱元素,VULTURE 将切片 i 标记为候选切片,表明该切片中至少有一个提交包含与漏洞相关代码元素的修改。否则,它继续分析下一个切片 ( i + 1 )。
3) 候选提交选择: 在定位候选切片后,VULTURE 进行细粒度分析,以选择与漏洞相关的候选提交。它将脆弱代码与每个补丁进行比较以生成代码差异。如果代码差异包含任何脆弱元素,VULTURE 将该提交标记为候选提交,并进入步骤 (4) 进行进一步确认。
4) 基于 LLM 的补丁提交映射: VULTURE 使用 LLM 确认补丁提交。一方面,候选提交中的一些提交可能也会修改脆弱元素,但它们并非针对目标漏洞的补丁,需要 VULTURE 排除这些提交;另一方面,NVD 提供的一些 CPE 信息不准确 [24],这可能导致误报。为了解决这些问题,VULTURE 将 CVE 描述和每个候选提交(即提交描述和修改的代码)作为输入,并调用 GPT-4.0 推断 CVE 和提交是否相关。需要注意的是,这里只需要分析少量候选提交,因此 GPT-4.0 在计算相关性时的成本极低。
附录 B 中展示了一个补丁提交映射的详细示例。
B. TPL 重用识别
为了确定每个目标程序中重用了哪些 TPL,VULTURE 将数据库的组件部分作为输入,检查这些 TPL 是否被调用。它首先使用 LSH 算法生成目标程序可能使用的 TPL 候选列表。随后,通过整合附加信息进一步优化识别过程以进行确认。
1) 候选库检测: 由于 TPL 可能以完全重用或自定义方式重用,仅依赖函数名称和代码语句的匹配可能会忽略自定义情况。因此,VULTURE 利用 LSH 算法进行代码相似性分析。
它从目标程序中提取所有文件及其路径,然后逐一处理这些文件。接着,VULTURE 根据声明的函数将目标程序中的每个文件划分为目标函数片段。对于每个函数片段,它使用 Python TLSH(一种基于 LSH 的模糊匹配库)生成唯一的哈希值。每个目标函数片段 ( i ) 可以用一个二元组表示:( f_t(i) = <Hash(i), Func_path(i)> ),其中 ( Hash ) 是目标函数片段 ( i ) 的哈希值,( Func_path ) 表示定义函数片段 ( i ) 的文件路径。
VULTURE 随后计算目标函数片段与组件部分中 TPL 函数之间的相似性。对于每个目标函数片段 ( i ),VULTURE 将其与 TPL 中的每个函数 ( j ) 进行迭代比较。具体而言,它以 ( Hash(i) ) 和 ( H(j) ) 为输入,并利用 TLSH 计算函数 ( i ) 和 ( j ) 之间的相似性得分。如果相似性得分低于哈希阈值 ( T_{Hhash} ),则认为函数对 ( i ) 和 ( j ) 相似。在分析所有目标函数片段后,VULTURE 计算相似函数对的总数。当总数超过相似性阈值 ( T_{Hsim} ) 时,表明对应的 TPL 可能被使用。由于不同版本的 TPL 可能差异显著,VULTURE 将具有最多相似函数对的版本识别为 TPL 的主流版本,并捕获该 TPL 的信息(即 TPL 名称、TPL 中函数的哈希值、TPL 版本以及目标程序中重用该 TPL 的文件路径),存储到候选 TPL 列表中。需要注意的是,当多个 TPL 版本具有相同数量的相似函数对时,VULTURE 随机选择一个版本作为主流版本。VULTURE 迭代分析目标程序中的所有函数,并收集可能被重用的候选 TPL 列表。
2) 识别优化: 基于相似性的常见方法(如 Centris)可能会产生大量误报,原因包括:1)功能相似的 TPL 可能使用相同的函数;2)TPL 之间的相互依赖可能导致 TPL 之间存在高度的函数重叠。为了准确选择哪些 TPL 被重用,VULTURE 利用辅助信息(即文件路径和出生时间)来优化候选列表。
一些现有方法(如 SNYK [12])使用 TPL 许可证来识别重用,因为目标程序在重用时必须在 LICENSE 文件中或通过注释声明 TPL 许可证。然而,我们观察到这些 TPL 许可证通常书写不一致且不规范,未遵循标准。VULTURE 在使用此类信息时可能会忽略已声明的 TPL。因此,VULTURE 将目标程序中说明 TPL 重用位置的文件路径以及每个 TPL 的出生时间作为指标。通常,目标程序会将重用 TPL 的代码放置在单独的目录下,并以类似于 TPL 名称的标题命名该目录。出生时间用于定位重用函数的首次调用,从而在函数比较过程中消除冗余的 TPL 依赖关系。
为了确认重用的 TPL,VULTURE 首先将在目标程序中共享相同文件路径的 TPL 候选分组。对于同一组中的 TPL 候选,使用路径分词器根据分隔符(例如空格、反斜杠和冒号)将每个文件路径划分为标记。然后,VULTURE 将每个标记与每个 TPL 候选的名称进行比较,并计算 Jaccard 相似性得分 [34],选择具有最高 Jaccard 相似性得分的 TPL 候选作为确认的重用 TPL。需要注意的是,一个文件可能调用多个 TPL 的函数,因此几个 TPL 可能具有相同的 Jaccard 相似性得分。
VULTURE 进一步处理继承情况,即多个 TPL 共享相同的得分以定位确认的重用 TPL。首先,VULTURE 将共享相同哈希值 ( H ) 的剩余 TPL 候选归为一组,表明这些 TPL 是相关的。在每组内,VULTURE 比较每个 TPL 的出生时间,并将最早出生时间的 TPL 识别为该组的父 TPL(即目标程序中确认的 TPL)。然后移除该组中的所有其他 TPL 候选。
对于每个目标程序,VULTURE 最终生成一份包含所有确认重用 TPL 的 TPL 重用报告。
C. 1-day 漏洞检测
当 TPL 重用报告显示某个易受攻击的 TPL 版本已被重用时,VULTURE 随后确定是否有任何易受攻击的函数以完全或自定义的方式被调用。因此,VULTURE 实施了一种双层分析策略,在函数级别分别利用基于版本和基于代码块的分析来区分完全重用和自定义重用。
1) 基于版本的分析: 通过检查重用的 TPL,我们发现一些开发者可能重用了一个易受攻击的 TPL 版本,但自行修补了易受攻击的代码片段。因此,VULTURE 使用基于差异的版本分析,从三个方面检查 TPL 重用:1)TPL 重用是完全还是自定义;2)重用的 TPL 版本是否易受攻击;3)被利用的漏洞是否已被修补。
具体而言,VULTURE 首先以 TPL 重用报告为输入,提取重用的 TPL 及其版本。根据 TPL 名称和版本,它查询数据库的漏洞部分,验证重用的 TPL 版本是否与任何 CVE 报告相关联。如果识别出 CVE 报告,VULTURE 提取与 CVE 相关的易受攻击和修补代码版本,并利用 diff 定位代码差异 ( Diff_{vp} )。随后,VULTURE 分析 ( Diff_{vp} ) 以确定 ( Diff_{vp} ) 中的修改项是函数还是全局声明(例如全局变量、结构体和宏)。对于函数,VULTURE 提取并记录易受攻击和修补代码的整个函数,分别作为易受攻击函数和修补函数;对于全局声明,VULTURE 将它们记录为易受攻击和修补的全局声明。然后,在目标程序中,利用 ctags,VULTURE 将每个代码片段具体标记为函数或全局声明,并分别与易受攻击/修补的函数/声明进行比较。
因此,VULTURE 将目标程序中的 TPL 重用分为四组,并以函数级粒度处理每组,确保 TPL 中未使用的函数不会影响检测准确性:
G1:无漏洞重用。 表示目标程序重用了易受攻击的 TPL 版本,但未涉及任何易受攻击的函数或全局声明。
- 分析: 当所有目标代码片段与修补后的函数或修补后的全局声明完全相同时,VULTURE 将目标程序归类为 G1。该组中的目标程序被认为是安全的。
G2:易受攻击的全局声明重用。 表示目标程序仅重用了易受攻击的全局声明。
- 分析: 当目标代码片段中的任何全局声明与易受攻击的全局声明完全相同时,VULTURE 将目标程序归类为 G2。
- 确认: VULTURE 使用行匹配来识别易受攻击的声明。如果从易受攻击的 TPL 中删除的全局声明继续出现在目标代码片段中,VULTURE 认为已识别出漏洞。此外,当添加到修补后的 TPL 的全局声明未出现在目标代码片段中时,VULTURE 认为目标程序存在漏洞。随后识别出 1-day 漏洞。
G3:完全易受攻击的重用。 表示目标程序完全重用了 TPL 的易受攻击函数,且未提供任何补丁。
- 分析: 如果任何目标函数与易受攻击的函数相同,VULTURE 将目标程序标记为 G3。
- 确认: VULTURE 使用 TLSH 计算易受攻击函数和目标函数片段的哈希值。如果目标程序中的任何函数与易受攻击的函数具有相同的哈希值,VULTURE 认为其未修补并将其分类为 G3。随后识别出 1-day 漏洞。
G4:自定义重用。 表示目标程序以自定义方式重用了易受攻击或修补的函数。
- 分析: 如果任何目标函数与易受攻击或修补的函数相似,VULTURE 将目标程序标记为 G4。如果任何函数对的相似性得分超过 ( T_{Hsim} ),VULTURE 将目标程序分类为 G4。
- 确认: VULTURE 使用 TLSH 比较目标程序中每个函数与易受攻击函数的哈希值。由于涉及自定义重用,无法确定目标程序是否安全;因此,VULTURE 通过基于代码块的分析确认易受攻击的自定义重用。
2) 基于代码块的分析: 为了保留函数 [28] 和行匹配 [46] 所忽略的语义和语法信息,传统上使用静态分析来解决此问题,但其面临重大挑战。首先,静态分析需要可编译的代码,这存在问题,因为补丁通常以孤立的代码片段形式提供,无法直接编译。其次,静态分析需要设置广泛的编译环境,这一过程既耗时又耗费资源。
VULTURE 使用基于代码块的代码分析检查自定义重用的函数,在不依赖编译的情况下,在语义信息提取的效率和准确性之间取得平衡。对于这些自定义函数,VULTURE 验证这些自定义修改是否提供了与 TPL 贡献者发布的官方补丁相同的安全功能。具体而言,在基于代码块的分析中,一个代码块表示一组专注于特定功能的修改行。在给定函数中,同一代码块内的行要么受相同的控制结构(例如 if-else、while、for)支配,要么操作于同一组变量。这种设计保留了补丁代码中嵌入的语义含义和上下文关系,确保对自定义调整进行准确评估。
以 CVE ID、易受攻击的代码片段、修补后的代码片段、( Diff_{vp} ) 和目标代码片段作为输入,VULTURE 执行以下步骤:
代码块构建。 在重用 TPL 时,目标程序可能会更改重用代码的格式。因此,VULTURE 首先标准化所有代码片段,包括目标代码片段、易受攻击的代码和修补后的代码。根据 LLVM 编码标准 [2],VULTURE 删除不必要的实体,例如前导空格、注释和常量字符串。
标准化后,VULTURE 分别在目标代码、易受攻击代码和修补代码片段之间启动代码差异比较。比较相应生成三个代码差异(即 ( Diff_{vt} )、( Diff_{pt} ) 和 ( Diff_{vp} )),其中 ( Diff_{vt} ) 是目标代码与易受攻击代码之间的差异,( Diff_{pt} ) 是目标代码与修补代码之间的差异,( Diff_{vp} ) 是易受攻击代码与修补代码之间的差异。上述代码差异中的每一行都被视为一个独立的代码块。我们手动预定义了 40 个正则表达式,涵盖所有类型的语句(例如调用表达式、二元操作)。使用这些正则表达式,VULTURE 提取每个代码块中涉及的变量和操作。它进一步采用不相交集合并算法来识别数据依赖的代码块,当满足以下条件时:1)代码块属于同一控制块且没有嵌套控制结构,或 2)代码块共享相同变量。最终,所有相关代码块被合并,而未合并的代码块保持彼此独立。
漏洞检测。 在构建代码块后,VULTURE 使用代码块匹配来确定目标代码片段中的变量是否已被修补。最初,VULTURE 通过成对比较 ( Diff_{vt} ) 和 ( Diff_{pt} ) 中的每个代码块与 ( Diff_{vp} ) 的代码块,进行不相交检查,以确定补丁是否已应用于目标程序。如果 ( Diff_{vt} ) 和 ( Diff_{pt} ) 两组代码块都与 ( Diff_{vp} ) 共享相同的变量,VULTURE 进一步执行行匹配。如果 ( Diff_{vp} ) 中的所有行都出现在 ( Diff_{vt} ) 中,但在 ( Diff_{pt} ) 中消失,则认为该漏洞已被“修补”。否则,VULTURE 进一步执行操作匹配。当 ( Diff_{vp} ) 中的所有操作都出现在 ( Diff_{vt} ) 中,但在 ( Diff_{pt} ) 中消失时,表明该漏洞已通过自定义修改被修补。如果两种匹配条件均未满足,则认为发现了 1-day 漏洞。

图 4 展示了基于代码块检测的详细示例。顶部的代码片段 A 表示补丁代码,而底部的代码片段 B 显示了自定义补丁。
为了构建代码块,VULTURE 最初将补丁和重用代码中的每一行添加的内容视为一个独立的代码块。接下来,VULTURE 根据语义关系和上下文合并这些代码块。例如,在补丁代码片段 A 中,前四行被合并为一个代码块,因为它们共享相同的变量 ( cmaplen )。同样,最后两行被合并为另一个代码块,因为它们受同一控制块支配。
在构建代码块后,VULTURE 开始处理代码块匹配。在上述示例中,代码块 C 与代码块 E 配对,代码块 D 与代码块 F 配对。代码 B 被分类为已修补,因为尽管行匹配失败(左侧高亮行所示),但操作匹配成功(右侧高亮行所示)。这种自定义补丁的情况可能导致其他系统(如 V1SCAN)出现误报,但 VULTURE 能够准确识别补丁。
在通过基于版本和基于代码块的分析处理目标程序的所有潜在漏洞后,VULTURE 将生成一份全面的漏洞报告。该报告不仅包括漏洞的 CVE-ID,还提供数据库漏洞部分中的补丁提交 URL,以及检测过程中涉及的代码块详细信息,以便开发者进一步修补 1-day 漏洞。
V. 实验
我们从两个方面评估了 VULTURE 的性能:TPL 重用检测的准确性,以及检测由重用 TPL 引入的 1-day 漏洞的有效性。
A. 实验设置
尽管 VULTURE 可应用于任意平台进行 1-day 漏洞检测,我们在以下实验中将其应用于物联网(IoT)项目作为代表性案例。具体而言,VULTURE 从 GitHub、OpenWRT、stm32duino、awesome-cpp、awesome-c 和 mongoose-os-libs 中收集了所有流行的 C/C++ 仓库,并进行了 TPL 选择以挑选特定的 TPL。通过关键词过滤仓库后,剩下 19,057 个库。我们将这些库标记为数据库 ( DB_{kwd} )。在识别依赖库并仅保留父级 TPL 后,VULTURE 最终构建了一个包含 1,872 个 IoT 特定 TPL 的 TPL 数据库 ( DB_{iot} ),其中包括 TPL 名称、所有 TPL 版本、函数的哈希值和出生时间,存储为 ( DB_{iot} ) 的组件部分。根据收集到的 TPL,VULTURE 探索了 5,114 份 CVE 报告,其中 1,717 份 CVE 提供了 GitHub 补丁。这些 CVE 报告和补丁被存储为 ( DB_{iot} ) 的漏洞部分。
我们评估了 VULTURE 中每个组件与相应的最新技术工作的性能对比。为了评估数据库质量(第 V-B 节),我们选择了 Centris、SNYK 和 VFCFinder [20]。对于漏洞检测(第 V-C 节),我们选择了 V1SCAN、TPLite [27] 和 SNYK。虽然 MVP 也是一种 1-day 漏洞检测工具,但由于其报告的性能低于 V1SCAN,因此被排除在外。每种工具均使用截至 2024 年 4 月的最新版本实现,并遵循开发者提供的说明。
我们在一台配备 Debian GNU/Linux 12、32GB 内存和 1TB SSD 的机器上运行 VULTURE。对于补丁提交收集,我们将搜索切片大小 ( k ) 设置为 20。对于相似性比较,在手动测试后,我们将 ( T_{Hhash} ) 设置为 30,( T_{Hsim} ) 设置为 10%,以实现最佳检测结果。
B. 数据库评估
我们分别评估了数据库 ( DB_{iot} ) 中的两个部分(即组件部分和漏洞部分)。
1) 组件部分评估: 适合 TPL 重用检测的数据库必须全面、特定且可维护(参见第 II 节);因此,我们进行了两项实验,以评估 ( DB_{iot} ) 是否符合这些特性,同时确保数据库规模保持相对较小:
- 特性对比。 我们将 ( DB_{iot} ) 与最近发布的流行库数据库进行了对比 [48] [27]。
- 数据库集成。 我们将 ( DB_{iot} ) 与最先进的 TPL 重用检测工具 Centris 集成,以验证其检测性能是否得到提升。
特性对比。 我们从存储消耗、效率和可维护性三个方面,将 ( DB_{iot} ) 与 ( DB_{kwd} )、Centris 构建的数据库(即 ( DB_{centris} ))和 TPLite 构建的数据库(即 ( DB_{tplite} ))进行了对比。
对比结果列于表 I。

总计,( DB_{iot} ) 仅包含与 IoT 相关的 1,872 个库,需要 3.5 GB 的存储空间,而 ( DB_{kwd} ) 和 ( DB_{centris} ) 的存储需求是其十倍,因为它们通过随机 TPL 选择包含了大量无关库。相比之下,TPLFILTER 在构建 ( DB_{iot} ) 时有效过滤掉了大多数无关库。
在处理每个 TPL 时,尽管 ( DB_{iot} )、( DB_{kwd} ) 和 ( DB_{centris} ) 克隆一个 TPL 仓库并计算其中函数哈希值所需的时间相同,但 ( DB_{centris} ) 平均需要 115.1 秒来消除每个 TPL 内的冗余函数,而 ( DB_{iot} ) 仅需 0.1 秒即可完成去冗余。由于大多数检测工具通过相似性比较来识别重用的 TPL,数据库的准确性显著影响搜索空间和检测效率。具体而言,( DB_{iot} ) 的搜索空间小于 ( DB_{kwd} ) 和 ( DB_{centris} ),表明当使用 ( DB_{iot} ) 时,识别一个 TPL 重用所需的相似性比较要少得多。
随着 TPL 的频繁更新,用于 TPL 重用检测的数据库需要易于更新和维护。然而,更新 ( DB_{centris} ) 所需的时间超过 100 小时。相比之下,借助基于哈希索引的去冗余方法,( DB_{iot} ) 仅需几分钟即可完成更新。尽管 TPLite 也为 TPL 重用检测创建了数据库,但其数据库创建需要大量存储空间来保存过多的库细节,包括所有函数的详细信息。仅处理 1,000 个 TPL 时,其存储容量就已不堪重负,表明使用 TPLite 构建数据库并不现实。
数据库集成。 为了测试 ( DB_{iot} ) 与最新工具集成的表现,我们比较了 ( DB_{iot} ) 、( DB_{kwd} ) 和 ( DB_{centris} ) 在检测来自 GitHub 的前 10 个 C/C++ IoT 项目中的 TPL 重用情况(目标程序)。这些项目的详细信息列于附录 B。

表 II 显示了将 Centris 与三个不同数据库集成的结果。使用 ( DB_{centris} ) 时,Centris 仅识别出 71 个 TPL 重用;然而,当利用 ( DB_{iot} ) 和 ( DB_{kwd} ) 时,其性能显著提高,分别检测到 174 和 112 个 TPL 重用。值得注意的是,尽管 ( DB_{iot} ) 规模最小,但其全面性和特异性使 Centris 能够检测到比另外两个更大数据库更多的重用。
安全补丁映射至 CVE 数据库。
C. 基准漏洞检测
我们进一步评估了 VULTURE 在检测由重用 TPL 引入的 1-day 漏洞时的表现。
我们将 VULTURE 与最先进的工具 V1SCAN 进行了比较。其他工具因各种限制被排除在外。具体而言,OSSFP 并未开源,而 SNYK 需要版权和许可证信息,这与我们的基准测试不兼容。
漏洞基准。 据我们所知,目前尚无专门针对 C/C++ 程序中 1-day 漏洞的基准测试。因此,我们手动构建了一个真实的漏洞基准测试集。该基准测试包含 200 个易受攻击函数重用案例,这些案例来自 GitHub 上拥有超过 100 星标的多个仓库。这 200 个案例涵盖了 66 个 CVE 的重用。在这些案例中,45% 已修补了其所重用的 CVE,而 55% 尚未修补。此外,64% 的案例涉及自定义重用,包括函数名称修改、语句修改和操作修改。
结果审查。 结果如表 V 所示。我们将 VULTURE 与 V1SCAN 进行了比较。对于自定义重用,VULTURE 成功识别出 65 个已修补案例和 78 个未修补案例,仅产生 4 个假阴性和 12 个假阳性。相比之下,V1SCAN 识别出 35 个已修补案例和 42 个未修补案例。对于完全重用,VULTURE 识别出 19 个已修补案例和 22 个未修补案例,且没有假阴性或假阳性,而 V1SCAN 检测到 10 个已修补案例和 13 个未修补案例,并出现 1 个假阳性。总体而言,VULTURE 实现了 95.8% 的 F1 分数,显著优于 V1SCAN 的 66.7%。
经过三名计算机科学专业的博士生手动确认后,我们观察到,V1SCAN 由于其数据库的全面性有限,产生了大量假阴性。此外,它还生成了许多假阳性,这是由于其检测算法设计中的固有缺陷所致,详见两个激励示例和附录 ??。VULTURE 总共报告了 4 个假阴性和 12 个假阳性。其中,4 个假阴性和 8 个假阳性是基于代码块检测方法的固有限制导致的。基于代码块的方法只能在其各自的控制语句范围内定位修改的代码行。如果修改的行未与任何控制语句关联,则无法精确定位,从而可能导致不准确的结果。此外,另外 4 个假阳性源于基于相似性检测的局限性。如果重用的函数被大幅修改,( Hash(i) ) 和 ( H(j) ) 无法准确识别(IV-B1),导致 VULTURE 未能识别实际重用的函数。然而,这些问题在现实场景中相对少见。
2) 漏洞部分评估: 我们将 VULTURE 与最先进的 CVE 补丁映射工具 VFCFinder、常用方案 Link Matching(直接从 CVE/NVD 参考信息中收集补丁信息)[46] 和 SNYK 数据库检索 [12] 进行比较,分别评估它们的映射准确性、时间成本和空间成本。假设所有解决方案都可以直接从 CVE/NVD 收集补丁提交。
我们排除了 PatchScout [41] 和 VCMatch [45],因为这两种方法在研究中已被证明表现不如 VFCFinder [20]。
提交基准。 我们随机选择了 200 个 CVE,并使用 NVD 网站和项目提交的信息手动识别相应的补丁提交。总体而言,200 个 CVE 中有 158 个被标记为对应的补丁提交,其余 42 个 CVE 被标记为“无”,因为无法在给定的 CPE 范围内(从最后一个易受攻击版本到修复版本)手动找到其补丁提交。
映射准确性。 我们量化了每种方法识别的补丁提交数量,并手动验证了结果。

表 III 展示了每种方法识别的补丁提交数量(检测到)以及通过手动验证确认正确识别的补丁数量(确认)。此外,为了量化每种方法的整体性能,我们还考虑了它们处理标记为“无”的案例的能力,并计算了 F1 分数(F1)。如表所示,VULTURE 成功识别了最多的验证补丁提交(124 个),同时未产生任何误报。对于未识别的 34 个补丁提交,我们发现其中 33 个是由于 CVE 描述中缺乏与脆弱元素(文件、函数、变量)相关的信息,无法揭示漏洞细节。例如,NVD 中对 CVE-2007-0457 的描述为“IEEE 802.11 解析器中的未指定漏洞……”,未提供有关脆弱元素的有用信息。剩余的一个失败案例是因为 LLM(GPT-4)在第 4 步(IV-A3)中未能准确识别候选补丁提交。此类失败的情况相对较少。总体而言,在 F1 分数方面,VULTURE 在所有方法中取得了最高的 F1 分数,具有显著优势。
为防止数据偏差并确保数据分布均匀,我们将数据集分为五组,并进行了 5 折分组验证以验证 VULTURE 的性能。VULTURE 在每轮验证中分别实现了 87.5%、88.9%、88.51%、88.50% 和 86.11% 的 F1 分数,证明了其有效性。
时间和空间成本。 我们比较了 VULTURE 和 VFCFinder 的时间和空间开销。为了评估时间开销性能,我们随机选择了 50 个 CVE,这两种方法都能成功识别其补丁提交。对于空间开销,我们计算了在真实数据集上直接匹配每个 CVE 所需的平均空间消耗。

实验结果如表 IV 所示。可以看出,VULTURE 的时间开销最低(平均值和中位数均最低),空间开销也最小。在空间开销方面,VFCFinder 需要在本地克隆 GitHub 仓库以获取候选提交,这导致了显著的额外空间开销。相比之下,VULTURE 通过 GitHub API 访问候选提交,并仅在运行时将提交作为临时变量使用,不会产生额外的空间开销。
搜索空间对时间成本的影响。 识别补丁提交所需的时间成本与候选提交的数量直接相关,这是由于搜索空间的不同。我们对真实数据集中标记为补丁提交的 158 个 CVE 进行了一项实证研究,旨在揭示不同方法的时间成本如何随候选提交数量的分布而变化。
我们将候选提交数量 ( N ) 的分布分为三个范围:❶ ( 100 > N > 0 ),❷ ( 1000 > N ≥ 100 ),❸ ( N ≥ 1000 )。在总共 158 个标记的 CVE 中,提交数量的分布如下:❶ 96,❷ 54,❸ 8。此外,我们选择了涵盖三个候选提交数量范围的 9 个 CVE,分析了不同方法的时间成本并评估了其可用性。

如图 5 所示,横轴表示 CVE ID,括号内为候选提交数量;纵轴表示时间开销,单位为秒。可以看出,每种方法的时间开销与候选提交数量呈正相关。此外,随着候选提交数量的增加,VFCFinder 的时间开销显著增大;相比之下,即使候选提交数量达到数千,VULTURE 仍能将时间开销控制在几百秒以内。
CVE 数据库的安全补丁映射。
C. 基准漏洞检测
我们进一步评估了 VULTURE 在检测由重用 TPL 引入的 1-day 漏洞时的表现。
我们将 VULTURE 与最先进的工具 V1SCAN 进行了比较。其他工具因各种限制被排除在外。具体而言,OSSFP 并未开源,而 SNYK 需要版权和许可证信息,这与我们的基准测试不兼容。
漏洞基准。 据我们所知,目前尚无专门针对 C/C++ 程序中 1-day 漏洞的基准测试。因此,我们手动构建了一个真实的漏洞基准测试集。该基准测试包含 200 个易受攻击函数重用案例,这些案例来自 GitHub 上拥有超过 100 星标的多个仓库。这 200 个案例涵盖了 66 个 CVE 的重用。在这些案例中,45% 已修补了其所重用的 CVE,而 55% 尚未修补。此外,64% 的案例涉及自定义重用,包括函数名称修改、语句修改和操作修改。
结果审查。

结果如表 V 所示。我们将 VULTURE 与 V1SCAN 进行了比较。对于自定义重用,VULTURE 成功识别出 65 个已修补案例和 78 个未修补案例,仅产生 4 个假阴性和 12 个假阳性。相比之下,V1SCAN 识别出 35 个已修补案例和 42 个未修补案例。对于完全重用,VULTURE 识别出 19 个已修补案例和 22 个未修补案例,且没有假阴性或假阳性,而 V1SCAN 检测到 10 个已修补案例和 13 个未修补案例,并出现 1 个假阳性。总体而言,VULTURE 实现了 95.8% 的 F1 分数,显著优于 V1SCAN 的 66.7%。
经过三名计算机科学专业的博士生手动确认后,我们观察到,V1SCAN 由于其数据库的全面性有限,产生了大量假阴性。此外,它还生成了许多假阳性,这是由于其检测算法设计中的固有缺陷所致,详见两个激励示例和附录 ??。VULTURE 总共报告了 4 个假阴性和 12 个假阳性。其中,4 个假阴性和 8 个假阳性是基于代码块检测方法的固有限制导致的。基于代码块的方法只能在其各自的控制语句范围内定位修改的代码行。如果修改的行未与任何控制语句关联,则无法精确定位,从而可能导致不准确的结果。此外,另外 4 个假阳性源于基于相似性检测的局限性。如果重用的函数被大幅修改,( Hash(i) ) 和 ( H(j) ) 无法准确识别(IV-B1),导致 VULTURE 未能识别实际重用的函数。然而,这些问题在现实场景中相对少见。
D. 实际环境中的重用与漏洞检测
为了确保评估的稳健性,我们测试了 VULTURE 在面对真实软件时的表现。

本分析中选择的目标程序与表 II 中列出的一致。随后,我们使用 VULTURE 进行了涵盖 TPL 重用检测和 1-day 漏洞检测的全面分析。
1) TPL 重用检测: 在本实验中,我们分别使用 ( DB_{iot} ) 和 ( DB_{kwd} ) 执行 VULTURE 来检测目标程序中的重用 TPL。

表 VI 展示了检测结果。当使用 ( DB_{iot} ) 时,VULTURE 正确检测到 178 个重用的 TPL,实现了 74% 的精度;然而,在集成 ( DB_{kwd} ) 时,其精度仅为 41%。在手动检查失败案例后,我们发现 62 个失败案例中有 18 个是由 ( DB_{iot} ) 中的非库项目引起的。这些项目(如 LuatOS)本身并非库,但仍被许多其他软件重用,因此难以手动过滤。这些非库项目影响了数据库的特异性,并导致 VULTURE 错误地将它们识别为重用的 TPL,而非实际的父级库。9 个失败案例是由于 9 个 TPL 被 VULTURE 过滤掉,因为这些库在 GitHub 上并不流行(星标数 < 100)。由于预设的阈值 ( T_{Hhash} ) 和 ( T_{Hsim} ),29 个案例因高估相似性而失败。不幸的是,调整阈值可能会导致更多失败或遗漏案例。最后 6 个失败案例是由于许多 TPL 重用了流行函数,使得 VULTURE 无法准确识别实际被重用的 TPL。这些流行函数可以分为加密函数(如 ( md5Update )、( parse_hex4 ))、实用函数(如 ( hammingDistance ))和通用函数(如 ( strcpy ))。
使用 ( DB_{iot} ) 和 ( DB_{kwd} ) 的检测结果差异源于 ( DB_{kwd} ) 包含了许多非 IoT 特定库。这种缺乏特异性导致将父级 TPL 重用错误识别为子级 TPL 重用,从而产生大量误报。相比之下,( DB_{iot} ) 作为专注于 IoT 相关库的精选子集,最大限度地减少了此类错误识别并实现了更高的特异性。由于 ( DB_{centris} ) 缺少 VULTURE 所需的关键信息(例如出生时间、文件路径信息),我们未将其与 VULTURE 集成。
2) 1-day 漏洞检测: 在此,我们应用 VULTURE、V1SCAN 和 SNYK 来识别现实世界中的 1-day 漏洞。表 VII 仅突出显示了检测到漏洞数量最多的前 5 个目标程序。其余 5 个目标程序根据检测结果未发现任何漏洞。

表 VII 显示,VULTURE 是最有效的工具,识别出 175 个漏洞,并在所有测试目标中始终优于 SNYK 和 V1SCAN。相比之下,SNYK 检测到 111 个漏洞,而 V1SCAN 仅检测到 13 个。此外,VULTURE 还精确定位了需要修补的具体位置和代码语句,并为识别出的漏洞提供了 154 个 GitHub 补丁提交 URL。然而,SNYK 仅报告了 CVE ID 并提供了 59 个 GitHub 补丁提交 URL,未提供有关需要修补的具体代码的详细信息,而 V1SCAN 仅提供了 13 个 GitHub 补丁提交和有限的漏洞信息(如脆弱文件和函数名称)。
在手动验证遗漏案例时,我们观察到 SNYK 严重依赖目标程序维护的版本信息。当程序未能很好地维护此类信息(如 TizenRT)时,SNYK 将遗漏大量漏洞。在分析 V1SCAN 漏掉的 87 个漏洞时,我们发现其中 64 个是由于其数据库有限,其余则归因于其粗粒度的行匹配方法。此外,SNYK 和 V1SCAN 分别错误报告了 37 和 9 个漏洞。我们的手动检查表明,这些不准确性源于 SNYK 对基于版本检测的依赖以及 V1SCAN 的粗粒度行匹配方法。
在分析 VULTURE 漏掉但被 SNYK 和 V1SCAN 检测到的 6 个漏洞时,我们发现其中 3 个是由于缺少补丁提交(这是 VULTURE 定位补丁所必需的)。其余案例涉及广泛的代码修改,导致 VULTURE 无法配对重用的函数。
3) 时间成本: 我们评估了 VULTURE 和 V1SCAN 在检测 TPL 重用和 1-day 漏洞时的时间成本。

表 VIII 展示了时间成本。通常,即使在处理像 AliOS-Things 这样的大型程序时,VULTURE 识别所有 TPL 重用所需时间不超过 25 秒,识别单个 1-day 漏洞所需时间不到 5 秒。相比之下,V1SCAN 通常需要超过 25 秒来定位一个重用,超过 5 秒来报告一个 1-day 漏洞。在分析具有广泛 TPL 重用的程序(如 Tasmota)时,VULTURE 识别单个 1-day 漏洞需要更长时间,但 V1SCAN 超时且未报告任何结果。
E. 局限性
数据库准确性。 VULTURE 的性能高度依赖于数据库的质量。由于 VULTURE 使用脆弱元素和修补代码来识别 1-day 漏洞,NVD 提供的数据质量差或格式不一致会显著影响 VULTURE 的性能。此外,VULTURE 利用 LLM(大型语言模型)捕获脆弱元素以进行补丁识别,这使得 VULTURE 高度依赖于 LLM 的性能。尽管 LLM 在处理自然语言上下文时通常表现良好,但为了确保补丁映射的准确性,仍可能需要手动验证。否则,漏洞检测的性能可能会受到负面影响。
相似性比较的局限性。 尽管 VULTURE 避免使用函数或行匹配来识别自定义重用,但在处理涉及广泛修改的自定义重用时,所采用的 LSH(局部敏感哈希)比较仍可能带来不准确性。相似性阈值 ( T_{Hhash} ) 的设置需要根据不同的数据库和应用场景进行调整,以适应各种情况。
基于代码块分析中的数据流限制。 由于 VULTURE 通过分析代码差异及相关的变量生成代码块,这可能导致代码块内的数据流不完整,从而造成某些信息丢失。因此,在分析具有广泛代码修改的目标程序时,VULTURE 的表现较差。此外,代码块生成的准确性还取决于从每个 CVE 描述中提取的脆弱元素的识别结果。相应地,基于代码块的分析也受到 LLM 处理自然语言描述能力的影响。
VI. 相关工作
A、B 和 C 节分别介绍了与 TPL 重用检测、安全补丁收集和 TPL 漏洞检测相关的研究工作。
A. TPL 重用检测
TPL 重用检测是一项重要任务,旨在识别软件所依赖的 TPL,从而促进全面的软件维护和管理 [32]。已经提出了多种针对不同平台的检测方法 [14], [23], [27], [30], [33], [37], [44], [48], [49], [58]。
TPL 重用往往会将 TPL 中相似甚至相同的代码段引入软件中。基于此,一些研究提出了基于关键字标记的代码重用检测方法。SourcererCC [37] 利用了基于标记的检测方法,通过“标记袋”策略匹配相似的代码块。此外,CCAligner [44] 引入了代码窗口的概念,并额外考虑了编辑距离以检测大间隔的代码重用。然而,基于标记的方法在检测自定义 TPL 重用时表现较差,也无法处理交互式代码段嵌套的 TPL 问题。为了解决上述问题,开发了函数级代码重用检测方案。Woo 等人 [48] 提出了 Centris,通过哈希函数匹配 TPL 的独特部分并消除重复代码以提取函数特征。类似地,Wu 等人 [49] 开发了 OSSFP,专注于识别核心函数。然而,Jiang 等人 [27] 指出,在实际部署中,Centris 在 TPL 嵌套的情况下仍然表现不佳。为了解决这一问题,开发了 TPLite [27],它引入了函数出生时间和所在目录以构建依赖图并分析嵌套关系。
尽管如此,上述方法需要在检测之前对 TPL 之间的依赖关系进行先验分析,这意味着候选 TPL 数据库无法轻松扩展。添加任何新的 TPL 都需要重新分析所有依赖关系——这是一个极其耗时的过程。因此,随着 TPL 池和软件复杂性的不断发展,TPL 重用检测工具必须具备可维护性,这一点在 VULTURE 中得到了兼容。
B. 安全补丁收集
为了收集安全补丁,现有解决方案包括从漏洞维护平台检索补丁信息 [15], [46], [52] 和从 GitHub 仓库映射与漏洞相关的提交 [20], [38], [41], [45]。一些研究 [15], [46] 通过访问 CVE/NVD 网站并提取“超链接”字段来检索补丁链接。然而,由于 CVE/NVD 更新不及时,通过这种方法收集的补丁数量非常有限。相比之下,Tracer [52] 从多个已知来源(如 Debian 和 Red Hat)以及 CVE/NVD 收集安全补丁。然而,更新不及时的问题在所有平台上普遍存在。
为了解决上述问题,其他研究 [20], [38], [41], [45] 致力于从 GitHub 提交中识别补丁。Tan 等人 [41] 提出了 PatchScout,通过排名策略分析漏洞信息与 GitHub 提交之间的相关性。类似地,[20], [38], [45] 也开发了基于排名的方法,结合机器学习和深度学习模型(如 XGBoost [17]、CNN [29]、CodeBERT [22])提取特征。然而,基于排名的解决方案无法精确映射补丁提交,正如研究中所述,高召回率只能在 Top-N(例如 Top-5)场景中实现,这需要大量手动验证工作。此外,这些方案无法应对某些 CVE 缺少补丁提交的情况。如果 CVE/NVD 提供的 CPE 错误或补丁仅通过其他渠道发布,则会返回误报,识别出具有一定相似度的提交。
相比之下,VULTURE 根据受影响的代码元素过滤候选提交,确保排除非补丁提交;除此之外,VULTURE 利用 LLM 逻辑判断实际的补丁提交,有效解决了现有解决方案的缺陷。
C. TPL 漏洞检测
TPL 漏洞检测主要依赖于 TPL 重用检测,并与 TPL 漏洞分析相关联。ReDeBug [26] 采用基于标记的方法,通过标记级相似性比较检测重用的易受攻击代码。类似地,Kim 等人 [28] 提出了高效的 TPL 漏洞检测策略 VUDDY,基于函数比较构建基于哈希的函数指纹。Zhang 等人 [57] 设计了 FIBER,利用子图匹配追踪补丁的传播。然而,这些方法在复杂自定义 TPL 重用的情况下难以检测漏洞,限制了其在现实软件中的实用性。为了解决上述问题,Xiao 等人 [51] 提出了 MVP,提取粗粒度语义信息以识别修改后的易受攻击代码克隆。Woo 等人 [47] 提出了 Movery,基于漏洞特定代码和补丁行构建核心漏洞特征的函数指纹。除此之外,V1SCAN [46] 进一步从漏洞补丁中提取补丁行,并在检测 TPL 漏洞时通过比较补丁行进一步减少误报。然而,这些方法仍然存在局限性,在复杂的自定义重用中导致误报。具体而言,Movery 无法处理已被修补的易受攻击代码;而 V1SCAN 仅依赖于补丁行的数量而非内容,这在处理某些现实软件时几乎等同于随机判断。此外,一些研究专注于物联网固件 [58], [59]、移动软件 [19], [33], [50], [55] 和 Web 应用程序 [39] 中的 TPL 漏洞分析,提供了针对其他平台和各种编程语言的解决方案。
VULTURE 使用静态分析根据漏洞特征将代码转换为代码块。与现有方法相比,VULTURE 可以检测由自定义 TPL 重用引入的缺陷,并分析是否存在自定义补丁。此外,VULTURE 的 TPL 数据库是可维护的,使其能够适应不断发展的软件供应链环境,这是现有解决方案所缺乏的能力。
VII. 结论
本研究表明,实现准确的软件供应链安全检测需要一个综合的工具链。我们介绍了 VULTURE,它结合了数据库构建、安全补丁收集、TPL 重用检测和库漏洞检测。通过构建全面的数据库和先进的算法,VULTURE 最小化了误报并提高了检测效率。评估表明,VULTURE 显著优于最先进的工具,包括商业解决方案。尽管存在一些局限性,VULTURE 在现实场景中证明了其有效性,为开发者提供了一个强大的工具,以减轻与 TPL 重用相关的风险。
附录
A. 附录 A
在本节中,我们展示了 VULTURE 用于识别给定漏洞的补丁提交的完整过程,并以 CVE-2013-4080 为例。
CVE/NVD 提供了对 CVE-2013-4080 的描述:“Wireshark 1.8.x 版本(1.8.8 之前)中的 Assa Abloy R3 解析器的 epan/dissectors/packet-assa_r3.c 文件中的 dissect_r3_upstreamcommand_queryconfig 函数未能正确处理长度为零的项,这允许远程攻击者通过构造的数据包导致拒绝服务(无限循环、CPU 和内存消耗)。” 映射过程详细如下:
1) 基于 LLM 的描述解析。
VULTURE 分析 CVE 描述以解析脆弱元素。解析结果如下:
- 文件:
packet-assa_r3.c - 函数:
dissect_r3_upstreamcommand_queryconfig - 变量:无
2) 基于切片的提交过滤。
首先,VULTURE 执行基于日期的提交切片,以确定包含补丁提交的日期范围。根据 CVE/NVD,“wireshark-1.8.7” 是最后一个易受攻击版本,“wireshark-1.8.8” 是修复版本,将时间范围缩小到 (2013-05-17T16:41:42Z, 2013-06-07T15:49:07Z)。此期间共有 348 次提交。
接下来,VULTURE 将这些提交划分为 18 个切片,每个切片包含 20 次提交(最后一个切片仅包含 8 次提交)。它通过计算每个切片中第一次和最后一次提交之间的代码变化来分析每个切片中的代码更改,并将包含脆弱元素的切片标记为候选切片。只有第三个切片符合这一标准。
3) 候选提交选择。
VULTURE 依次分析候选切片中的 20 次提交,选择真正修改了脆弱元素的提交作为候选提交。在此步骤中,仅哈希值为 779d28d39039ada8970c910d8350fc2eb05cf00a 的提交被识别为候选提交。
4) 基于 LLM 的补丁提交映射。
通过结合 CVE 描述和候选提交,VULTURE 使用特征工程调用 LLM(GPT-4.0)分析候选提交是否是该漏洞的补丁。最终,VULTURE 成功识别出 CVE-2013-4080 的补丁提交(779d28d39039ada8970c910d8350fc2eb05cf00a)。
B. 附录 B

模拟中使用的目标项目的详细信息列于表 IX 中。“Stars” 列显示 GitHub 上的星标数量,“Lines” 列表示 C/C++ 代码的行数,“Version” 列包含访问时每个程序的提交哈希值。

356

被折叠的 条评论
为什么被折叠?



