原文作者:Nasif Imtiaz, Aniqa Khanom, and Laurie Williams
原文标题:Investigating Security Releases of Open Source Packages
原文连接:https://arxiv.org/pdf/2112.06804.pdf
笔记作者:童话 - https://www.tonghuaroot.com/about
文章小编:[email protected]
供应链安全、开源安全、软件供应链安全
0x01 IDEA
这篇 paper 中,牵扯到的技术细节中规中矩,基础的爬虫能力和一定的数据分析能力基本够用,覆盖到主流开源软件包生态,本质上还是堆工程量的活,亮点是对开源生态中从漏洞发现到下游软件漏洞修复整个生命周期中多个时间差测量,把一些我之前认为很难用数字量化的指标给出来了,安全工程师、研发团队、开源组件的维护团队可以根据这些数字做进一步的决策。再就是针对非标准化格式数据(比如说多样的包版本号)规整与取舍,数据的有效性验证,还是比较有挑战的。
应用程序依赖存在漏洞的开源组件将会引入新的安全风险。当新的安全漏洞在一个开源组件中被发现时,开源组件的维护团队需要尽快解决该漏洞并发布新版本,本文中,我们将该过程称为 security release 。对于 security release 来说,需要具备详细的说明文档,包含尽可能少且明确的迁移指令,以方便下游应用程序可以将依赖的开源组件尽快升级至新版本,收敛安全风险。
然而,实际情况是开源组件以何种程度 follow 上述推荐的最佳实践是未知的。该研究的目的是帮助软件从业者和研究人员了解开源组件 release 安全 fix 的当前实践,以及针对 security release 的实例研究指出目前的提升空间。
本篇 paper 主要包含如下几部分内容:
分析之后我们注意到,一般在对应的 fix 代码发布四天之后会释出 security release,并且包含大约 134 行左右的代码更改。
此外,我们发现 61.5% 的 security release 的 release note 中记录了相应的 security fix 情况。
然而,Snyk 和 NVD 可能需要接近 25 天(从 release 开始计算)发布 security release 的安全公告,这将会导致延通知到依赖这些开源组件的下游研发团队。
基于上述这些发现,我们为开源组件的维护者和开源社区的管理人员提出了 4 条建议,比如说针对 security fix 采用 private fork 以及标准化、流程化的 security release 方法。
近期针对软件供应链中开源软件包的网络攻击激增,现代软件开发大量依赖开源软件包,这些依赖中的安全漏洞会为应用软件带来新的安全风险。安全研究员和 bug hunter 的 review 会在开源生态中持续发现新的安全漏洞。
发现漏洞只是解决问题的开始,一旦发现漏洞,理想的情况是尽快修复该漏洞并发布新版本,即 security release,目的是让下游应用尽快修复该漏洞。下游应用程序未及时收到该修复版本更新将会为攻击者提供了利用该漏洞的时间窗口。
因此,这些开源软件包应该遵循标准的软件开发实践,确保依赖该开源组件的下游项目可以及时了解漏洞相关的信息(例如通过发布 release note 或者在知名的漏洞数据库中发布安全公告。),并且在最精简的迁移步骤中升级至最新的 security release 版本。
理解和量化 security release 实践将有助于:
该研究的目的是帮助软件开发和研究人员通过开源软件生态理解当前的 security fix 发布实践,以及通过实际案例发掘提升空间。
如下几个为我们研究的问题,以及想要研究这些问题背后的动机。
RQ1: security fix 和相关 release(security release) 发布之间的实践差是什么?
动机:
漏洞可能通过公开或私有的方式披露,然而一旦相关 fix 的代码片段 push 进入代码仓库,相关的漏洞 fix 代码便会通过开源的方式公开。即使安全方面的 fix 没有公开讨论,研究表明,通过数据挖掘的方法去检测安全 fix 是可能的。这些 fix 代码将会给攻击者提供更多的信息用于设计相应的漏洞利用代码。(注:说到这里就不得不提到 Log4j 这次的漏洞修复了,JNDI Expoit 在 Apache Jira Issue 里头躺了半个月。)
但是知道包含安全 fix 的代码 release 之前,依赖该开源组件的应用程序并不能及时进行修复,存在被漏洞利用的风险,这就为攻击者创造了一个机会窗口。因此,我们在历史的 security releases 中量化分析 fix-to-release 延迟。
RQ2:安全 fix 如何记录在 release note 中?
动机:
一旦安全 fix 包含在 release 中,需要更新漏洞数据库,以及通知对应的下游项目。据研究表明:研发人员更有可能采用不需要大量开发工作,有据可查、明确指示的安全 fix。(白话讲就是修复建议说清楚,当前面临了啥风险,需要怎么解决,解决该问题的潜在风险以及对应的应对策略。)
因此我们调查伴随着 release note(随每个版本更新分发的正式文档,解释新版本中的显著变化) 的 security release ,定性分析 release note 中记录了哪些包含关于对应安全 fix 的信息。
RQ3:security release 的代码更改特征(大小和 semantic versioning )
动机:
接到漏洞修复通知后,应用程序需要将依赖组件更新到修复后的版本。迁移更新流程通常包括如下几个部分:
以前的研究发现,研发人员更乐于更新在新的 release 中只包含 security fix 的代码。(即安全性更新,不与功能性更新重叠的情况。)但是,实际情况是,开源软件组件在进行安全更新时通常会包含一些其他不相关的功能性代码。因此我们定量分析 security release 中的代码改变情况。
我们假设较大的代码更改中也包含了与安全更新无关的功能性更新。我们还研究了这些 release 的 semantic versioning (SemVer),因为开源软件包的维护者通常使用 SemVer 格式来指示已进入新 release 的更改类型以及它可能需要的潜在迁移工作量。
RQ4:security release 和漏洞数据库(Snyk 和 NVD)中发布漏洞公告的时间差
动机:
应用程序可能会采用诸如 Dependabot 之类的 SCA 工具,用于获取第三方依赖依赖漏洞的通知。SCA 利用 NVD、Snyk 这类漏洞数据库,跟踪开源软件包中的漏洞数据并通知对应的应用程序研发团队。
然而,此前有研究表明, 不同的 SCA 工具的分析结果可能是不同的,导致使用 SCA 工具的项目在 security release 可用时可能没有意识到漏洞(延迟通知),甚至根本没有收到通知(漏报)。因此,我们定量分析了两个流行漏洞数据库 Snyk 和 NVD 的 security release 和安全公告之间的时间延迟,以了解依赖这两个数据库的 SCA 工具的通知延迟。
在这篇 paper 中,我们研究了跨越 7 个软件包生态系统(相当于主流编程语言的主要生态系统)的 security release:Composer (PHP)、Go (Go)、Maven (Java)、npm (JavaScript)、NuGet (.NET framework: C#、F#、Visual Basic)、pip (Python)、RubyGems (Ruby)。
我们采用混合方法来回答我们的研究问题,主要贡献包括:
上图展示了开源软件包中的安全 fix 如何可用于下游项目以及可能出现延迟窗口的 timeline。(注:还是拿 Log4shell 这个漏洞来举例,在安全 fix 代码提交半个月后才 release 新版本,这期间下游项目想要 fix 该漏洞,成本还是相当高的。至于 SCA 漏洞库更新漏洞公告,那就更晚了。)
paper 中提到一些有意思的观点,也是业界普遍存在的痛点,比如研发团队为什么没有及时升级存在漏洞的直接、间接依赖,安全团队在依赖管理过程中应该扮演什么样的角色等。
在数据收集阶段,漏洞公告的数据源主要来自 Snyk 和 NVD,其中 Snyk 中包含了一些没有 CVE 编号的漏洞。
最后的数据集包含 4377 个安全公告,覆盖来自 2217 个开源软件包的 4812 个 security release。开源软件包可能在同一段时间内维护多个分支(比如说 1.x.x 或 2.x.x),并且为这些维护的分支分别 push 安全 fix。此外,一个单独的 release 可能包含多条漏洞公告。
在我们的数据集中,1231 条漏洞公告(28.1 %),超过一个 security release,738 条 release(15.3 %)包含超过一条以上的安全 fix 公告。
对于 RQ1 和 RQ3 作者团队采用了保守自动化的方法识别安全公告的 fix commit 和 security release 中的代码变更,并对收集到的数据进行准确性分析。对于 RQ2,采用随机抽样的数据子集进行了手动分析。
在 RQ3 的代码改变情况的测量中,有一些比较有意思的 case:
在 security release 中存在源代码未改变的情况,这种情况主要出现在 Go 生态中,Go packages 的代码仓库通常包含许多遵循单一版本控制方案的相关 packages(modules,在 Go 生态中通常称之为 modules)。因此,当 modules 一起使用时,可以通过更改相关 modules 中的代码来修复 Go modules 中的漏洞。
还有一些诸如配置文件中依赖版本号的修改,yaml 数据格式文件中内容的修改等:
fix-to-release 延迟部分,重点关注两个问题:
不同开源软件生态下的 fix-to-release 延迟情况:
作者也提到了这个观点,开源软件包的维护者在提交相关 fix 代码之后,延迟 release 新版本或者发布安全公告之前,攻击者可以通过 security fix commit 或者 issue tracker 来发现并利用这些潜在的安全漏洞。
那回到甲方安全视角也应该投入一定的资源去按需跟踪这部分信息。
不同开源软件包生态下,在 release notes 中 security releases 、升级过程中可能影响业务中断的潜在风险等信息的提及情况:
开源软件包在 61.5% 的情况下都会在 release notes 中记录安全 fix。但是,仅在 39.6% 的案例中明确提到了(修复的)安全隐患。缺乏适当的文档可能会导致下游项目仍然意识不到对应的 security fix。
在一个 security release 中,不同开源软件包生态下的文件及代码行数的修改情况:
我们可以将其简单理解为,开源软件的维护者为了修复对应的漏洞,修改了多少代码。
大部分情况下,开源软件包可以在修改 134 行代码左右 6 个文件的情况下,解决对应的漏洞。很多开源软件的维护者在 release 版本的过程中,同时会增加很多无关安全的功能性更新,这在之前的工作中提及的安全漏洞修复建议是不推荐的。
security release 和 安全公告 之间的延迟情况:
一些下游应用程序的 owner 会依赖开源或者商业化的 SCA 产品,其部分数据源来源于安全公告,延迟的安全公告会为攻击者带来持续的时间窗口,使下游软件长期暴露在安全风险中。
Paper 中,作者还对 CVE 和 无 CVE 编号之间的漏洞修复生命周期,不同开源软件包生态,以及升级第三方软件包的潜在回退风险等内容进行了讨论,有兴趣的朋友可以直接阅读原文查看。
最后,paper 的作者团队为开源软件包的维护者和开源社区的管理团队提供了四条建议,用于优化上述面临的潜在风险:
安全学术圈招募队友-ing
有兴趣加入学术圈的请联系secdr#qq.com