如需转载请注明出处,侵权必究。
论文题目:How Long Do Vulnerabilities Live in the Code? A Large-Scale Empirical Measurement Study on FOSS Vulnerability Lifetimes
发表会议:Security 22
本文第一作者是来自德国达姆施塔特工业大学(Technical University of Darmstadt)的Nikolaos Alexopoulos博士后,其研究主要关注软件安全、匿名通信系统和去中心化计算领域中的测量问题。
概述
安全漏洞是可能被攻击者利用的软件缺陷,寻找现有漏洞并避免引入新的漏洞是安全从业者的主要目标之一。然而,漏洞会在代码仓库中存在多久?前人工作没有对这个问题进行足够深入的、大规模的研究,主要困难在于确定漏洞被引入的确切时间点。
以前,度量漏洞生命周期的方法主要有两种,一是通过手动映射漏洞贡献提交(Vulnerability contribute commit, VCC)到修复提交,但由于需要大量人工,所以研究规模有限;二是使用启发式方法来估计漏洞生命周期的下限,然而这种方法存在较大误差,需要结合数据分析和建模才能实现精确估计。
本文作者提出了一种新的基于加权平均日期的启发式方法,用于准确估计足够大规模的漏洞样本在代码中的平均存在时间。作者使用这种方法在开源软件中执行了一次大规模的测量,超越了之前研究中普遍使用的估计漏洞生命周期下限的方法,并得出了一些具有安全意义的统计结论。
背景
图 1
漏洞的生命周期是指从引入漏洞代码到修复漏洞代码的时间间隔。在版本控制系统(如git、SVN、mercurial)中,这些更改是提交的一部分,提交中包括多个更改的元数据(如,时间戳、作者),可以用来追溯代码库的完整历史。引入漏洞的提交被称为漏洞贡献提交(VCC),而用于修复漏洞的提交则称为修复提交。一个漏洞可能有多个VCC和修复提交。
图1展示了漏洞生命周期简单的阶段划分。漏洞的生命周期从引入漏洞代码开始,经历漏洞发现、公开披露、补丁发布和所有受影响的主机被修复四个阶段。但这并不是一种严格定义,各阶段或长或短,甚至某些阶段可能不存在。例如,如果安全研究人员在发现漏洞的同时向厂商进行披露,厂商就有机会可以同时公开漏洞和修复方案使第三阶段消失;对于某些严重的漏洞,可能需要静默修补,这意味着漏洞永远不会被公开披露。
研究问题
漏洞在代码中存在多久?对于不同项目或不同漏洞类型,漏洞生命周期是否相同?漏洞生命随时间增加还是减少?软件质量是否有改善的迹象,软件是否随时间推移变得更安全?回答这些问题将帮助确定项目曝光窗口的持续时间,进而确定稳定冻结的持续时间。稳定冻结即只对软件进行安全更新,不进行业务更新,以减少引入新漏洞的风险。如果漏洞生命周期长,那么稳定冻结期也需要加长,确保修复所有关键问题。
贡献
-
作者提出加权平均的启发式方法精确估计漏洞生命周期,超出了在以前的工作中普遍使用的估计下限的方法。
-
作者构建了一个包含5,914个CVE的大型数据集,涵盖11个流行开源软件,这是迄今为止最大、最完整的CVE及其修复提交的映射数据集。
-
作者在该数据集上进行漏洞生命周期的测量,得到对于软件安全具有指导意义的一些统计发现。
工作流程
数据集创建
链接CVE和VCC
作者使用人工映射CVE到VCC的数据集作为Ground Truth,用于评估和验证估计漏洞生命周期的方法。主要的数据源包括Ubuntu CVE Tracker,该数据源提供了有关Linux内核漏洞的相关数据。此外,作者还从Vulnerability History Project获取了Chromium和Apache HTTP Server的数据。考虑到其他编程语言的数据较少,作者决定将研究范围限定在C/C++代码库。作者从这些高质量的来源获得了1,171个CVE与一个或多个VCC映射的数据集。
构建项目样本
为了进行分析,作者需要选取一个大规模且具有代表性的FOSS(自由开源软件)项目样本,这些项目需要与Ground Truth数据集兼容,并提供足够的数据点供分析。为此,作者确定了以下选取原则:(a) 项目必须是开源软件,具有透明且一致的安全工作流程。(b) 项目应具有相当数量的CVE记录。为了能够对项目进行全面分析,作者只选择具有至少100个CVE的项目。(c) 项目主要应以C或C++编写。作者没有足够的数据表明方法适用于其他编程语言,因此专注于C/C++。(d) 项目的大部分CVE应与修复提交相关联,从而明确追踪到CVE与修复提交之前的关系。基于这些选取原则,将能够确保所选项目与作者的分析目标相符,并提供充足的数据来支持研究。
链接CVE和修复提交
为了分析漏洞的生命周期,作者采用了四种不同的方法将NVD中的漏洞条目与一个或多个修复提交关联起来。下面介绍这四种方法:
1. 使用自动化脚本收集修复提交中的CVE-ID,并人工分析删除无效的映射,添加未被识别的映射。
2. 收集NVD引用中的指向版本控制系统提交的链接。
3. 许多软件供应商在其开发过程中使用专用的bug跟踪系统。每个提交对应一个使用特定语法在提交消息中标记的Bug ID。因此,大多数提交可以与特定的Bug ID关联起来。另一方面,NVD条目可能包含对供应商bug跟踪系统的链接。使用正则表达式,可以从这些链接中提取Bug ID,然后将其与相应的修复提交进行匹配。
4. 使用可信第三方构建的映射数据集,作者主要采用三个第三方构建的数据集:(a) Linux内核CVE项目,(b)由Piantadosi等人手动制作的映射,(c)Debian安全跟踪器。
图 2
最终,作者得到了一个包含来自11个项目的5,914个CVE及其修复提交的数据集。图2中列出了这些CVE及其修复提交的数量,分别显示了CVE总数、至少有一个修复提交的CVE数量、修复提交总数。
从漏洞修复提交自动估计生命周期
前人工作中采用的方法
找到漏洞的VCC(引入漏洞的提交)并不简单,之前使用的一种方法是人工识别VCC。虽然这种方法能得到最准确的结果,但它不适合大规模的研究。因此,研究人员又提出了一种自动化的方法,通过git blame命令找到更改特定代码行的提交,来追溯漏洞的起源。具体做法为:对给定的修复提交的每个删除或修改的行运行该命令,在返回的多个候选VCC中选择最近的提交日期作为漏洞引入日期。这种方法具有较大误差,研究人员又提出了VCCFinder,在git blame命令的基础上,加入一个区分风险提交的分类器来指导VCC的选择。但是作者在Ground Truth数据集上评估了VCCFinder后,发现精确度仅有40%。
加权平均的启发式方法
作者提出不需要将漏洞引入时间绑定到具体的某个VCC,只需要近似确定漏洞引入的时间点。由此,通过加权(根据提交频率分配权重)平均多个可能的漏洞引入日期来实现新方法。具体步骤为(1)使用git blame -w命令将修复提交中每个可疑更改映射到VCC,(2)使用图3公式对所有可疑VCC进行加权平均后作为漏洞的引入日期,公式中n为提交数量,bi为可疑更改数量,di为日期。
图 3
测量结果
项目的漏洞生命周期
图 4
图4显示了每个项目以及整个数据集的漏洞生命周期。总体而言,漏洞在代码中存在很长时间,平均超过1,900天。不同项目的生命周期存在很大的差异,TCPDump的平均生命周期是Chromium的4倍。有多种可能的解释导致这些差异,例如更好的安全协议、代码改动等。
CVE的漏洞生命周期
图 5
图 6
图5展示了所有CVE的生命周期分布以及指数拟合曲线。图6表明指数分布适合生命周期在约4,200天以内的数据。作者采用了前人工作中提到的Kolmogorov-Smirnov检验,来统计比较指数分布与其他候选分布的拟合优度,发现指数分布在统计上更好地拟合数据。
生命周期随时间变化的趋势
图 7
为了调查漏洞生命周期随时间的变化,作者按照修复年份(最后一次修复提交的年份)对CVE进行分组,并计算每年的平均生命周期。图7显示了整个数据集以及Firefox、Chromium和Linux的漏洞生命周期随年份变化的情况。
整体来看(图7a),漏洞生命周期随着年份的增加呈现出增加的趋势,对于整个数据集,平均漏洞生命周期每年增加42.78天。
对于Chromium(图7c)和Linux(图7d),可以观察到明显的增长趋势,而对于Firefox(图7b),漏洞生命周期是稳定的,甚至存在轻微的下降趋势。
代码使用年龄
图 8
为了计算项目在特定时间点的整体代码年龄,作者采用了以下方法:对每年7月1日时的代码库中的每一行进行git blame操作,获取最后一次更改该行的时间点,将最后一次更改和7月1日的时间跨度视为该行在该年的常规代码年龄。作者计算了有漏洞生命周期数据的每年的平均代码年龄,并在图8中绘制结果,包括Firefox、Chromium、Linux和Httpd。
观察到所有项目的平均代码年龄和平均漏洞生命周期之间存在密切的相关性。除了Firefox外,所有项目的这两个指标随时间呈现增长趋势,而Firefox则略微呈下降趋势。从而得出两个观察结果,(1)漏洞生命周期低于常规代码年龄,(2)尽管对于大多数项目,漏洞生命周期和常规代码年龄之间的差距似乎随时间保持稳定,但对于某些项目(例如Chromium-图8b),差距在增加。
模糊测试工具对生命周期的影响
图 9
作者调查了模糊测试工具对漏洞生命周期的影响。内存相关的错误是模糊测试的传统目标,作者将Linux内存相关的CVE与其他漏洞类型中的Linux CVE的趋势进行对比,如图10,显示这两组CVE的生命周期趋势没有显著差异,即模糊测试工具的引入并没有显著影响漏洞生命周期。
讨论与发现
RQ1:对于不同时间和不同项目,加权平均启发式方法是否具有泛化性?
图 10
图 11
如图10,该方法的一个鲁棒性表现是其误差在低均值周围近似对称,并且几乎符合正态分布,这意味着错误会相互抵消,从而提高了方法的可靠性。另外,图11展示了加权平均的启发式方法在三个不同项目中的类似表现,证明了方法的一般适用性。
RQ2:随着时间的推移,软件是否变得更加安全?
根据作者的观察结果,可以得出以下结论:(1)没有证据支持引入并修复的新漏洞随着时间推移而减少。这意味着在软件开发过程中,即使修复了一些漏洞,仍然存在引入新漏洞的风险。因此,持续的安全更新和漏洞修复仍然是必要的。(2)漏洞的平均生命周期略短于代码库的年龄。这意味着漏洞修复能够显著减少零日攻击的窗口期。通过快速修复漏洞,可以减少潜在的攻击面和暴露时间,增加系统的安全性。(3)对于某些项目,漏洞的平均生命周期与代码库的年龄之间的差距随着时间的增加而增加。这表明这些软件项目逐渐进入成熟状态,漏洞的修复速度逐渐趋于稳定。
总结
在前人的研究中,确定漏洞引入具体时间的方法存在较大误差。为了解决这个问题,作者提出了一种加权平均的启发式方法来估计漏洞生命周期。作者构建了一个迄今为止最大的、最完整的CVE及其修复提交之间的映射数据集,并在此数据集上进行了大规模的测量,得出了一些重要的统计发现,这些发现对指导软件安全具有重要意义。
供稿:张聪聪
审稿:谈心、邬梦莹、洪赓
排版:边顾
戳“阅读原文”即可查看论文原文哦~
复旦白泽战队
一个有情怀的安全团队
还没有关注复旦白泽战队?
公众号、知乎、微博搜索:复旦白泽战队也能找到我们哦~
原文始发于微信公众号(复旦白泽战队):白泽带你读论文|How Long Do Vulnerabilities Live in the Code?