Aqua Nautilus 的研究人员发现,下载次数最多的 npm 包中有 8.2% 已被正式弃用,但由于处理包依赖项的做法不一致,实际数字要大得多,接近 21.2%。此外,一些软件包维护者在遇到安全漏洞时,会弃用他们的软件包,而不是报告它们、分配 CVE 或修复漏洞。这些漏洞可能会使开发人员不知道他们正在使用未维护的易受攻击的软件包,并为攻击者创造机会来接管继续使用的未维护代码。
在这篇博客中,我们将解释欺骗性的弃用差距,介绍一种新的开源工具来扫描您的软件包以查找已弃用的依赖项,并解释 Aqua 客户可以采取哪些措施来减轻这些风险。
这项研究是如何开始的
最初,我们的研究重点是通过使用静态应用程序安全测试 (SAST) 来大规模识别漏洞。为了系统地发现这些安全漏洞,我们采用了 Semgrep,这是一款功能强大的 SAST 工具,它利用规则和条件的组合来搜索代码中的模式。
在研究开始时,我们最初针对“唾手可得的果实”漏洞来验证我们的假设。为此,我们使用了 Semgrep 社区的默认规则,搜索 Prototype Pollution、XSS、SQLI、Command injection 等。
在我们的研究过程中,我们发现了几个漏洞。值得注意的是,CVE-2023-26364 已由 Adobe 的安全团队有效解决。但是,由于维护者响应迟钝,我们报告的许多其他漏洞未得到解决。
在发现的漏洞中,有几个漏洞脱颖而出。在我们报告漏洞后,维护人员决定存档存储库而不是修复问题。
一个漏洞报告称,维护者在同一天决定存档作为响应
这让我们想知道其他已弃用的软件包和存档仓库的安全状态。它们是否隐藏着尚未分配 CVE 的未解决漏洞? 如果没有 CVE,安全扫描程序将无法通知用户与这些软件包相关的风险,从而可能使它们暴露在风险之下。
此问题的一个主要示例是已弃用的包。以下是维护者提供的弃用消息:sntp
你可以看到,它们清楚地声明这个包不再维护,这可能会导致严重的安全漏洞,你应该切换到另一个包。然而,正如前面在博客中提到的,并不是每个维护者都向他们的用户展示了这种程度的责任。
考虑到依赖已弃用软件包的风险,我们意识到:任何依赖于已弃用软件包的软件包都可能在不知不觉中变得易受攻击。
请务必承认,依赖项中存在漏洞不一定会危及依赖包。此风险取决于受影响的代码是否实际由依赖包执行。然而,在没有详细的漏洞数据的情况下,最安全的做法是始终更新到最新版本或用替代包替换已弃用的包。
什么是已弃用的软件包
了解与使用已弃用的软件包相关的固有风险会让我们得出一个基本问题:究竟什么构成了已弃用的软件包?
关于已弃用的包的最初想法是检查它是否在 npm 注册表中被弃用,例如包请求:
尽管如此,正如我们之前的示例所示,在某些情况下,维护者选择在 GitHub 中存档包的存储库,而不是在 npm 上正式弃用它。此类操作会促使我们寻找其他条件来确定软件包的弃用状态:
-
如果链接到 npm 包的存储库无法访问,我们是否应该将该包视为已弃用?存储库是否因为已被删除而不再可用(表示已弃用),或者只是将其设为私有?
-
如果 package 没有关联的 repository,我们可以使用什么措施来确定其维护状态?
这些问题没有绝对的答案。对于每个使用 npm 包的组织来说,建立自己的一组标准来确定包的弃用状态是必不可少的,尽管常识表明应谨慎对待“孤立”npm 包。虽然可以采用各种其他标准来确定软件包是否被弃用,包括上次发布日期和上次提交日期等因素,但在本博客中,我们专注于我们认为应该是弃用的主要标准。
Top npm 包的依赖分析
在 npm 中,包可以形成一个复杂的依赖关系图,因此不仅要评估它们的直接依赖关系,还要评估它们的传递依赖关系,即依赖关系的依赖关系,这一点至关重要。此链可以延伸到多个层,从而可能放大单个已弃用软件包的影响。
我们想从下载量前 50K 的 npm 包中检查有多少直接或间接依赖于已弃用的包。
对于此统计分析,我们搜索了已明确弃用或具有直接弃用依赖项的包。我们之所以选择这种方法,是因为即使可能存在深层、易受攻击的包,但如果顶级包不执行易受攻击的代码,它可能不会构成直接威胁。但是,必须承认在深度依赖关系中弃用仍然会产生严重的后果。
在这里,您可以查看顶级 npm 包的弃用结果:
如上图所示,根据官方的 “弃用” 定义,前 50K 个软件包中有 8.2% 被视为已弃用,而根据我们的扩展定义,高达 21% 的软件包被视为已弃用。
如前所述,定义软件包弃用缺乏标准化标准。因此,图表的组成细分因您的弃用标准而异:
-
如果您严格遵守 npm 的弃用状态,则大约 8.2% 的包属于已弃用类别。
-
将已弃用的存档仓库也视为已弃用,则会将弃用率提高到 12.8%。
-
对于那些担心包维护和仓库没有被删除的人来说,添加 GitHub 不可用的标准会导致 15% 的弃用率。
-
最后,如果你寻找由可见的仓库、提交历史和问题跟踪积极维护的软件包,那么包含 'no repository linked' 标准会将弃用率提高到 21%。
根据我们的扩展定义,前 50k 个程序包中已弃用程序包的每周下载量达到 21 亿次下载!
通常建议只使用完全维护的软件包,其中维护者会积极解决安全问题并为软件包提供持续支持。使用未维护的软件包会增加未修复漏洞的风险,甚至威胁行为者会接管软件包以插入恶意代码。因此,建议纳入本博客中介绍的所有标准。
需要注意的是,我们选择分析排名靠前的 npm 包,因为它们是最依赖的包,这意味着所有依赖它们的依赖包也可以标记为已弃用,这表明存在更广泛的问题。
此类依赖包的示例包括
-
通过 – GitHub 已存档,但有 3000 多个包作为其直接依赖项。
-
request – package 已弃用,但它有 55000 个软件包作为其直接依赖项。
Aqua Nautilus 依赖项弃用检查器
现在,我们已经了解了依赖已弃用的软件包对组织来说可能有多么大的风险,那么组织如何检查他们是否直接或间接地依赖于已弃用的软件包呢?
如果我们能够向组织提供有关其已弃用软件工件中隐藏的威胁和依赖关系的见解,他们就能够将某些被认为已弃用的软件包替换为“更健康”的软件包。
为此,我们推出了一个名为“Dependency Deprecation Checker”的新开源工具。此工具可在 GitHub 上找到,可扫描您的 package.json 文件并检查依赖于已弃用软件包的依赖项。
该工具允许您选择组织中被视为已弃用包的标准,以便根据您的需求进行自定义。
该工具目前是概念验证 (PoC),并未全面涵盖已弃用的软件包,但它仍然会产生有洞察力的结果。
以下是使用存储库中提供的示例 package.json 文件执行 Dependency Deprecation Checker 的结果:
我们可以观察到,它打印了已弃用的直接依赖项列表,突出显示了弃用链。这样可以更轻松地确定弃用的根本原因。
摘要和缓解措施
我们的研究揭示了 npm 生态系统中的一个重大问题:很大一部分最常用的 npm 包已被弃用,这对许多项目的稳定性和安全性构成了风险。
当维护者选择弃用受影响的软件包,而不是通过补丁或 CVE 分配来解决安全漏洞时,这种情况就变得很严重。特别令人担忧的是,有时这些维护者不会在 npm 上正式将包标记为已弃用,从而为可能仍然没有意识到潜在威胁的用户留下安全漏洞。
这也引发了开源维护的争论,开源维护者是否应该有义务在空闲时间解决他们参与的开源项目中的漏洞?有一个众所周知的例子,维护者对社区维护他的包的要求感到沮丧,导致他插入恶意代码,你可以在这里阅读更多相关信息。
为了解决这些问题并支持使用 npm 包的组织的安全状况,我们建议执行以下步骤:
-
建立弃用协议:组织应定义在 npm 注册表的名称之外构成已弃用包的内容。这可能包括存储库无法访问或最近缺少维护活动等标准。
-
采用依赖项弃用检查器:我们新开发的工具“依赖项弃用检查器”可在 GitHub 上获得,它为组织提供了扫描其package.json文件以查找已弃用的包依赖项的方法。
-
更新或替换已弃用的依赖项:检测到弃用时,组织应优先更新到维护更积极的软件包。
通过实施这些措施,组织可以显著减少与已弃用的 npm 包相关的漏洞,并维护其应用程序的完整性和安全性。
Aqua 客户应采取的措施:
Aqua 客户可以从我们的软件供应链安全 (SSCS) 解决方案中受益,以灌输防止在其构建中使用已弃用的 npm 包的做法,作为供应链安全和治理整体方法的一部分。
Aqua SSCS 中的缓解措施包括:
-
定期扫描代码依赖项以评估其安全状况,包括识别任何已弃用的依赖项。
-
监控代码依赖项的行为更改,例如使用长时间后突然发布的未固定依赖项版本。
-
使用保障策略建立预防措施,以防止将高风险依赖项集成到您的代码库和云环境中。
原文始发于微信公众号(菜鸟小新):欺骗性弃用:关于 npm 已弃用包的真相
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论