前言

“开源”是指源代码、文档等设计内容开放的开发模式,是群智协同、开放共享、持续创新的理念和生产方式。2020年,根据Synopsys发布的《开源安全和风险分析报告》显示,开源使用数量占比较高,在教育、金融、医疗等传统行业渗透率已超过60%,开源软件已成为企业构建信息技术的重要选择。

国家政策上,2021年3月12日,开源首次被明确列入《中华人民共和国国民经济和社会发展第十四个五年规划和2035年远景目标纲要》,支持数字技术开源社区等创新联合体发展,完善开源知识产权和法律体系,鼓励企业开放软件源代码、硬件设计和应用服务。

开源蓬勃发展一方面可以突破技术壁垒、推动创新,另一方面考虑到国际竞争关系错综复杂,开源软件安全作为软件供应链安全的重要环节,面临着安全漏洞、知识产权、软件供应链安全等相关风险。在此背景下,认识和了解开源安全风险情况是至关重要的。

国家互联网应急中心联合棱镜七彩开源安全研究团队持续对开源软件供应链安全进行跟踪分析。《2019年开源软件风险研究报告》主要从GitHub热门开源软件视角出发,对开源软件安全风险进行了分析。本报告从全新视角带来开源安全风险新的发现与突破。报告共分为五部分,第一部分,首先介绍开源漏洞的发展现状及趋势;第二部分,聚焦开源组件生态库的安全风险;第三部分,重点围绕组件按依赖层级漏洞传播范围分析;第四部分,对文件级漏洞潜在安全风险及波及范围进行讨论;第五部分,对开源使用者和关注者如何在开源领域蓬勃发展下,更安全的拥抱开源生态提出了建设性意见。

一、开源漏洞发展现状及趋势

开源软件具有代码公开、易获取、可重用的特点,这一特点是开源软件热度攀升的重要原因。随着开源软件的广泛使用,一旦软件发现安全漏洞,必将给开发、安全团队带来严峻的挑战。然而,开源漏洞信息往往散落分布在各大社区,很多漏洞信息不能及时被官方收录。同时,对于软件使用者,由于缺少漏洞信息跟踪能力,使得漏洞修复具有滞后性,提升了软件被攻击的风险,为软件供应链安全管控增加了难度。

本次研究收录了官方漏洞库、开源社区等渠道的数据1,并统一收录整理成开源漏洞知识库。通过从中选取2015年至2020年发布的开源漏洞为研究对象,本报告展示了近6年开源安全漏洞发展现状及趋势。

发现一:开源软件漏洞整体呈增长趋势,2020年增长率略有下降

图1:开源漏洞时间分布

根据调查结果,相比2015年漏洞数据,近5年的漏洞数量均有不同程度增长。2018年是开源项目快速增长的一年,根据GitHub官方数据显示,GitHub代码仓库中超过1/3的开源项目创建于2018年,2018年新增开源漏洞数也创下近6年新高,新增7563个漏洞,相较于2015年翻了2.85倍;2017年漏洞增长速度最快,环比增长率为92.86%;2019年与2020年增长率略有下降,2020年发布的漏洞数较2019年发布漏洞数少了1746条。

发现二:CVE官方未收录的开源软件漏洞数逐年递增

图2:CVE官方未收录开源漏洞情况

对CVE官方网站2进行统计,可发现2020年发布的开源漏洞中未被CVE官方收录漏洞有1362个,占2020年发布漏洞总数的23.78%;CVE官方未收录数据呈上长趋势,增长率逐年递增,2018年环比2017年增长速度达133.52%。

发现三:开源软件漏洞由POC披露到NVD首次公开时间长达11年

2020年发布的开源漏洞中,编号为CVE-2009-4067的Linux内核的Auerswald Linux USB驱动程序的缓冲区溢出漏洞由POC披露到NVD首次公开时间长达11年。POC信息在2009年10月19日披露3;该漏洞于2009年11月24日获得CVE编号,但未公开漏洞具体信息;直到2020年11月2日NVD官方才将其发布。

