当前位置: 首页 > 科技观察

为什么代码重用仍然是一个安全噩梦

时间:2023-03-14 18:11:28 科技观察

现代软件应用程序是从公共存储库中提取的数千个第三方组件拼接在一起的。这种代码重用对软件行业有很大好处,减少了开发时间和成本,使开发人员能够更快地添加功能,但由于复杂的依赖系统通常难以跟踪管理问题,它也产生了重大漏洞。从第三方代码继承的漏洞多年来一直困扰着应用程序,但在政府支持的软件供应链攻击时代,这个问题比以往任何时候都更加重要。软件组成分析工具可以帮助发现其中的一些风险,但微妙的依赖盲点仍然存在,即使是具有安全意识的开发人员也很难发现所有继承的缺陷。ReversingLabs的安全研究人员最近对NuGet存储库进行的扫描发现,有50,000个程序包使用了一个名为zlib的流行库的过时且易受攻击的版本。他们中的许多人没有明确地将其列为依赖项。依赖性跟踪是最先进的为了找到所有的错误,开发人员不仅需要跟踪他们在应用程序中使用的组件,还需要跟踪这些组件所基于的第三方库和包。依赖链可以深入很多层。达姆施塔特大学的研究人员在2019年对npm存储库进行的分析发现,平均而言,导入单个JavaScript包会引入对39个不同维护者的79个其他包的隐式信任。当时,研究人员还发现近40%的软件包所依赖的代码至少存在一个公开漏洞。一个问题是,只有与同一存储库中的包相关的依赖项才会被包存储库及其相应的包管理工具跟踪。但这并不是第三方代码进入项目的唯一途径。一些开发人员静态链接库或手动编译来自包存储库外部存在的其他项目的代码,这些信息不容易通过自动扫描工具找到。ReversingLabs发现了50多个NuGet包,其中包含被主动利用的漏洞,因为它们捆绑了7Zip、WinSCP和PuTTYgen的过时和易受攻击的版本。这些是流行的压缩或网络程序,它们不直接托管在NuGet上,但可能有其他开发人员在NuGet上为它们创建的包装器。NuGet是.NET编程语言的主要存储库,托管在那里的大多数组件都以ZIP存档的形式提供,带有.nupkg扩展名,其中包含预编译的Windows.DLL库,旨在导入到其他软件项目中。ReversingLabs发现的一个易受攻击的NuGet包名为WinSCPHelper,它是WinSCP的包装库。它允许集成它的应用程序通过SFTP协议管理远程服务器上的文件。WinSCPHelper自2017年以来未在NuGet上更新,但上一版本自发布以来已下载超过34,000次,在过去6周内下载了约700次。最新的WinSCP版本是5.17.10,其中包含针对关键远程代码执行漏洞的补丁,但与WinSCPHelper捆绑的版本是旧版本-5.11.2。“虽然在这种情况下,被分析的包明确声明它使用WinSCP,但它并没有在依赖列表中公开版本,你也无法轻易发现哪些漏洞影响了它的基础依赖,”研究人员说。“是体力活,还是可以做的,就是要费点功夫”。识别无声错误但追踪依赖关系可能比这更难。以zlib为例,它是使用最广泛的开源数据压缩库之一,最初编写于1995年。这个库几乎已成为事实上的标准,并由其维护者作为源代码提供。这意味着开发人员倾向于自己编译它并将其静态链接到他们的项目中,通常不会提及它的存在,因为它无处不在。通过静态文件分析,ReversingLabs发现了50,000多个使用2013年发布的zlib1.2.8版本的NuGet包,其中包含四个高危或严重漏洞。一些已识别的包通过其他未明确列出依赖项的第三方组件继承了这个旧的zlib版本及其漏洞,促使研究人员将这些称为无声漏洞。ReversingLabs提供的一个例子是一个名为DicomObjects的NuGet包,它在医学中实现了数字成像和通信(DICOM)协议。DICOM是一种用于传输和管理医学影像数据的标准。它广泛应用于医院,并得到许多成像设备的支持,例如医疗扫描仪、打印机、服务器和工作站。DicomObjects被医疗软件开发人员用来轻松构建DICOM解决方案,下载量接近54,000次,由一家名为MedicalConnections的英国公司维护。该软件包将Microsoft.AspNet.WebApi.Client、Newtonsoft.Json和System.Net.Http列为依赖项,但根据ReversingLabs,它还捆绑了一个名为ceTe.DynamicPDF.Viewer.40.x86.dll的商业PDF库,但没有明确提及。DynamicPDFViewer在NuGet上被列为单独的包,但捆绑在DicomObjects中的版本是旧版本,包括zlib1.2.8。“这是最常见的软件维护问题之一,”研究人员说。“开发人员创建了一个包,决定使用第三方软件,但在随后的更新过程中,依赖被忽略了。在这种情况下,情况更糟,因为任何地方都没有明确引用DicomObjects包依赖DynamicPDF.Viewer。我们无法知道DynamicPDF.Viewer依赖于易受攻击的zlib库。以这种方式堆叠隐藏的依赖项会导致多层无声漏洞,并使软件更难维护和审核”。MedicalConnections没有立即回应置评请求。另一个例子是一个非常流行的包,称为librdkafka.redist,这是一个实现ApacheKafka协议的C库。ApacheKafka是一种开源的高性能流处理框架,用于处理实时数据传输。librdkafka.redist包的下载量为1890万次,其中31.2万次是2个月前发布的最新版本1.7.0。此版本的librdkafka.redist使用zlib1.2.8,但在NuGet或GitHub上的项目依赖列表中未明确说明。一年多前,该问题已在GitHub上的项目错误跟踪器上报告,目前已标记为在1.8.0版中修复。该项目的首席开发人员MagnusEdenhill审查了四个zlib漏洞,并表示其中只有两个适用于librdkafka,通过Kafka消费的消息成功利用它们的风险似乎非常低。Edenhill没有立即回应置评请求。其他13个NuGet包依赖于librdkafka.redist,其中一些是由一家名为Confluent的数据基础架构公司开发的,该公司拥有许多大型企业客户。“安全软件开发是一个复杂的问题,因为它涉及处于多个开发阶段的许多参与者,”ReversingLabs研究人员说。“无论你的公司生产什么类型的软件,迟早你都需要将第三方依赖项纳入你的解决方案。这将引入管理安全和代码质量风险的需要。软件供应链攻击对企业的威胁越来越大在线社区很大。它们是传统漏洞的DDoS模拟”。供应链风险NuGet并不是唯一具有这种脆弱依赖问题的软件包存储库,并且可以争辩说,并不是NuGet或其他库迫使开发人员更加关注这些问题。但是,一些平台比其他平台更主动。GitHub主动扫描托管在其平台上的公共代码存储库,分析它们的依赖关系,并在这些依赖关系中存在任何已知漏洞时通知其所有者。该公司维护着一个公共咨询数据库,其中包括已知的npm(JavaScript)、RubyGems(Ruby)、NuGet(.NET)、pip(Python)、Maven(Java)以及刚刚宣布支持Go模块的漏洞。开源治理公司Sonatype在其《2020年软件供应链报告》报告中指出据统计,下一代攻击数量同比增长430%,黑客试图主动向开源软件项目中注入恶意软件,试图毒害更多项目和应用在他们的依赖链上的链接。黑客利用开源组件中已知漏洞的传统攻击仍然很强劲,但利用的时间已经减少,攻击者在公开披露的几天内就利用了新发现的漏洞。与此同时,半数公司花了超过一周的时间才了解这些漏洞,并在一周或更长时间内采取缓解措施。攻击者显然对利用软件供应链感兴趣,但数以千计具有继承漏洞的软件包仍在公共存储库中,并充当企业软件的构建块。