snyk:2017年开源安全的现状报告

开源似广袤之地,且越来越多样化。开源安全的整体状况是一个重要的衡量尺度。我们需要了解它当前所处的位置,以便了解我们能够改进的地方。

试图并提供对开源这个生态系统安全健康的全球性观点需要数据的支持。为了更好地理解安全的开源是什么样的以及我们如何可以让开源的安全性变得更好,Snyk公司发出并分析了由500多名开源维护者和用户填写的调查。我们同时查看了Snyk公司基于40,000多个项目的内部数据、由Red Hat Linux提供的信息、以及我们通过扫描数百万GitHub仓库和包所收集的数据。

本报告概述了这些研究结果。

概览

去年,包管理工具索引的开源包数量呈爆炸式增长。

包管理器 开源包增长百分比
Rubygems 10%
Python 32%
Maven 28%
Npm 57%

开源维护者的安全知识并没有保证。仅有16.8% 的维护者认为他们掌握的安全知识很多,而43.7% 的维护者从未开展过代码安全审计。

对43万站点的测试结果显示,77%的站点至少运行了一个带有已知安全漏洞的前端库 (front-end library)。

开源应用库的漏洞数量在2016年增长了53.8%。而在2017年,漏洞数量在此基础上又增长了39.1%。

发布修复方案后,维护者需要通知用户保护应用的安全。88% 的维护者通过发布说明(Release notes)通知用户,而只有9%的维护者会申请CVE编号,仅有3%的维护者会将漏洞情况告知漏洞监控服务。

漏洞在披露前潜伏的时间中位数是2.5年,不过一旦发现后,维护者的响应速度通常很快。漏洞从发现到修复的时间中位数是16天。

美国国家漏洞库 (NVD) 中的漏洞数量大幅增长,但漏洞覆盖是个问题。

被NVD所覆盖的漏洞百分比:npm(11%)、Rubygem(67%)。

 

开源软件情况总览

整体而言,开源正在蓬勃发展。Forrester和Gartner都表示80%到90%的商用软件开发人员都在应用程序中使用开源组件。全球范围内所有可想象得到的垂直行业都在使用开源代码助力自己的业务。

使用

不管你看的是哪个生态系统,它们对开源组件的使用都在增多。

截止到2017年9月底,人们通过PyPi下载Python包的次数已达到63亿,通过npm下载Node包的次数超过873亿。

去年(2016年10月1日至2017年10月1日),包管理工具索引的开源包数量呈爆炸式增长。Rubygems的数量已增长10.3%,Python库的数量增长32%,Maven的数量增长28%,npm包的数量增长57%。

同时,Docker Hub上的公共应用程序数量已超过90万个,而去年的数量为46万左右。

简言之,开源组件的数量之多前所未有,而且它们的便捷性也史无前例。

平均每天下载的npm包数量(单位:百万)

平均每天下载的PyPi包数量(单位:百万)

索引包总数的百分比增长率 (2016年10月至2017年10月)

风险和影响

如果你正在使用开源代码,那么安全性是一个首要考虑因素。Github在最近的开源调查中指出,86%的用户表示安全极其或非常重要。但是开源具有内在风险,因为你不知道你所下载的来源是谁,而且不同开源项目之间的安全标准和维护者的技术水平各不相同。

开源组件中的已知漏洞也成为非常具有吸引力的攻击向量。一旦这些漏洞遭公开披露,那么利用代码就会紧随其后。

今年的Struts2漏洞 (CVE-2017-5638) 就是一个例子。研究人员在2017年3月发现了这个漏洞,6天之后,Imperva公司就报告称发现数千个来自40多个国家1323个不同IP地址的漏洞利用尝试。

聚焦Equifax

2017年最引人注目的安全事件之一是Equifax遭受的攻击,它导致数百万记录遭泄露。这次事件是通过利用Apache Struts2包中的一个已知漏洞引发的,该漏洞能让远程攻击者发送恶意请求,从而执行任意命令。