开源软件的使用者仅关注官方漏洞库(如NVD等)可能无法及时获取漏洞信息,需综合考虑更多渠道的漏洞数据。

发现四:近4年,高危及以上开源漏洞占比均超40%

图3:含高危以上漏洞占比

调查结果显示,近6年高危及以上漏洞占比逐年递增,从2015年占比30.87%增长至2020年占比56%;其中,2017年至2020年高危及以上漏洞占比均超过40%;2020年,超危漏洞占比为8.83%,高危漏洞占比为46.91%,占2020年新增漏洞超5成。

图4:2020年漏洞危害等级占比

发现五:2020年,最主要缺陷类型为CWE-79

图5:2020年开源漏洞TOP10 CWE缺陷类型

调查结果显示,缺陷类型CWE-79数量最多,占2020年新增开源漏洞的14%左右。表1列出了TOP 10 CWE缺陷类型,这些缺陷类型很容易并被利用,往往通过系统信息暴露、窃取数据或阻止应用程序正常工作等方式,对系统造成安全风险。了解开源漏洞Top10 CWE 可以帮助开发人员、测试人员、用户、项目经理以及安全研究人员深入了解当前最严重的安全漏洞。

表1:2020年开源漏洞TOP10 CWE缺陷类型

CWE编号中文名称个数
CWE-79在Web页面生成时对输入的转义处理不恰当(跨站脚本)824
CWE-506内嵌的恶意代码726
CWE-400未加控制的资源消耗(资源穷尽)510
CWE-200信息暴露305
CWE-20输入验证不恰当212
CWE-94对生成代码的控制不恰当(代码注入)201
CWE-119内存缓冲区边界内操作的限制不恰当142
CWE-125跨界内存读134
CWE-78OS命令中使用的特殊元素转义处理不恰当(OS命令注入)124
CWE-325缺少必要的密码学步骤117

二、开源组件生态安全风险分析

开源组件生态蓬勃发展,重要原因是组件独立、可复用。组件化可以大幅度提高开发效率、可测试性、可复用性、提升应用性能。同时,组件化能够屏蔽逻辑,帮助迅速定位问题,易于维护和迭代更新。组件标准化使得优质好用的组件越来越多,用户也更愿意使用,形成一个良性循环的开源组件生态库。

开源组件被广泛使用,根据官方数据显示,Maven仓库数据量已达650万+,Nuget仓库累计下载量超930亿,Rubygems仓库累计下载量超712亿,PyPI仓库使用人数超过49万。

本报告选取了CocoaPods4、Composer5、Go6、Maven7、npm8、Nuget9、PyPI10、Rubygems11这8个主流的仓库作为研究对象,分析近6年各仓库新增漏洞数据,帮助解开源组件生态安全风险情况。

发现六:开源组件生态中的漏洞数呈上涨趋势,2020年环比增长40%

根据调查结果,近6年开源组件生态中漏洞数逐年递增。其中,2020年新增漏洞数为3426,环比去年增长40%;2017年增长速度最快,环比增长49%;近3年增长速度呈上升趋势,2020年新增漏洞数是2015年的4.48倍。

图6:开源组件生态漏洞时间分布

发现七:近6年中Maven仓库漏洞数量最多

图7:近6年中各组件仓库漏洞情况

调查结果显示,近6年中漏洞数量最多是Maven仓库,漏洞数量为3533个;Go仓库漏洞数量最少,漏洞数量为348个;平均每个仓库漏洞数量为1413个。

发现八:超半数仓库的漏洞数均较上年有所增长

图8:近6年各仓库漏洞分布图

调查结果显示,近6年,Composer、Go、Maven、npm、PyPI、Rubygems 6种仓库的漏洞数均有不同程度的上涨;Rubygems仓库漏洞增长速度最快,相比去年翻10.5倍;Go仓库和PyPI仓库增长率其次,环比增长率分别为252%和132%;Maven仓库2020年新增漏洞数基本与去年持平。

