包管理器已成为现代软件开发过程的重要组成部分,它使开发人员可以重用第三方代码,共享自己的代码,最小化其代码库并简化构建过程。但是,最近的报告表明,攻击者滥用了软件包管理器来分发恶意软件,这给开发人员和最终用户带来了重大的安全风险。eslint-scope这个在Npm每周有数百万下载的软件包,被盗用以窃取开发人员的凭据。为了解使最近的供应链攻击成为可能的安全漏洞和错误信任,本文提出了一个比较框架,以定性评估解释型语言的软件包管理器功能和安全性。基于定性评估,应用了众所周知的程序分析技术(例如元数据,静态和动态分析)来研究注册表滥用。最初工作发现了339个新的恶意软件包,已报告将其删除。软件包管理器维护者确认了339个报告的软件包中的278个(占82%),其中三个软件包的下载量超过100,000。对于这些软件包,已经获得了官方的CVE编号,以帮助受害者快速删除这些软件包。
0X01 Introduction
许多现代的Web应用程序依赖于解释型编程语言,因为他们有丰富的库和包。 PyPI,Npm和RubyGems等注册表(也称为软件包管理器)提供了一个集中式存储库,开发人员可以搜索并安装附加程序包以帮助开发。例如,开发Web应用程序的开发人员可以依靠Django,Web2py和Flask之类的Python Web框架来提供用于快速开发的代码。注册管理机构不仅使开发过程更加高效,而且还创建了一个大型社区,可以协作并共享开源代码。不幸的是,攻击者找到了渗透这些社区并用恶意代码感染流行软件包的方法,这些恶意代码可以窃取凭据,安装后门,甚至滥用计算资源进行加密货币挖掘。
此问题的影响不仅限于一次性的小型Web应用程序,还包括大型网站,企业甚至政府组织,它们依赖于开源的解释型程序语言来实现不同的内部和外部应用程序。攻击者可以通过简单地破坏注册表的软件供应链来渗透防御良好的组织。例如eslint-scope,一个在Npm每周有数百万下载的软件包,被盗用以窃取开发人员的凭证。同样,在RubyGems中下载量超过1亿的rest-client,也在Web服务器上留下了远程代码执行(RCE)后门。这些攻击表明,恶意软件如何通过实施软件供应链攻击来秘密地访问各种组织。
本文提出了一个框架MALOSS,这是一个为解释型语言量身定制的自定义框架,可以用它来经验性地研究软件包管理器的安全性,已经开放分析的源代码(https://github.com/osssanitizer/maloss ),并根据要求提供收集的恶意软件样本以供研究之用,以帮助将来进行有关提高包装管理者安全性和防御供应链攻击的研究,供社区参考或帮助分析和识别可疑包。
0X02 Background
注册表(Registry)是用于代码共享的平台,并且在软件开发过程中起着至关重要的作用。首先介绍参与开发,管理和使用来自注册表的软件包的四个主要利益相关者,即注册管理机构(RM),软件包维护者(PM),开发人员(Dev)和最终用户(Users)。
A.主要利益相关者
在上图的软件包管理器生态系统中概述了主要利益相关者的特征及其简化的关系。请注意,利益相关者是可以分配给一个人的角色。
注册管理机构:注册管理机构管理注册表维护框架,并负责运行注册表,这些注册表是托管PM所开发软件包的集中存储库。注册中心为开发人员提供搜索和安装功能,以帮助在中央存储库中组织软件包。注册管理机构通常由两部分组成:一个管理和提供软件包的Web应用程序(例如pypi.org)和一个提供对软件包的轻松访问的客户端应用程序(例如pip)。注册管理机构需要在允许PM进行发布(即,通过身份验证写入)其程序包之前进行PM的注册。另一方面,无论是否注册,Dev都可以从注册表中查询和安装(读取)。
软件包维护者:软件包维护者管理程序包维护框架,并负责开发,维护和管理包。软件包维护者通常使用诸如GitHub之类的代码托管平台来管理其开发并与其他贡献者进行协作。他们可能会收到对他们的项目感兴趣的贡献者的pull请求,从而为增强和维护提供社区支持。他们可以使用持续集成和持续部署(CI / CD)管道来自动化发布过程(即构建和部署)。
开发人员:开发人员管理应用程序开发框架,并且是已发布软件包的使用者。他们负责找到在其软件中使用的正确软件包,并将其产品发布给最终用户。开发人员致力于开发其软件中的独特功能,并从注册表中重用软件包以实现常见功能。而且,开发人员需要解决重用软件包的问题,例如已知的漏洞和不兼容性。
终端用户:尽管不直接与注册表交互,但终端用户仍然是生态系统中的重要利益相关者。用户位于下游,并在浏览器,移动设备或物联网(IoT)设备上使用来自Dev的服务或应用程序。用户最终是为整个生态系统付费并为其提供动力的客户,但是,除了反馈外,他们对软件没有控制权,并且可能会受到上游安全问题的影响。
B.注册表滥用
在上图中列出了供应链攻击的选定列表,涵盖了不同类型的注册管理机构(全系统范围内的解释型语言)。2016年,Tschacher演示了针对包装管理人员的概念验证攻击。该攻击使用了错别单词,这是一种拼写错误名称的技术,它会等待用户安装流行的软件包时拼写错误名称,从而导致安装了恶意软件包。截至2019年8月,已经在不同的注册表(PyPI,Npm,RubyGems等)中报告并删除了300多个恶意软件包。在下图中,按上传年份汇总了上传到注册表中的恶意软件包的数量及其相应的下载计数。注意到,这些计数是记录/检测到的攻击,是所有攻击(已知和未知)的子集。如图显示仅2018年一年,就有100多个恶意软件包,累计下载量超过6亿次。
拼写错误只是攻击的一种,而漏洞分析平台Snyk的最新报告则将攻击分为三种类型,即:拼写错误,帐户劫持和社会工程。劫持是通过凭证盗窃来破坏帐户的行为,而社会工程学是一种欺骗策略,诱骗软件包存储库的所有者转移所有权。报告强调,域名抢注是最常见的攻击策略,因为大多数注册管理机构都没有执行Loden所示的任何安全策略。帐户劫持的发生是由于攻击者可以猜测的凭据薄弱,而社会工程攻击利用了开源项目的协作性质。不幸的是,社区的焦点一直是通过Synode,NodeCure和ReDoS等平台在程序包代码中查找错误。BreakApp使用运行时隔离不受信任的程序包,但是由于需要开发人员的协同而遭受了实用性的困扰,并且无法应对诸如密码劫持之类的攻击。注册管理机构已经意识到了这些问题,并主动采取了一些安全性增强措施,例如软件包签名和两因素认证(2FA)。尽管做出了这些努力,但上图显示了注册表中恶意软件包的数量正在上升。
C.确保注册安全的挑战
为了应对针对包装管理者的供应链攻击,需要对生态系统进行深入分析,以了解滥用哪个部分,由谁负责,如何最好地防止此类攻击以及如何进行补救。尽管针对每种威胁提出临时解决方案可能很简单,例如2FA帐户入侵,但要系统地了解薄弱环节并提出对策仍然是挑战。为了实现这一目标,本文提出了一个比较框架,以定性分析PyPI,Npm和RubyGems注册表。选择这些程序包管理器是因为它们在开发人员中很流行,并且看到的供应链攻击最多。
定性分析的重要意义之一是,注册管理机构目前对发布软件包的审核过程很少甚至没有。因此,在野应该仍然存在更多未知的恶意软件。为了验证这一点,应用了众所周知的程序分析技术(例如元数据,静态和动态分析)来研究注册表滥用。但是,现成的工具存在准确性和缺乏领域知识的问题。首先,由于这些程序包可能具有大量依赖性,因此直接将现有的静态分析工具应用于这些程序包不仅会导致大量的时间和空间开销,而且还会在重复分析常用程序包时浪费计算资源。例如,eslint和electronic都在Npm上重复使用了100多个包,包括间接依赖项。受StubDroid的启发,本研究实现了模块化的静态分析,该分析将依赖关系汇总为多种格式,以供进一步重用。其次,这些包是用动态类型的语言编写的,并且在执行方面很灵活,从而导致静态分析不准确,并且动态分析中的运行时要求也很复杂。在这项研究中,将采取尽力而为的方法来分析软件包的行为,并利用从现有供应链攻击中获得的见解来标记可疑事件,然后反复检查结果以识别并报告恶意软件包。
0X03 Methods
A.定性分析
自2018年以来,本文的研究者就一直在跟踪针对注册表的供应链攻击,重点是承受大多数攻击的PyPI,Npm和RubyGems。通过镜像这三个注册表,获得了312个报告的攻击样本。本为提出框架的灵感来自于对软件包管理生态系统中的管理和开发过程进行建模。
1)注册表特征:
注册表是软件包管理器生态系统的核心组件,并提供诸如软件包托管和帐户保护之类的方法。在下表中列出了PyPI,Npm和RubyGems的特征,分为三类,即功能性,审查和修复。
功能性:作为供应商的PM可以访问帐户并在注册表上发布和管理其软件包,而作为消费者的Dev可以从注册表中选择并安装软件包作为依赖项。每个注册中心在Devs的系统上都有不同的安装方式以及PM的代码传送方法。访问(Access)是指注册管理机构如何对PM进行身份验证以发布程序包。本文研究与帐户安全性相关的功能,例如公钥身份验证和多因素身份验证(MFA)。发布(Publish)是指软件包如何打包并发布到注册表,将研究发布方法,例如由PM上传并通过软件包开发存储库进行引用。此外,还将研究打包功能,例如签名和命名规则(例如拼写保护)。管理(Manage)是指如何管理软件包以及允许对软件包进行哪些控制,包括按版本删除软件包,弃用该软件包或添加授权的协作者。选择(Select)是指评估或信誉评分,可帮助开发人员选择要信任并添加为依赖项的软件包,本文将研究与存储库和作者的评级和声誉有关的标准。安装(Install)是指Devs如何安装软件包,例如可以运行其他代码的安装挂钩,可以指定安全依赖项的依赖项锁定以及软件包是否可以包含专有代码。
审查:本文定义了注册管理机构可以实施的审查方法,以主动保护用户访问并检测易受攻击的软件包和恶意软件包。元数据(Metadata)是指对给定程序包的元数据分析,其中包括依赖性分析,作者信息,更新历史记录和其他打包的组件。静态(Static)是指执行样式分析和逻辑代码分析。这可能包括查找易受攻击或恶意的代码。此外,它还包括使用防病毒(AV)解决方案扫描二进制组件。动态(Dynamic)是指通过动态执行软件包并监视可疑行为(例如网络连接和可疑文件访问)来分析软件包的行为。
修复:RM识别出需要进一步调查的异常后,安全团队将对事件进行调查,并进行清除和通知。删除(Remove)是指RM根据报告主动删除软件包,基本操作包括删除受影响的程序包并禁用发布者的帐户。通知(Notify)是指RM将有问题的软件包通知公众的机制。例如,RM可以在git repo上创建问题以通知PM,或者通过电子邮件联系PM。这还包括他们通知谁,如RM可以将违规包通知公共受害者,例如PM。更具前瞻性的通知将通知开发人员和发布公告,以通知其他受害者并提出修复建议。
2)威胁模型:
本文考虑了旨在利用软件包管理器生态系统中的上游利益相关者(即PM和RM)的供应链攻击,以扩大其对下游利益相关者(即开发者和用户)的影响,调查了有关供应链攻击的现有报告,并详细说明了它们的攻击媒介和恶意行为。
在供应链攻击中,将受害者视为下游利益相关方,例如开发人员和用户。开发人员可以直接被利用来窃取其证书或损害其基础架构,也可以间接地作为通过其应用程序或服务与用户联系的渠道。可以利用用户窃取其凭据或损害其设备。窃取(Stealing)是指收集敏感信息并将其发送回攻击者。可以收集或窃取各种类型的信息,其范围从对机密性较低的机器标识符可用于跟踪敏感信息,包括秘密令牌,加密货币,密码甚至信用卡,这些信息可能导致进一步妥协或造成经济损失。后门程序(Backdoor)是指将代码执行后门程序留在受害机器上。可以通过各种方式来实现后门,它可以是特定属性(例如cookie),特定有效负载或允许任何命令的反向壳代码生成(例如eval)。
破坏(Sabotage)是指破坏系统或资源。由于隔离原因,这在浏览器中不太严重,但对开发人员基础设施和终端用户设备却很关键。常见的事情是通过删除或加密文件系统来破坏系统并索要金钱(勒索软件)。加密劫持(Cryptojacking)是指利用受害者机器的计算能力进行加密挖掘,加密劫持软件是一种新兴的恶意软件家族,在浏览器和其他平台中也可以看到。病毒(Virus)是指利用一个人可以同时是开发人员和PM的事实来传播恶意软件,以感染其维护的软件包。恶意广告(Malvertising)是指利用访问受感染网站或使用受感染应用程序的最终用户来点击与攻击者发布者帐户相关的广告,从而为他们带来收入。概念证明(Proof-of-concept)是指没有真正危害的软件包,但是可以证明软件是恶意的。
3)安全漏洞和信任破坏:
注册表被利用是由RM的实现错误引起的,但它很难启动并且很少见。域名窃取和发布是由于RM对PM的隐式信任而导致的。由于PM的安全性机制不足以及RM对其提供的代码和基础架构的安全性的隐式信任,导致了基础结构的损害。
为了更好地理解信任破坏,在上表中列出了利益相关者的信任模型。 RM是生态系统的中央主管部门,因此PM和Devs必须信任RM才能采取良性和负责任的行动。但是相反,尽管RM仍然可以信任大多数PM和Devs作为社区,但是由于潜在的攻击者,RM不应信任所有PM和Dev。由于潜在的恶意贡献者和内部人员不满,PM与贡献者和其他PM进行交互,并且还应削弱其对多数信任或基于信誉的信任。开发者和用户作为生态系统中的下游成员,不能完全信任上游利益相关者,尽管他们可能会添加一些安全机制来进行保护。另一方面,开发人员会通过网络与用户交互,但对他们不信任。
B.MALOSS
上图介绍了MALOSS的工作流和内部组件,该组件由四个组件组成:元数据分析,静态分析,动态分析和真阳性验证。来自注册表的程序包由三个分析组件处理,以生成显示可疑活动的中间报告。从报告的攻击中总结出一个启发式规则列表,以进行程序包过滤和标记,当遇到误报时,这些规则将得到迭代改进。
1)元数据分析:
元数据分析着重于收集软件包的辅助信息(例如,软件包名称,作者,租赁,下载和依赖项),并根据不同的标准对它们进行汇总。所有信息均直接从注册表API中检索。元数据分析可以标记可疑软件包,并识别类似于已知恶意软件的软件包。例如,包名称的编辑距离可以帮助根据包的名称对包进行分组,从而可以确定流行包的抢注候选者。作者信息可以帮助根据作者对软件包进行分组,从而可以识别来自已知恶意作者的软件包。元数据分析还包括检查软件包中随附的文件类型,以识别是否存在嵌入式二进制文件或本机扩展名。
2)静态分析:
静态分析专注于为每个程序包管理器分析相应解释语言的源文件,并跳过嵌入式二进制文件和本机扩展。该分析包含三个组件,手动API标签,API使用情况分析和数据流分析。为了在给定大量依赖的情况下进行处理,使用程序包摘要执行模块化分析。
手动API标签:如上图所示,在静态分析中,关注四种类型的运行时API,即网络,文件系统,进程和代码生成。网络API允许通过各种协议(例如套接字,HTTP,FTP等)进行通信,它们已用于泄漏敏感信息、获取恶意有效载荷等。文件系统API允许文件操作,例如读取,写入,chmod等,它们已用于泄漏ssh私钥、感染其他软件包。进程API允许进程操作,例如进程创建,终止和权限更改,它们已被用来生成单独的恶意进程。代码生成API(CodeGen)允许运行时代码生成和加载,这包括臭名昭著的评估以及诸如Node.js中的vm.runInContext,它们已用于加载恶意有效负载。
对于每个注册表的运行时,研究人员手动检查它们的框架API,并检查它们是否属于上述任何类别。为了进行数据流分析,进一步将它们标记为数据源,前提是它们可以返回敏感或可疑数据,而数据宿(接收器)则可以对输入执行可疑操作。请注意,API既可以是源,也可以是接收器。 Node.js中的https.post可以检索可疑数据并发送敏感信息。另外,某些接收器API不必与源一起使用来执行恶意行为。
例如,Node.js中的fs.rmdir是一个接收器,如果其参数来自用户输入,则会发出警告。但是即使没有源,也可以通过将输入路径硬编码到根文件夹来使用fs.rmdir破坏用户计算机。因此,需要同时识别可疑的API及其流程。上表更详细地显示了手动标记结果。
API使用率分析:将包的源文件解析为抽象语法树(AST),并在AST中搜索手动标记的API的用法。对于全局名称空间中的API(例如,Python中的eval),使用它们的名称将它们与函数调用进行匹配。对于是类的静态方法或模块的导出函数的API(例如,Node.js的vm.runInContext),通过跟踪类或模块的别名并匹配其全名来确定其用法。对于作为类的实例方法的API,由于以动态类型的语言标识它们是一个未解决的问题,因此进行权衡并以两种方式标识其用法:仅方法名和具有默认实例名的方法名。尽管前者可能会估计偏高,而后者可能同时具有漏报和误报,但认为它们仍可用于估算API使用率。例如,通过处理上面的eslint-scope的恶意代码段,可以确定下载恶意负载的静态方法https.get和执行它的全局函数eval。
此外,程序包可以具有依赖关系,并可以通过其依赖关系导出的函数间接调用可疑的API。例如,上面代码显示的discord.js-user通过其依赖性请求窃取了discord令牌。处理间接API使用情况的一个直观解决方案是分析每个程序包及其依赖关系,但这可能导致对常见程序包的重复分析,并在给定过多依赖关系的情况下可能耗尽资源。因此,为了提高效率并减少故障,执行模块化的API使用率分析,该分析仅对每个软件包进行一次分析。首先构建所有程序包的依赖关系树,然后分析没有依赖关系的程序包的API使用情况。然后,到依赖关系树,并结合软件包的API及其依赖关系。令Pk表示软件包k的API,i表示k所依赖的软件包,将k的组合API计算为⋃iPi⋃Pk。
数据流分析:为了执行数据流分析,调查和测试了每种解释语言的开源工具,并为Python选择了PyT,为JavaScript选择了JSPrime,为Ruby选择了Brakeman。将这些工具调整为使用源和接收器的自定义配置来分析包,并在任何源-接收器对之间输出识别出的流。
与API使用率分析类似,数据流分析需要处理依赖项外的流或依赖项。StubDroid建议总结Java包的依赖关系以加快后续数据流分析的速度。受StubDroid的启发,本研究在包上运行数据流分析以检查其导出的函数是否为返回源于已知源的值的间接源,还是返回其参数支持的间接接收器,或返回从参数派生的值的传播节点。当遍历所有程序包的依赖关系树时,将输出已标识的流以及间接源,间接接收器和传播节点,这些流将合并到自定义配置中以进行后续分析。例如可以首先对请求进行汇总,以发现其导出的功能请求调用了诸如https.post之类的网络接收器,然后分析上段代码中的代码以识别通过网络泄漏令牌的恶意流。
3)动态分析:
动态分析的重点是执行程序包和跟踪系统调用。与静态分析相比,动态分析会考虑源文件,嵌入式二进制文件和本机扩展名,但无法查看运行时环境(例如无法跟踪评估)。该分析包括两个部分:在Docker容器中用于沙箱的包执行和使用Sysdig进行效率和可用性的动态跟踪。
包执行:软件包可以以多种方式使用,例如独立工具或库,应在动态分析中加以考虑。因此,以四种方式执行软件包,即安装,嵌入式二进制,导入和功能(install, embedded binary, import ,functional)。对于安装,运行安装命令(例如npm install \<name>)来安装软件包,该软件包会触发自定义的安装hook(如果有),并允许攻击者以用户的特权采取行动。对于嵌入式二进制文件,可以从程序包中运行可执行文件,因为攻击者可能会包含预构建的二进制文件或混淆的代码以阻止调查。对于导入,将软件包作为库导入,以触发攻击者可以利用的初始化逻辑。对于功能,对导出的功能和库类进行模糊处理以揭示其行为。当前的原型调用导出的函数,使用空参数初始化类,并递归调用模块和对象的可调用属性。在执行软件包时,使用Docker容器作为沙箱,以保护基础系统免受下面代码中destroyer-of-worlds之类的恶意软件的破坏,这些恶意软件滥用了系统资源。
动态跟踪:为了捕获与底层系统交互的过程,在基于Linux的系统中有三种流行的工具,即Strace,Dtrace和Sysdig。经过相互比较,选择Sysdig作为跟踪工具,因为它具有很高的效率和良好的可用性。为了充分利用计算资源,并行分析多个程序包,每个程序包都在一个单独的Docker容器中,其名称对程序包信息(例如名称,版本等)进行编码。Sysdig捕获系统调用跟踪并将其与用户空间信息(例如容器名)相关联,从而允许将行为与不同的容器和包装区分开来。在进行原型制作时,跟踪与IP,DNS查询,文件和进程相关的系统调用,并将它们转储到文件中以进行进一步处理。
4)真阳性验证:
验证步骤是半自动化的,包括基于启发式规则标记可疑软件包的自动化过程以及检查恶意程序和更新规则的手动过程。更新的规则用于迭代筛选和缩小可疑包的范围。通过从现有供应链攻击和其他恶意软件研究中学习,指定了一组初始启发式规则。规则的完整列表如下表所示。
元数据分析规则:要标记抢注域名的候选人,使用编辑距离来标识名称与在注册机构内部或整个注册机构中的流行名称相似但作者不同的软件包。为了通过推理找到可疑的候选者,如果软件包依赖于已知的恶意软件或具有相似的作者和发布模式,则将其标记。为了通过附带的文件类型识别可疑候选者,如果软件包附带了预构建的二进制文件(例如Windows PE和Linux ELF文件),会对其进行标记。
静态分析规则:首先,受恶意软件通常在安装过程中执行恶意代码的启发,使用自定义的安装逻辑标记软件包。其次,受基于帐户入侵的恶意软件的启发,该恶意软件通常会保留现有的良性版本并发布新的恶意版本,如果最近发布的版本使用以前未见过的网络,进程或代码生成API,会标记软件包。第三,受到窃取和后门行为的恶意软件的启发,通常涉及网络活动,使用某些类型的流来标记程序包,例如从文件系统源到网络接收器,从网络源到代码生成接收器的流。
动态分析规则:受窃取和后门需要网络通信等行为的启发,标记与意外IP或域联系的软件包,其中预期的IP或域来自官方注册表(例如pypi.org)和代码托管服务(例如github.com)。其次,受恶意行为的启发,通常涉及对敏感文件的访问,如果程序包写入或读取此类文件(例如,/ etc / sudoers,/ etc / shadow),会对其进行标记。第三,受密码劫持通常催生加密过程的启发,用意外的进程标记程序包,其中预期的程序被初始化为注册表客户端(例如pip)。
但是,为了提供RM或PM采取行动的证据,必须手动调查可疑软件包以确认其恶意或将其标记为误报,以帮助更新启发式规则。为了避免在更新规则时重新计算,将分析的中间结果进行缓存。根据规则和手动标记过程反复执行过滤过程,以报告恶意软件。
0X04 Findings
从前文中最初的启发式规则集开始,反复标记可疑程序包,更新规则,最终找到339种新的恶意软件,其中包括PyPI中的7种恶意软件,Npm中的41种恶意软件和RubyGems中的291种恶意软件。分别向RM报告了这339个新的恶意软件,278个(82%)已被确认和删除,其中PyPI的7个恶意软件中有7个,Npm的41个恶意软件中有19个被删除,RubyGems的291个恶意软件中有252个被删除。在已删除的软件包中,其中三个(即paranoid2,simple_captcha2和datagrid)下载量超过10万,表明存在大量受害者。因此,本研究要求他们提供CVE(CVE-2019-13589,CVE-2019-14282,CVE-2019-14281),希望潜在的受害者能够及时获得补救的通知。此外,在下表中列出了61个已报告但尚未删除的软件包。
在本节中,将339种新报告的恶意软件与312种社区报告的恶意软件结合起来,并使用前文提出的框架和术语分析这些供应链攻击,以了解各个方面,例如他们的攻击媒介和影响。此外,列举了良性软件包中的反分析技术和看似恶意的行为,以提高安全界的意识并避免陷阱。具体来说,结果包括:
●注册管理机构中的软件包通过一些直接依赖关系紧密地连接到许多间接依赖关系,这意味着需要PM来确保直接重用的软件包的质量,并要求RM信任RM来审核间接使用的软件包是否存在恶意。
●窃取和帐户泄露是使用最多的技术,这表明攻击者倾向于使用低成本方法,并且RM缺乏支持,PM缺乏保护帐户的意识。
●窃取和后门程序是最常见的恶意行为,表明所有下游利益相关者都受到了攻击,包括用户,开发人员甚至企业。
●这些恶意软件中有20%在软件包管理器中保留了超过400天的时间,下载量超过1K,这意味着缺乏对策和潜在的高影响力,而其反向依赖性又进一步加剧了这种情况。
●被动DNS数据显示了供应链攻击的有效性,即庞大的用户群可以帮助及时修复安全风险。
●攻击者不断发展并采用诸如代码混淆,多级有效载荷和逻辑炸弹之类的技术来逃避检测。
●注册表生态系统缺乏法规和定义明确的策略,从而导致诸如信息窃取与用户跟踪之间的混淆之类的问题。
A.实验设置
环境:使用20个运行Ubuntu 16.04、64GB内存和8 x 3.60GHz Intel Xeon CPU的本地工作站从PyPI,Npm和RubyGems下载并分析所有软件包及其版本。使用60TB磁盘空间的网络附加存储(NAS)服务器为所有工作站提供共享存储。使用NAS服务器镜像注册表中的软件包及其元数据,并存储分析结果。注册表镜像能够获取恶意软件的副本,即使它们已被删除也是如此。
工具和数据集:对于元数据分析,从官方注册表API收集软件包及其版本的辅助信息。对于静态分析,依靠开源项目进行AST解析和数据流分析。为了执行模块化分析,为每个注册表构建一个依赖关系树,并使用Airflow安排对依赖关系树中程序包的分析,该功能能够安排任务的有向无环图(DAG)。对于动态分析,依靠Docker进行沙箱测试,并依靠Sysdig进行深入的系统级跟踪,使用Celery进行对包分析。为了了解在野供应链攻击受害者的数量,与一家主要的Internet服务提供商(ISP)合作,以针对他们的被动DNS数据检查相关的DNS查询。
B.程序包统计
如上表所示,处理了超过一百万个软件包,其中PyPI分解为186K,Npm分解为997K,RubyGems分解为151K。
元数据分析:对于注册表中的所有软件包,在下图a中显示了每个软件包的版本数和下载量的分布。版本数量的分布表明,80%的软件包具有少于7到9个版本,并且不同的注册表具有相似的分布,这意味着跨注册表的发布模式相似。相比之下,下载数量的分布在不同的注册表中有所不同,其中20%的RubyGems和PyPI软件包分别被下载了13,835次和678次以上,这表明在RubyGems上分发的软件包被更频繁地下载和重复使用。
还提供了下图b中下载的前10K软件包的依赖性计数分布,包括直接和间接依赖性。这些软件包中的80%具有2个或更少的直接依赖关系,从而变为20个或更少的间接依赖关系,这意味着需要PM来确保重用OSS的质量,并且需要RM信任RM来审核软件包的恶意性。下图b中的间接依赖关系的最大数量超过了1K,这意味着当频繁重复使用的程序包受到损害时,其显着放大。这表明PyPI和RubyGems面临着Npm的类似风险,例如单点故障和未维护软件包的威胁。
静态分析:在下图a中显示了使用可疑API的前10K下载软件包的百分比。与直觉的代码生成API(例如eval)是危险的且很少使用的直觉相反,下图a显示7%的PyPI包和10%的RubyGems包使用代码生成API。此类代码生成API不仅经常用于供应链攻击,而且如果未正确清理其输入,也可能导致代码注入漏洞。
动态分析:通过将它们打包在Docker容器中并使用Sysdig跟踪其行为,动态分析了注册表中的所有软件包。上图b显示了根据初始启发式方法在每个注册表中表现出意外动态行为的软件包数量。该图显示,与RubyGems相比,Npm和PyPI具有更多具有意外网络活动(即IP和DNS查询)的软件包。重要的是要注意,在安装阶段,意外的行为会因独立的软件包而扩大,从而导致上图b中标记的软件包数量很多。随后通过检查依赖关系树来删除这种冗余。
C.供应链攻击详细信息
本文系统地总结了651种恶意软件,在呈现时使用总体(Overall)来指整体报告的恶意软件,社区(Community) 指社区报告的恶意软件,作者(Authors)指作者报告的恶意软件。
在上图b中按恶意软件的恶意行为对其进行了分类,这表明窃取是最常见的行为,其次是后门,概念证明和加密劫持。进一步调查了窃取的主导类别,发现其中大约四分之三正在收集不太敏感的信息,例如用户名,IP等,从而对开发人员和最终用户的危害较小。其余的窃取包会收集各种敏感信息,例如密码,私钥,信用卡等。对于后门和加密劫持,它们的流行程度表明攻击者不仅针对最终用户,而且针对企业的开发人员和基础设施,这意味着开发商和企业迫切需要采取行动。
在上图中显示了每种恶意软件的持续天数和下载数量的分布,这表明其中20%的恶意软件在包管理器中可以保留400天以上,并且下载量超过1000。截至2019年8月,三个注册管理机构都没有声称部署自动分析或手动审核流程,而是依靠社区查找和报告恶意软件,从而导致了恶意软件的长期存在。为了更好地理解恶意软件在持久性和流行性方面的分布,下图中显示了持久性天数与下载次数之间的相关性,流行的软件包可能会保留较少的天,这可能是因为它们的容量更大用户群。如下图所示,共发现18个恶意软件包,下载量超过10万。本研究报告的三个恶意软件包(即paranoid2,simple_captcha2和datagrid)已由注册表维护人员确认并删除,并分别分配了CVE-2019-13589,CVE-2019-14282和CVE-2019-14281。不幸的是,第四个已识别的恶意软件包rsa-compat仍然在线。它收集有关程序包,Node.js运行时和操作系统的信息,由于缺少定义用户跟踪和窃取的策略,因此Npm维护人员正在对其进行调查。
D.反分析技术
在手动检查恶意负载时,注意到恶意软件一直在发展并利用各种反分析技术来击败检测。受先前针对易受攻击的恶意软件的研究的启发,对这些供应链攻击中使用的技术进行了枚举和分类,以引起社区的关注并有助于将来的分析。
良性服务滥用:攻击者可以滥用良性服务来掩饰自己并规避保护机制。例如,上面代码显示rest-client滥用pastebin.com服务来托管其第二阶段有效负载,从而使基于DNS查询的防御技术有效。同样,AndroidAudioRecorder使用DNS隧道泄漏敏感信息,从而滥用入侵检测系统(IDS)通常允许的DNS服务。从DNS查询角度来看,pyconau-funtimes成功将攻击者隐藏在0.tcp.ngrok.io(用于建立安全隧道的服务)的普通用户中。
多阶段有效载荷:由于反病毒工具主要基于签名,因此恶意软件倾向于通过将恶意逻辑划分为多个阶段并包括最少的代码片段,来隐藏其逻辑和占用指纹的空间。例如,上面代码仅包含有效载荷的获取,代码生成和错误处理,并在pastebin.com的第二阶段有效载荷中隐藏了其恶意逻辑,例如窃取环境变量和将受感染的主机后门。
代码混淆:可以分为随机混淆,编码混淆,逻辑结构混淆等类别,恶意软件可以混淆代码以将恶意逻辑隐藏在手动检查和自动检查中动态检测,供应链攻击没有什么不同。例如,getcookies和purescript都使用编码混淆。同样,上面代码中的快速请求使用随机混淆和编码混淆来破坏分析。
逻辑炸弹:TriggerScope将逻辑炸弹定义为仅在某些情况下才执行或触发的恶意应用程序逻辑。逻辑炸弹可用于击败静态和动态分析方法。例如,如果未在生产环境中执行,对rest-client 的动态分析将永远不会执行恶意有效负载。
版本较旧:通过帐户泄露发布的几种恶意软件分析中发现,攻击者不是将恶意有效载荷发布到软件包的最新版本(即最大化受害者的数量,这反过来又增加了被捕获的可能性),而是将这些有效载荷发布到软件包的较旧版本,以针对较少数量的受害者。本文认为攻击者是使用较旧版本的开发人员对安全性不太谨慎,从而最大程度地提高了攻击持久性并最大程度地降低了检测概率。
0X05 Conclusion
为了系统地研究软件包管理器生态系统中最近的供应链攻击,本文提出了一个比较框架,该框架揭示了利益相关者之间的关系,查明根本原因并总结其攻击媒介和恶意行为。根据研究,将众所周知的程序分析技术(例如元数据,静态和动态分析)应用到大规模分析中,以揭示程序包的各个方面并帮助检测恶意程序包。通过迭代验证,发现并报告了PyPI中的7个恶意软件,Npm中的41个恶意软件和RubyGems中的291个恶意软件,其中,已删除278个(占82%),并分配了3个CVE。所提出框架已经开放源代码,并根据要求提供收集的恶意软件样本以供研究之用,以帮助将来进行有关提高程序包管理器安全性和防御供应链攻击的研究。 还将邀请社区进行改进,并由RM进行部署以设定最低安全标准。
发表评论
您还未登录,请先登录。
登录