这个漏洞的时间轴也让其与众不同。2017年3月6日,漏洞被公开披露并修复。一天之后,利用脚本就开始出现。2个月之后,也就是5月13日,Euifax数据泄露事件爆发。再过了2个月之后(7月29日),事件才被发现。这个漏洞从被公开到被利用中间只隔一天,而数据泄露事件是在2个月之后发生。因此,怎么强调优先保证开源的安全性也不为过。

开源软件维护者的安全态势

从安全角度来讲,开源的蓬勃发展也带来了挑战。并不存在开源开发必须遵守的、确保软件安全交付的“规则”,因此每个项目的安全态势各不相同。开源软件维护者的挑战在于,他们通常是业余维护这些开源资源,因此他们并没有足够的时间和资源来确保项目的安全。

虽然向开源项目贡献代码的多数人员并非恶意人员,但只有16.8%的受访维护者表示自己觉得自己的安全知识水平为“高”。

减少应用程序中漏洞数量的方法之一是例行开展安全审计,或者开展手动审计或者雇佣渗透测试人员来检查尚未披露的安全风险有哪些。然而43.7%的开源维护者表示从未开展过代码安全审计,而另外31.8%的维护者表示在项目生命周期内只审计过一两次。

目前,并不存在记录开源项目基本安全信息的标准。在GitHub排名前40万公共库中,只有不到1万个公共库中有说明开源项目安全信息的文件,,约占总数的2.4%。

由于缺少公开信息,因此难以评估任何单个开源包或项目的总体安全投入,而且也难以理解如何向开源维护者披露新发现的漏洞。

维护者如何评价自己的安全专业技能

维护者审计代码的频率

漏洞的数量有多少?

错误总会发生。卡内基梅隆大学开展的一项调查显示,每1000行商用软件代码中,约有20到30个bug。有了bug之后,漏洞会不可避免地随之产生。

应用程序库中的已知漏洞

自2009年以来,应用程序库中已发布的漏洞数量稳步增长,并且并无放缓的迹象。去年(2016年),所发布的开源安全漏洞数量增长了53.8%(基于Snyk数据库的统计,该数据库追踪的是npm、Maven、Pip、Rubygems和Go),而今年较去年已增长39.1%。

同样的问题也存在于前端。我们测试了超过43万个站点后发现,77%的站点至少运行着一个包含一个已知安全漏洞的库。

系统库中的已知漏洞

从Red Hat Linux中我们看到了一个相反的趋势。影响Red Hat Linux的漏洞数量自2012年以来稳步减少,至今已减少了62%。

按年份公布的开源漏洞数量

按年份统计的Red Hat Linux漏洞数量

漏洞严重性的趋势

对漏洞数量的统计是一方面,不过我们也可以质疑这些漏洞是否会产生真正的影响。下载数量不多的库中出现的高危漏洞可能会导致漏洞数量被人为夸大。

为此,我们查看了从下载量超过5万次的npm包中发现的高危漏洞,同时基于包对客户的重要性查看了Java包中出现的高危漏洞。在这两种情况下,我们发现影响力大的高危漏洞数量在稳步增长。截至2017年的目前阶段,我们看到增长趋势非常相似。

严重的Java和Node包漏洞

Docker容器中的漏洞

容器也面临着类似问题。容器将所有的库、包、设置等整合到一个预配置好的环境中,为人们提供了极大的便利性。

但跟其它事情一样,如果它们没有持续更新的话,也会出现已知漏洞。在最受欢迎的1000个Docker容器中,76.5%的容器中存在已知漏洞,而62.3%的容器中至少存在一个高危漏洞。

系统库中的高危漏洞

Red Hat Linux漏洞再次显示出不同的趋势。影响Red Hat的严重漏洞数量在2012年达到峰值,不过其它年份都基本保持一致。

Red Hat Linux似乎找到了某个稳定水平。虽然应用程序库的情况并非如此(漏洞数量和严重程度都在增加),但它让我们乐观地认为,只要多做一点工作,那么就可以变得更加安全。

 

开源安全的生命周期

开源安全漏洞的生命周期(从发现到修复)中涉及到很多步骤。生命周期中的每个部分都起着重要作用,从而最终对开源的安全状态产生影响。