发现九:2020年高危漏洞占比最高,相比去年增加2.6倍左右

调查结果显示,2020年新增漏洞中,高危漏洞占比最高,数量为1826个;超危漏洞逐年递增,2020年数量有所下降,环比下降53%,2019年新增数量最多,新增数量为468个;高危漏洞逐年递增,2020年增长速度最快,相比去年增加2.62倍;中危漏洞呈现平稳增长趋势,2018年增长速度最快,环比增长率为48.13%;低危漏洞逐年递增,2020年增长速度有所下降,2019年新增数量最多,新增数量为171个。

图9:近6年新增漏洞风险等级时间分布

图10:近6年新增漏洞各风险等级占比

发现十:2020年,含高危以上漏洞占比最多仓库是Rubygems

图11: 2020年各仓库中含高危以上漏洞占比

调查结果显示,超八成组件含高危以上漏洞占比均超过40%。2020年,Rubygems仓库含高危以上漏洞占比最多,占Rubygems仓库新增漏洞的96%;Go仓库含高危以上漏洞占比最少,占2020年Go仓库新增漏洞的39%。

发现十一:平均每版本漏洞最多的TOP 25组件约五成来自Composer仓库

针对2020年各仓库新增漏洞,分析得到平均每版本漏洞数量最多的TOP 25组件。考虑到各仓库不同组件的版本数量各不相同,本报告采取平均每版本漏洞数作为计算依据,即:平均每版本漏洞数=组件全版本漏洞数/组件版本数。

研究发现,平均版本漏洞最多的TOP25中,Composer仓库的组件数占比最多,共计12个,占比约5成左右;PyPI仓库的组件数排名第二,共计7个;平均版本漏洞数最多的组件来自Maven仓库,漏洞数量为47个,下图列示各仓库中平均版本漏洞TOP25 组件分布:

图12:平均版本漏洞最多TOP25 组件仓库分布

图13:Composer仓库组件分布

图14:PyPI仓库组件分布

图15:Maven仓库组件分布

图16: npm和Nuget仓库组件分布

三、组件漏洞依赖层级传播范围分析

软件工程中经常引用组件来实现某些功能,组件之间存在相互依赖关系,按依赖关系可分为直接依赖和间接依赖,即组件A依赖组件B,组件B依赖组件C,那么组件A→组件B和组件B→组件C的依赖关系称为直接依赖,而组件A→组件C的依赖关系称为间接依赖。组件存在安全漏洞,组件之间又存在相互依赖关系,导致漏洞在组件之间存在传播风险。

本报告以Maven、npm、Rubygems 、PyPI、Composer、Nuget 6个仓库中含已公开安全漏洞的开源组件为研究对象,共计6,416个12,对其做两轮漏洞传播模拟实验,研究开源组件漏洞依赖层级传播范围。第一轮实验,查找直接依赖这6,416个开源组件的组件集合,为方便定义,称该组件范围为一级传播;第二轮实验,查找直接依赖一级传播组件的组件集合,该组件集合均间接依赖这6,416个开源组件,称该组件范围为二级传播。

发现十二:一级传播影响范围扩大125倍,二级传播影响范围扩大173倍

图17: 组件漏洞依赖层级传播范围

调查结果显示,原始样本中6,416个组件,受组件依赖关系的影响,一级传播一共波及801,164个组件,其影响范围扩大125倍。第二轮实验中,发现二级传播一共波及1,109,519个组件,影响范围相比原始样本6,416个组件扩大173倍。

发现十三:npm仓库中的组件经2轮传播,影响组件数量最多

图18: 各仓库组件漏洞传播范围

调查结果显示,Maven、npm、Rubygems 、PyPI、Composer、Nuget 6个仓库选取样本中,npm仓库原始含漏洞组件数量为1,962个,npm仓库漏洞组件数量在原始样本中仅次于Maven仓库,排在第二位。经2轮模拟传播实验,发现6组仓库中波及范围最广是npm仓库。npm仓库原始样本中共有1,962个含有漏洞的组件,经过一级传播共波及459,876个组件,漏洞的影响范围扩大了234倍;二级传播共波及601,574个组件,范围比最初1,962个组件扩大了307倍。

