什么是依赖混淆?

中科天齐软件源代码安全检测中心

共 2357字,需浏览 5分钟

 ·

2022-11-08 11:22

现代应用程序是使用逻辑上独立的组件构建的,每个组件执行一组可以直接在软件中使用的功能。这些软件组件,也称为依赖包或库,存储在公共或私有存储库中,可以跨多个软件供应链重复使用。依赖关系混淆是如何导致安全漏洞的?

什么是依赖混淆?

当两个或多个依赖项相互冲突时,应用程序交付中的依赖项就会出现混淆,并且系统不知道首先使用哪一个依赖项。在这种情况下,当攻击者诱骗软件包管理器从公共库而不是合法库中提取恶意包时,就会利用依赖关系混淆攻击。此类攻击也称为供应链替换,它利用了用户无需为组件指定源存储库的事实,包安装程序会自动处理下载和配置。

典型的供应链替代攻击的工作流程如下所示:

网络攻击者发现目标组织内使用的私有包名称

网络攻击者构建软件包的恶意版本

恶意包随后被添加到公共代码存储库

下次当包安装程序从存储库请求依赖包时,它将从公共库而不是内部注册中心下载恶意代码文件

随着依赖包在现代软件开发中变得越来越普遍,流行的编程语言已经简化了它们的包安装程序,以抽象安装和管理第三方组件所涉及的任务。不幸的是,自动的包更新和安装助长了网络攻击者用恶意代码文件替换合法包的意图。

网络攻击者还采用多种方法来诱骗包管理器下载恶意依赖项,包括:

DNS 欺骗 – 通过更改代码库中的存储库路径,指示包管理器从外部库中提取依赖项

命名空间 – 将代码文件上传到与内部库中使用的名称相同的公共存储库中

脚本 – 修改基础结构即代码 (IaC) 和其他配置脚本以更改依赖项路径并诱骗系统安装恶意包

依赖混淆攻击包

依赖混淆攻击有效负载可分为不同类型,包括:

域名仿冒的软件包

域名仿冒依赖项包针对错误输入错误 URL 或搜索词的用户。攻击者战略性地将模仿包放置在错误的搜索查询或 Web 链接中以利用此类实例。

网络攻击者常用的一种方法是在容易访问的公共注册表中声明多个拼写错误但几乎相同的包名。例如,假设合法的包存储在一个名为darwin-qa的存储库中,攻击者倾向于注册许多名称与原始存储库类似的包源,如darwin-qa、darwinqa、darwin-aq和dawin -qa。黑客使用这些恶意存储库来存储利用脚本;当受害者输入错误的搜索查询、CLI命令或URL时,他们最终下载了错误的包。

最新版本包

黑客为这些版本的公共存储库分配了比生产环境中使用的最新合法软件包更高的版本号。在枚举所有正在使用的包及其各自的版本号后,攻击者会在包中构建恶意依赖项,为包分配更高的版本号,并将其存储在公共存储库中。如果应用程序的包管理器配置为获取最新版本,则最终将从公共存储库中提取黑客的依赖项包。

黑客为这些公共存储库版本分配了比生产环境中使用的最新合法包更高的版本号。在列举所有正在使用的包及其各自的版本号之后,攻击者在包中创建恶意依赖项,为包分配更高的版本号,并将其存储在公共存储库中。如果应用程序的包管理器被配置为获取最新版本,它将最终从公共存储库中提取黑客的依赖包。

具有不同包和导入名称的依赖项

由于命名规则和其他约束,包的名称可能与其导入命令中使用的名称稍有不同。大多数包管理器都称只需单击一次就可以下载、提取和安装依赖包。没有进行适当验证就快速安装这些依赖项的开发人员经常无法检查使用的名称并安装错误的组件。恶意行为者利用这种混乱,将损坏的代码包与其他可能的名称放在一起,实施一种简单但有效的攻击策略。

依赖关系混淆漏洞类型

依赖混淆漏洞根据受影响的编程语言或系统进行分类。一些常见的依赖混淆漏洞类型包括:

NPM 依赖关系混淆

在 JavaScript 应用程序中经常发现依赖混淆漏洞,其中内部package.json文件将整个项目的依赖关系作为构建过程的一部分嵌入到公共脚本中。由于 NPM 是 Node.js 包的主要存储库,因此已知在没有自动化、经过安全性检查的包更新的情况下,它可能包含依赖混淆漏洞利用脚本。

在以下情况下,使用 NPM 存储库中的包的组织容易受到依赖项混淆攻击:

组织的开发管道缺少内部注册表

开发人员未能在包管理器中包含适当的配置信息

NPM 环境配置文件(.npmrc)未能包含正确的内部注册表

PIP依赖关系混淆

PIP是驻留在PyPi在线存储库上的Python库的默认安装程序。PIP在默认情况下被认为是不安全的,因为它同时检查指定和公共包索引;如果找到多个依赖项,则最终安装最新的依赖项版本。为了利用这种易受攻击的结构,黑客会上传一个版本号更高的恶意版本,然后自动拉出恶意代码替换原始包。

缓解依赖关系混淆漏洞

缓解依赖关系混淆攻击的技术包括:

版本固定

依赖项固定显式声明应用程序将使用的包的版本。有些包管理器允许开发人员将他们的应用程序固定到不同的版本,而不是单一的版本。通过确保所有部署都使用相同的Git(或其他版本控制系统)存储库,冻结依赖项版本可以实现迭代安装和更精细地控制依赖项。

命名空间和依赖项范围

大多数联机存储库使用范围或命名空间来隔离和控制组织的技术框架内的资源。在典型方案中,组织拥有范围或命名空间,而存储库建立注册和验证过程来验证上传。为了确保从受信任的存储库中提取所有组件,建议的做法是强制实施策略,要求开发人员在获取包时仅引用定义的命名空间或作用域名称。

客户端验证

包安装程序应该支持客户端验证,例如哈希检查模式,根据存储在客户端上的哈希计算所有下载的包。一些包存储库还包括验证已安装组件PGP签名的插件。这种完整性验证有助于加强安全态势,同时阻止需要控制存储库服务器和客户端机器的成功利用。


来源:

https://crashtest-security.com/

浏览 88
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报