近期,国外知名的专注于应用安全的 Veracode 公司发布了他们一年一度的《软件安全报告》至今已连续发布了12版。在最新的报告中(第12版),Veracode 公司深入观察了软件开发和软件安全近十年的发展状况,提供了详实的数据分析和对比结果,并结合当下主流的应用缺陷扫描能力横向对比给出了提高软件安全性的最佳实现路径。这对于持续关注国内外安全行业应用安全领域发展态势的同行来说,具有一定的借鉴意义。
概述
世界正变得比以往任何时候都更紧密地联系在一起。连接使我们的生活更轻松,但它也增加了风险。一个安全漏洞可能会产生多米诺骨牌效应,使软件在全球范围内都受到攻击,例如去年年末爆发的 Log4j 高危漏洞以及近期出现的 Spring Framework 远程执行代码 (CVE-2022-22965),几乎影响了全球绝大多数软件。但是,塑造了安全格局的不仅仅是增强的连接性,还有超强的竞争力和不断创新的需求。为了加快速度,许多软件开发团队已经转向本地云技术、微服务架构和开源代码来加速和扩展他们的努力。此外,软件开发团队已经采用了敏捷方法,并且在开发过程中尽可能自动化更多的步骤。
虽然这种演变提高了软件开发生命周期的速度,但也带来了新的复杂性和风险。在我们的第 12 版软件安全状况报告中,我们将在 Cyentia 研究所的帮助下探讨这些趋势,以评估软件安全状况是如何继续发展的。我们的目标是帮助业内同行对软件安全计划作出明智的决定,以便各位同行可以最小化风险,并满足网络安全条例的要求,如美国白宫在2021年5月12日发布的关于改善国家网络安全行政命令中所列出的要求。
2021年5月,拜登政府发布了一项关于网络安全的行政命令,概述了向美国政府销售软件的供应商的新安全要求。这些要求包括软件开发过程中的安全测试以及正在使用的开源库的物料清单,因此,已知的漏洞将被披露,并且能够在将来进行跟踪。虽然该命令仅影响短期内向联邦政府销售软件的公司,但它也需要制定一个试点计划,最终将改变所有软件供应商的安全要求。
”商业软件的开发往往缺乏透明度,对软件抵御攻击的能力缺乏足够的重视,并且缺乏防止恶意行为者篡改的适当控制。现在迫切需要实施更加严格和可预测的机 制,以确保产品的安全运行,并且如预期的那样。”关键软件”——执行对信任至关 重要的功能(例如提供或要求提高系统特权或直接访问网络和计算资源)的软件—— 的安全性和完整性是一个特别令人关切的问题。因此,联邦政府必须采取行动迅 速提高软件供应链的安全性和完整性,优先处理关键软件。”
近十年软件开发发展变化
与去年类似,我们查看了活跃应用程序的整个历史,而不仅仅是查看一年内与应用程序相关的活动。通过这样做,我们可以清楚的了解到应用程序的整个生命周期,从而得到更精确的度量和观察结果。除了回顾过去,我们还通过考虑可能有助于提高应用程序安全性的最佳实践来设想未来如何增强软件安全性。
Veracode 用大量的数据量化了很多关于应用程序安全性状况的发展变化,近十年是互联网高速发展的时期,我们需要后退一步,审视过去,展望未来,看看哪些方面是稳定的,哪些方面发生了变化,并试图理解哪些原则经受住了时间的考验,哪些发生了动摇。
首先,我们来看看人们是如何使用软件分析工具的,以及这些年来它们是如何改变的。我们将看到这些扫描反映出的发展趋势。我们也将看到开源软件是如何继续成为大多数应用程序不可或缺的一部分。其次,我们将分析软件的缺陷,看看这些软件开发趋势是如何在引入软件的漏洞过程中表现出来的。接下来,我们将检查漏洞是如何修复的,以及开发人员是否在修复漏洞方面做得更好。最后,我们将展望未来, 思考开发者究竟能做些什么才能编写出更安全的软件。特别是,我们将看到开发人员花时间学习如何修复漏洞的简单行为有助于更快地修复漏洞,并有助于防止将来出现安全漏洞。
1、经过安全扫描的应用程序数量是十年前的三倍多
扫描的应用程序数量相比于十年前增加了三倍
从上图中,我们可以看到经过安全扫描的应用程序数量比以往任何时候都多。这种增长不仅仅是因为有更多的组织机构产生。 去年,大多数组织平均每季度创建超过 17 个扫描应用程序,而十年前只有大约 5 个。
其可能原因有以下两点:一是组织正在创建更小、更模块化的应用程序;二是组织正在将他们的安全扫描范围扩展到低危的应用程序。
从上图中可以看到应用程序的风险程度的分布一直相当稳定。在过去的 10 年里,这种倾斜是非常一致的,大多数应用程序的风险程度都是“高”或“非常高”,只有少数应用程序的风险程度是“低”或“非常低”。
2、微服务逐渐成为主流
微服务一种是松散耦合的应用程序的集合,通常有一个小的代码库,通过 API 进行通信。微服务的优势在于,如果更改一个部分不太可能影响其他部分,则可以更容易地处理应用程序的各个部分。
从上图可以看出,大约在2018年之前,使用多种编程语言的应用程序数量缓慢但稳定地增长,达到峰值(不包括异常值),约20%的应用程序使用多种编程语言。但是,随着微服务的概念越来越受欢迎,这一数字出现了急剧下降,目前只有不到5%的应用程序使用多种语言。
在 2018年,大约有 20% 的应用程序包含了多种软件开发编程语言。今年,只有不到 5% 的应用使用了多种编程语言,这意味着软件开发人员将转向更小的、只有一种编程语言的应用或微服务。
使用不同编程语言开发的软件代码库平均大小与首次静态扫描的时间关系
从上图可以看出,对于微服务型架构,我们认为可以用多种编程语言编写的应用程序的规模肯定会有所下降,这一趋势是好事情。使用 JavaScript、Python和 .NET 开发的应用程序数量都在下降,这表明软件开发人员更趋向于使用微服务,其他几种常见编程语言的情况如下:
JavaScript
随着时间的推移,JavaScript 应用程序变得越来越小,这可能是因为包含了更加多样化和健壮的库生态系统
PYTHON和.NET
Python和 .NET 规模有所减少,但这可能更多地只是均值回归,而不是真实趋势
C++与Java
同时,使用C++和Java等更为成熟的语言编写的应用程序在过去几年中保持着差不多的大小
Scala
与其更重量级的教父 Java 相比,Scala 应用程序(未展示图表)的规模有所下降,Scala 的受欢迎程度可能与不同的架构目标有关。
Go
有趣的是,Go(未展示图表)是一种通常与微服务相关的语言,实际上已经看到了应用程序大小的增加
ANDROID
在Android N发布之前,Android应用程序的规模越来越大,而Android N改用了OpenJDK。这使得应用程序的规模大大缩小,随后又出现了缓慢而稳定的增长。我们不认为这是一种趋势,但很高兴看到软件生态系统中的重大事件在数据中得到验证。
3、安全扫描频次比十年前增加了20 倍
有人说“软件正在吞噬世界”,也有人说“敏捷正在吞噬软件世界”这可能也是对的。持续测试和集成(包括对管道进行安全扫描)正在成为一种规范,我们可以从开发人员扫描其应用程序的频率中看到这一点。十年前,开发人员平均每年扫描两到三次。 现在,大多数开发人员每天会进行静态扫描,并且每周进行动态扫描。软件组合分析(SCA) 扫描也是至少每周进行一次。在软件生命周期中,你越早发现问题,你就越有可能在问题变得更大之前迅速解决它们。
包括管道安全扫描在内的持续测试和集成正在成为常态。十年前,应用程序每年参与安全扫描两三次。而现在,90%的应用程序每周参与安全扫描一次以上,其中大多数每周扫描三次。
持续集成模式的部分优势在于能够轻松地向管道中添加新的组件。静态测试是必须的。动态测试的使用也在不断增长,而且由于软件开发人员越来越意识到开源软件固有的潜在风险,SCA 的使用也在不断增长。
从 2018 年到 2021 年,我们看到采用多种安全扫描类型组织增加了 31% ,其中很大一部分组织使用了完整的静态、动态和 SCA 扫描套件。
4、三方库的安全性依旧堪忧
大多数应用程序(取决于编程语言)具有一种杠铃效应,几乎完全由第三方代码或几乎完全由内部代码组成。当然也有一些例外。 Java 的 OOP 设计哲学将类粘合在一起,直到你的代码开始看起来像一个正常运行的应用程序,这使代码重用变得轻而易举。当有完美的第三方类可以免费使用时,为什么还要编写自己的类呢?结果就是,Java 应用程序中的大部分代码都来自第三方,并且在过去几年中在这个方向上发展得更加迅猛。
不同编程语言所开发的软件中第三方库的占比情况
不同编程语言TOP10三方库的使用情况
上图展示了我们感兴趣的六种语言中最受欢迎的 10 个库是如何随着时间的推移而演变的。在堆积区域图中,每个波段代表使用特定库的扫描存储库的百分比。带子越厚,代表库越受欢迎。当图表的整体高度增加时,表明这 10 个库的受欢迎程度都在增加。如果库的受欢迎程度经常起起伏伏,那么我们可以预见,随着时间的推移,带子的颜色将会大幅增加,并逐渐消失。我们在上图中没有看到这种情况,那些顶级库的流行程度基本上是一致的。开发人员将坚持使用可靠的库,并且可能不会尝试重构他们的代码库来获取最新的热门的可替代软件库。当软件库没有漏洞时,更新进展缓慢,但软件库出现漏洞时,更新速度就相对较快。只要开源软件库的开发者继续修复安全漏洞,开发者们就会继续使用这些库。
在过去几年中,软件中是否使用了更多或更少的存在漏洞的第三方库呢?
近几年不同编程语言开发的软件中使用有漏洞的三方库的占比
在过去四年中,存在已知漏洞的软件库的比例从35%下降到不到10%
尽管存在安全漏洞的软件库的数量有很明显的下降并且大多数组织采用了多种安全扫描能力,但是仍然有 77% 的第三方软件库在漏洞出现三个月后仍未修复。
从积极的方面来看,对第三方软件库存在的漏洞进行补救的时间有了明显的改善。在 2017 年,要达到 50% (半衰期)的临界点需要三年多的时间,而现在只需要一年多一点的时间。
通过分析对比近十年的数据,我们可以看出应用程序的安全性在不断提升:
存在OWASP Top 10 和 CWE/SANS Top 25 中列出的缺陷的应用程序数量占比
上图分析了 OWASP Top 10 和 CWE/SANS Top 25 中列出的缺陷,以及那些被归类为“高危”或以上的缺陷。随着时间的推移,如果仔细观察每一个缺陷,我们就会注意到一些高峰和低谷。尽管线条可能会跳来跳去,总体上都在缓慢地减少。
静态安全测试(SAST)、动态安全测试(DAST)和SCA对比
1、缺陷发现能力对比
静态扫描需要直接查看分析源代码,因此,在不同的编程语言开发的软件中查找的缺陷也不同。静态扫描非常擅长检测内存管理不正确或输入未正确验证的缺陷。鉴于此,静态分析的结果非常依赖于开发语言也就不足为奇了。在C++语言中使用缓冲区/内存管理发现缺陷是很常见的,但是在.NET或Java语言中不存在这些缺陷。因此,即使CRLF注入是静态分析的顶部缺陷类型,它甚至不在C++或PHP的前10个缺陷中。
不同编程语言开发的软件中通过静态分析发现的缺陷数量变化
动态扫描利用运行时环境,并针对运行时环境运行。它没有深入研究底层语言的特性,而是可以在代码的执行和接口中发现更多的缺陷。请注意,此处最常见的缺陷类型通常与静态分析结果不重叠。服务器配置和信息泄漏一直是所有底层语言中发现的主要缺陷类别。这些缺陷在不同的语言中是如此一致,因此不值得展示这些差异。每种语言的总体趋势如下图所示。
通过动态分析发现的缺陷数量变化
软件组合分析是第三种扫描,它通过跟踪各种开源项目和包,然后识别代码库中包含的项目和包来进行操作。这允许与开发人员共享这些库中的所有现有信息。第三方软件中的缺陷可以从各种来源报告,如静态代码扫描、人工代码审计、安全研究人员报告缺陷等。我们再次发现,这些类型的缺陷因语言而异,如下图所示(但请注意,纵轴对不同语言使用不同的比例)。一些语言(Java、JavaScript和Python)在使用时表现出明显的下降趋势,.NET和C++没有显示出它们第三方库中的那种类型的下降。
不同编程语言开发的软件中通过SCA发现的缺陷数量变化
2、缺陷修复速度对比
到目前为止,我们一直在研究应用程序、检测方法、缺陷类型及其流行程度,以及开发人员如何随着时间的推移改变他们的安全实践。但是,实际上又解决了多少问题呢?这是一个很好的过渡点,可以考虑有多少缺陷得到修复,以及修复的速度有多快。通过观察我们一直在追踪的数以百万计的缺陷,并预测任何一个特定的缺陷会持续多久,就可以既考虑到已经修复的缺陷,也考虑到尚未修复的缺陷,使我们能够更准确地度量一段时间内的预期修复率。
从上图可以看出,动态缺陷修复速度最快,SCA缺陷修复速度最慢,静态分析的缺陷修复速度介于两者之间。让我们重点关注上图所示的50%的水平虚线。它代表了修复大约一半缺陷所需的时间,我们可以称之为缺陷的“半衰期”。
在通过SCA识别的缺陷中,甚至有一半都要在一年多后才能修复,这似乎很荒谬——尤其是当我们看到通过动态分析发现的缺陷在同一个半衰期指标下持续不到5个月时。但如果我们告诉你这实际上是一个巨大的进步呢?看看下图,我们跟踪了半衰期指标随时间的变化。从这个历史角度来看,SCA 发现的缺陷展示了巨大的改进。回到2017年,要达到50%(半衰期)的修复率需要三年多的时间,而这一点已经被推到了我们今天所看到的程度:刚刚超过一年。
在查看SCA缺陷并对情况正在改善感到乐观之后,再看看静态扫描。看来修复工作已经从2017年左右的历史低点有所回落,半衰期不到200天。目前,补救措施已放缓至不到300天。这里的部分挑战是,竞争激烈的商业市场要求软件能够及时发布,软件开发团队被迫在及时交付和风险之间做出艰难的权衡。有些缺陷可能无法在截止日期前解决。
如果我们想追踪修复的速度,缺陷修复半衰期是一个很好的指标,但依赖它作为一个完整的衡量标准是一个挑战:因为它不能解释在给定时间段内修复的所有缺陷。为了衡量在一段时间内修复了多少缺陷,我们必须查看开发团队修复缺陷的总体能力。
3、缺陷修复能力对比
为了衡量修复能力,我们查看了一个开发团队在一个月内面临的所有缺陷,然后查看其中有多少缺陷在该月内得到了修复。当然,不同的应用程序会有所不同,但下图显示了过去五年的总体趋势。
下图中的点代表单个应用程序,线代表了总体趋势。请记住,这里的能力是指在给定的一个月内,未解决缺陷总数中已修复缺陷的数量。这为我们提供了每月修复缺陷的百分比。很高兴看到静态缺陷和SCA 缺陷的修复在任何一个月都呈上升趋势,即使增长幅度不大,并且需要更长的修复时间(根据上图可证明)。通过动态分析发现的缺陷的修复已经有点反弹,但随着我们获得更多数据,我们应该可以看到它稳定下来。
不同扫描类型的月度缺陷修复能力
总结
小型模块化应用的敏捷开发已经吞噬了整个世界,无论开发人员是否选择微服务架构、敏感开发模式,如果不能及时修复软件安全缺陷,那么随着时间的推移,安全债务就会不断累积,尽早解决缺陷有助于缓解未来的工作。使用多种类型的扫描(静态、动态和软件组合分析)可以更全面地了解应用程序的安全性,并有助于更快、更全面地修复漏洞。此外,该报告也指出,通过给开发人员培训掌握修复漏洞的技能,并持续教育开发人员,对漏洞的及时修复很有帮助。
开源的代码以及三方软件库对于开发人员来说将继续是福也是祸。我们没有看到任何迹象表明第三方库的使用发生了巨大的变化,甚至开发者使用的库也没有改变。开发者使用的已知缺陷软件库似乎越来越少,这一点让人感到乐观。在整个报告中,最令人振奋的可能是,几乎所有的应用程序都在朝着更安全的应用程序稳步发展。尽管漏洞修复的能力和速度并没有增加。但是将多种类型的工具嵌入到持续集成管道和 IDE 中可以加快开发人员修复漏洞的速度。