发现十四:一级传播影响范围最广的仓库是Composer

图19: 各仓库一级传播影响范围

调查结果显示,Composer仓库原始含漏洞组件数量为380个,为6个仓库中原始样本中含漏洞组件数量的第5位。经1次传播,一级传播波影响范围最广的仓库是Composer。经过一级传播共波及99,611个组件,漏洞的影响范围扩大了262倍。

发现十五:二级传播影响范围最广的仓库是Nuget

调查结果显示,Nuget仓库原始含漏洞组件数量为172个,为6组中含漏洞组件数量最少的仓库。经2次传播,二级传播波影响范围最广的仓库是Nuget。经过一级传播共波及23,240个组件,漏洞的影响范围扩大了135倍;二级传播共波及84,995个组件,范围比最初172个组件扩大了494倍。

图20: 各仓库二级传播影响范围

发现十六:传播影响范围最小的仓库是Maven

图21: 两轮漏洞传播组件漏洞影响范围分布图

调查结果显示,Maven仓库原始含漏洞组件数量为2,289个,经过2次传播,6组仓库中受漏洞影响范围最小是Maven仓库。经过一级传播共波及94,724个组件,漏洞的影响范围扩大了41倍;二级传播共波及145,827个组件,范围比最初2,289个组件扩大了64倍。

从整体上看,开源组件生态中漏洞影响范围远超预期,组件间的依赖层级关系会导致组件之间漏洞存在传播风险。因此,要保证软件的安全风险控制,应通过自动化的手段识别软件工程中的组件成分,梳理组件间的依赖关系;在已知成分清单基础上对组件漏洞风险实施管控;同时,还要对已知成分进行动态监控,建立组件生态的漏洞威胁警报,在动态变化中将安全漏洞风险降到最低。

四、开源文件潜在漏洞风险传播分析

开源项目中往往存在相互引用关系,同一开源文件可能被多个项目所引用或包含。考虑到开源文件这一特性,本研究选取已公开漏洞中定位至文件级的开源文件为研究对象,共计17,570个,依托本研究团队的开源项目知识库13,对17,570个漏洞文件进行同源分析,识别开源生态中包含此漏洞文件的开源项目范围。

发现十七:超80%漏洞文件在开源项目具有同源文件

图22: 漏洞文件同源占比分布

调查结果显示,选取的17,570个含漏洞的开源文件中有80.35%的文件可在开源项目中找到同源文件,共计14,118个,其余的3,452个文件未找到同源文件。

发现十八:漏洞文件在开源项目中传播范围扩大54倍

图23: 漏洞文件在开源项目中传播范围分布

通过对含同源文件的14,118个含有漏洞的开源文件进行分析,在不考虑同一开源项目不同版本的前提下,这些漏洞文件被766,877个开源项目所引用,漏洞文件在开源项目中传播范围扩大54倍。如果考虑同一开源项目的不同版本,这些漏洞文件被2,410,476个开源项目所引用,漏洞文件在开源项目中传播范围将扩大171倍。

案例分析

LibTIFF项目中tif_next.c被曝出有2个中危漏洞CVE-2015-1547和CVE-2015-8784。为了解该漏洞文件在开源项目中的引用情况,本研究团队对tif_next.c漏洞文件进行同源分析,在开源项目知识库中共发现有237个开源项目包含tif_next.c文件,如果考虑项目不同版本,共有1000个开源项目中引用tif_next.c文件。表2列出了6大托管平台引用tif_next.c文件的部分同源开源项目,经对比,所有同源文件均仅删减了注释行,而代码逻辑以及函数变量名称均未改变。

表2:6大托管平台tif_next.c文件的同源开源项目举例

托管平台