发现漏洞(漏洞是如何被发现的,以及它们隐藏了多长时间)——发布修复方案(从披露到漏洞解决所耗费的时间)——通知用户(用户是如何了解到漏洞修复方案的)——采纳发布的修复方案(用户在修复方案发布后采纳的速度有多快)

发现漏洞

第一阶段需要查看的是漏洞被引入之后,多久会被发现。

从漏洞被引入(包含在正式发布中)应用库到被公开披露之间的时间间隔中位数是2.53年(924天)。无数研究已证实,对于Linux漏洞而言,这个时间间隔约为5年。而这就更加突出了例行开展安全审计的重要性:很可能还存在很多其它尚未被披露的漏洞。一般来说,代码审计是软件维护者确保项目安全的重要步骤。

维护者是如何找到漏洞的?

如何披露并解决这些漏洞是项目整体安全性的重要特征。在理想情况下,应该私下将漏洞报告给维护者,让他们在外界知晓漏洞之前将其修复。

而在现实中,漏洞披露的过程并不总是一帆风顺。部分原因是面向公众的披露策略比较少见。79.5%的维护者表示他们并未准备面向公众的披露策略。由于缺乏清晰的披露沟通,导致研究人员难以通过私密且负责任的方式报告漏洞情况。

正因如此,维护者表示他们获悉漏洞的方式多种多样。大多数漏洞是由项目之外的其他人发现的,只有25%的维护者表示他们是自己发现漏洞的。开源维护者收到私下披露的可能性 (31.4%) 和仓库中被公开指出存在问题的可能性 (30.3%) 一样大。

备有面向公众的披露策略的维护者更可能收到私下披露的漏洞。大约21% 的未准备公开披露策略的维护者接收到私下披露的漏洞,而对于准备了公开披露策略的维护者而言,这个比例是73%。

这里可能也存在一些确认偏见。在备有披露策略的维护者中,有13.5%的人员表示从未遇到过安全问题;而在没有准备披露策略的维护者中,这个比例是32%。虽然产生这种结果的原因可能是因为备有披露政策的维护者是在第一次收到安全问题报告之后才准备的策略,但鉴于未准备披露策略提供指导的情况下披露漏洞所面临的复杂问题,很可能是因为虽然发现了很多漏洞但却未被披露的缘故。

漏洞:从存在到披露 (最长时间是5.9年,最短是0天,中位数2.5年)

漏洞:从披露到修复(最长时间94天,最短0天,中位数16天)

发布修复方案

下一阶段要查看的是“风险天数”,即从披露到修复所经历的时间。从漏洞被公开披露的那一刻开始,风险就急剧增大并且持续增大直到漏洞被修复而用户可采取措施为止。为此,这里的情况更加多变。

紧急处理漏洞

开源维护者非常迫切希望尽快对安全漏洞做出响应。34%的维护者表示他们能够在获悉漏洞的一天之内做出响应,而60%的维护者表示他们能在一周之内响应。

我们可从对今年出现的影响力最大的一些npm漏洞的响应中看出以上所述内容。从漏洞被披露到正式发布版本中包含修复所需要的时间中位数是16天。

维护者对漏洞的响应速度

具有已知修复方案的漏洞百分比

在多数情况下,修复方案并不会向后移植到其它版本流中。在Snyk公司的数据库中,只有16.1%的漏洞的修复方案能向后移植到其它版本流中。这种情况在所有生态系统中都差不多,除npm外:只有4.1%的npm修复方案能应用于其它版本流中。

由于缺乏向后移植,因此很多人难以升级到新修复方案,因为迁移到一个新的库版本要求投入时间和精力根据库的变化做出必要的更新。

能够向后移植到其它版本流的修复方案百分比

聚焦Nokogiri和LibXML

有时候,依赖关系链也会让开源项目的处境变得艰难。非常流行的Nokogiri库就遭遇到这种情况。Nokogiri使用libxml2库让用户轻易从XML、SAX、Reader或HTML文档中解析并提取数据。

遗憾的是,libxml2中存在一个漏洞,可导致攻击者轻易执行XXE攻击。

虽然这个漏洞于2016年11月发布,但libxml2尚未集成修复方案。这导致Nokogiri处于艰难位置:它所依赖的库中存在的漏洞导致它易受攻击。Nokogiri已试图通过确保默认配置尽可能安全的方式来避免用户沦为受害者,但在libxml2解决这个问题之前,Nokogiri仍处于易受攻击的状态。

通知用户

漏洞解决之后,必须快速通知用户,让他们知道通过哪些措施来确保应用程序的安全。

维护者将安全问题告知用户的方式

(受访者可选择多种响应方式)

多数维护者 (88%) 表示通过发布说明(Release notes)的方式通知用户,而约34%的维护者会通过不支持最新的易受攻击版本来鼓励用户应用修复方案。

最值得注意的是,竟然有25%的维护者表示如果发现安全问题不会通知用户。如果不跟用户沟通漏洞的情况,那么用户很可能不会快速应用最新的修复方案。而易受攻击的版本可能会长时间处于生产环境中,而用户本可以很早就可以因此受到保护。

不常采取的一个步骤是将漏洞情况告知漏洞库或漏洞监控服务。在理想情况下,每个漏洞都会被归类于已知漏洞数据库中供软件使用者研读。只有3%的维护者表示它们会将漏洞情况告知服务公司如Snyk公司等。

而8.9%的维护者表示它们会为漏洞申请CVE编号,一小部分的维护者表明申请CVE时会遇到一些麻烦。

聚焦Next

Next是服务器渲染的一个React应用程序框架,今年发现Next中存在一个目录遍历漏洞。这个漏洞自从2016年10月Next首次发布之日起就存在。该漏洞发现于2017年5月31日。6月1日,Next发布了包含修复方案的新版本库。

Next不仅快速实施修复,而且响应十分迅速。虽然在很多情况下,一个安全修复方案仅占据库发布说明(Release notes)的一行之地,但Next的做法与之相反。在修复版本的发布说明中,Next提供了诸多信息:漏洞的细节、如何解决、受影响群体以及如何跟进最新安全问题。

CVE、CPE和NVD

美国政府创建并为CVE列表提供支持。CVE列表是关于漏洞的免费字典。CVE旨在为所有已知漏洞提供单一目的地——不仅是为开源软件,也供软件使用者研读。

CVE本身是一个列表而不是数据库,包含关于所引用的漏洞的最少信息。NVD提供了更多的信息。NVD是从CVE列表中扒下(尽管并不一定是马上)并提供更多的漏洞信息:包括修复详情、提供CPE(通用产品枚举, Common Product Enumeration)帮助找到包含该漏洞的产品或应用程序、提供CVSS评分以提供漏洞的安全严重程度和特征信息。

总体而言,NVD带来了积极成果。自从1999年推出以来,NVD已经包含超过8.1万个漏洞且仍在持续增长。单在2017年,数据库中就添加了8500多个漏洞信息,要比历史上其它任何年份都要多。

这种联合维护漏洞数据库的方法虽然有效,但遗漏了很多漏洞。

相比我们的开源漏洞数据库,CVE/NVD对漏洞的覆盖根据语言和生态系统的不同而不同。例如,NVD仅覆盖了67%的Rubygem漏洞以及只有11%的npm漏洞。

CVE/NVD面临的另外一个挑战是速度问题。虽然漏洞可能会相对较早地获得一个CVE编号,但这个漏洞要进入NVD并获得CVSS评分和CPE的话,通常会等待很长时间。

53%的应用库漏洞在被添加到NVD之前已经被公开(无论是在漏洞数据库中、库发布说明中或其他的机制中)4周或更长的时间。在这个案例中,长尾非常长。28.9%的漏洞的公开时间会超过半年,而9.4%的漏洞在进入NVD之前已经公开一年多的时间。

CVE滞后的部分原因是,多数开源维护者在发现新漏洞时并不会参与申请CVE编号。如之前所讨论的那样,在调查中,只有8.9%的维护者表示会在发现漏洞后申请CVE编号。遗憾的是,只要试图通过联合方式管理漏洞,那么这个问题将持续存在。

在被加入NVD/CVE之前,漏洞被公开的时长