开源项目名称

版本号

同源文件路径

GitHub

reactos/reactos14

backups/ros-branch-0_4_2@73087

见注释15

Gitee

mirrors-opencv16

2.4.10

见注释17

Gitlab

limbo18

v2.2.1-Limbo-armv7-hf

见注释19

Bitbucket

xray20

FirstAddedTBB

见注释21

Sourceforge

wxhaskell22

wxInstall-Abriline-32-0.1

见注释23

CodePlex

casaengine24

master

见注释25

从整体上看,本次研究发现相同的文件被多个开源项目所引用的现象远多于预期。考虑到漏洞利用的复杂性,本研究团队认为这些结构一致的同源文件具有潜在漏洞风险,漏洞是否能真正的被利用,还需要深入研究。

五、开源安全风险建议

开源生态带来的正面效应已在信息经济生活中发挥重要影响,如何在安全可控的情况下使用开源,已成为开源生态的关键任务。开源安全风险防范措施应贯穿软件开发的整个生命周期。本报告给出了如下六点建议:

(一)建立开源管理领导组织。随着软件开发过程中开源软件的使用越来越多,开源软件事实上已经成为了软件开发的核心基础设施。开源软件由于其特殊性,从软件供应链视角看,将横跨采购、选型设计、研发编码、运维交付等多个环节,需要跨组织、跨部门协同管理。具备条件的企业、机构建议设立开源管理办公室或领导小组,全面学习开源生态知识,了解开源生态运作机制,开展开源风险意识培训,强化开源风险管控手段。

(二)识别开源成分。开源软件全面渗透至软件供应链体系中,需准确识别软件中的开源成分(包括开源源代码成分、开源二进制成分、引用依赖的开源组件成分等),形成开源成分清单和图谱,做到对软件开源成分的可知可控。同时精确绘制开源组件依赖链条,防止安全风险随着开源组件依赖链条的逐层传播,是进行开源安全风险防范的基础。

(三)修复已知开源漏洞。已知软件的开源成分清单和图谱,明确开源成分及依赖链条后,通过相关工具检测或知识库查询,可有效识别已知开源漏洞。结合项目实际情况进行漏洞修复,降低软件安全风险;对于未修复或短期内无法修复的漏洞,确定安全风险接受清单,明确相关应急响应机制,最大程度降低风险。已知的开源漏洞修复,相较于代码安全审计,往往是将带有漏洞的组件升级至最新或较安全的组件版本,操作简单,易于实施,是一个投入产出比较高的风控措施。

(四)建立开源威胁情报体系。软件安全是动态发展的,开源软件的威胁情报由不同的组织(如开源社区、开源基金会、开源项目方)共同贡献分享。开源威胁情报呈现无统一组织,散落在互联网海量信息中。需建立对已知开源成分及依赖链条漏洞威胁情报的实时监控跟踪机制,搜集多维度多渠道的开源威胁情报,并针对企业、机构已有的开源成分清单和图谱,在第一时间内将有效的开源威胁情报同步给相关责任人。

(五)弃用过老的开源组件和版本,及时安全更新。较老的组件往往存在大量的安全漏洞,也存在软件供应链安全隐患(如停止运维更新升级)。在使用开源软件,应关注其热门程度、受欢迎趋势、社区口碑、更新时效性等因素。应选择较新的安全的开源组件,并做到及时安全更新,降低开源安全风险。

(六)使用左移安全工具。在测试或者交付验收环节,针对开源安全风险进行处置往往会投入更大的工作量和成本。通过使用左移开源安全治理工具的方式,将开源安全风险治理集成到软件开发全生命周期过程中。在需求设计、组件选型、编码集成等早期研发过程中及早发现开源风险问题,从而降低开源安全治理成本。

声明:本文来自国家互联网应急中心CNCERT,版权归作者所有。文章内容仅代表作者独立观点,不代表安全内参立场,转载目的在于传递更多信息。如有侵权,请联系 anquanneican@163.com。