采纳发布的修复方案

最后需要查看的时间线就是在修复方案发布后,用户会以多快的速度采纳修复?这个决定并不容易做,因为用户必须同时知道修复方案的存在,而且还需要确保新版本不会导致应用中断。换句话说,应用修复方案需要时间。

从调查结果来看,开发人员保证依赖关系是最新版本的方法有很多,包括不定期清扫颠簸版本(bump versions)(46.9%)、让工具提醒漏洞的存在(41.6%)、让工具提醒新的依赖关系版本(37.2%)以及口口相传(8.6%)。

令人惊讶的是,16.3%的用户表示并不会更新自己的依赖关系。乍一看,让工具帮助自己管理依赖关系的比例看似还正常,但其实存在很多重叠之处。很多用户使用一款工具来提醒新版本出现的同时会使用另外一款工具提醒他们安全问题的出现。

事实上,38.7%的用户并不会使用工具来确保依赖关系是最新版本。这就不可避免地导致出现这样一种情况:依赖关系的更新频率并未达到要求,或者很多压力被放到开发过程。

由于缺少工具,重视安全的组织机构必须手动检验并验证依赖关系的新版本以确保它得到更新并且不含已知的漏洞。由于开源社区的快速变化,这种手动方式变成一个麻烦的瓶颈问题而且无法得到维护。

存在漏洞的开源库版本的下载量

应用补丁的节奏往往会有一个很长的长尾。看看流行的Python “requests” 库就知道了。”request” 库是最流行的Python包之一,在去年它每个月的下载量差不多有1200万次。2016年,Python “requests” 曝出一个HTTP请求重定向 (Request Redirection) 漏洞。由于它非常流行,我们可以通过仔细查看它正在被使用的版本情况来了解用户打补丁的速度。

从2016年5月到2016年7月(即漏洞被解决的3个月前), “request” 包的易受攻击版本占所有下载量的99%。2017年4月,也就是版本2.11.0发布的那个月,易受攻击版本所占的比例下降到56.6%。然而,在漏洞最初爆发后,长尾出来了。在2017年9月,在所下载的所有 “requests” 包中,仍有22.4%的下载是易受攻击的版本,尽管修复方案已经发布一年多的时间。

易受攻击版本的Python “request” 下载量占所有下载量的百分比%

 

开源的未来

开源正在蓬勃发展,而且并无减缓趋势。虽然开源的好处人尽皆知,但是开源风险的知识却不尽然。不过这种趋势正在发生变化。

很明显开源安全有改进的空间,而且改进的机会很多。显然,维护者们迫切希望让自己的项目变得更加安全,而用户想的是在使用开源时将安全列为优先考虑因素。而这只不过是像把衣服上的褶皱熨平一点那样容易。

如果你是维护者,从简单的三个步骤开始吧:

  1. 确保你的项目拥有公开披露的策略,这样如果有人找到漏洞,就能快速报告给你。
  2. 例行审计并检查代码基的安全,这样更易于在漏洞公开前发现它们。
  3. 清楚地向项目用户说明,你在乎项目安全。在解决好安全问题后,详细并清楚地告知用户,这样用户就能准确地知道如何继续进行下去。

如果你在自己的应用中使用了开源组件,你也可以做一些事情:

  1. 利用工具自动检测第三方组件中含有的已知漏洞,以便能够尽快修复它们。
  2. 做点回馈。多数时间,除了日常工作外,维护者们在努力地维护开源项目。撸起袖子并帮助他们解决问题是确保自己最爱的项目保持健康和安全的最佳方式之一。
  3. 尽可能负责任地报告漏洞。如果你发现出现问题了,通过私下渠道告知维护者。如果没有公开披露策略,思考下自己是否能通过邮件或其它沟通方式告知他们。

保护开源的安全并不会在一夜之间发生。如本报告所述,开源安全决定于很多因素。但如果我们齐心协力,每个人都做出力所能及的事情来改进安全态势,那么我们就能够改进开源安全的状态,而且在这个改进过程中,我们要确保开源仍然是欣欣向荣充满生机的生态系统。

(完)