PSK's blog

PSK的学习研究经验分享站

现有顶会关于开源软件供应链恶意软件论文的简要研究

本文选择的论文主要在CCS(包括Workshop SCORED)、USENIX Security、NDSS、S&P安全四大顶会、以及ISSTA、ICSE、ASE、FSE软工方向A类会议收集。搜索的年限为2020年-2023年,搜索的关键词包括:Malicious、Supply Chain、Backdoor、Python、Malware等。

当前该领域的论文与克隆漏洞检测、APT攻击检测等方向对比相对较少。总体下来,2020-2023年安全四大顶会和软工四大顶会的论文我收集了约20篇,并选择了其中的一些静态分析、非深度学习的论文进行简要的研究和学习。

本文中将重点关注论文提出的方法是怎么去发现某段源代码具有恶意信息的,以及论文所采取的数据集来自哪里。此外还会关注这些论文提出的方法检测对象。但是,不对论文的实验效果进行讨论。

01 YODA

  • 论文名称:Mistrust Plugins You Must: A Large-Scale Study Of Malicious Plugins In WordPress Marketplaces

  • 作者及单位:Ranjita Pai Kasturi, Jonathan Fuller, Yiting Sun, Omar Chabklo, Andres Rodriguez, Jeman Park, and Brendan Saltaformaggio, Georgia Institute of Technology

  • 发表会议:USENIX SECURITY 22

  • 论文网址:https://www.usenix.org/conference/usenixsecurity22/presentation/kasturi

  • GitHub项目地址:https://github.com/CyFI-Lab-Public/YODA

  • 检测对象:WordPress插件(PHP语言)

  • 主要检测方法:后向切片+数据流规则匹配

论文提出方法

YODA

YODA以整个网站作为输入来检测其中使用的WordPress插件是否为恶意。因此,存在两个挑战:从网站的文件中找到WordPress插件包以及需要检测的源代码,判断代码是否存在恶意行为。这两个挑战在YODA的工作流中分别由第一部分和第二部分完成。

第一个部分中,YODA首先寻找含有WordPress插件头的文件来找到插件根文件。然后,把根文件所在文件夹及其所有子文件夹中的代码文件提取AST树以备后续检查使用。然后,检查这些代码文件是否有插件头,是否链接到其他插件目录下代码文件,以及是否含有插件中常有的API(论文附录B)来判断是否是需要检查的代码文件。

第二个部分中,YODA根据设定好的规则进行恶意代码的检测。作者团队联系了CodeGuard和收集从商店移除的恶意软件来进行规则的生成。并设定了14个恶意代码的检测规则。这些用来作为参考的恶意WordPress插件可以在作者的GitHub仓库中找到。他们注意到存在一些恶意插件通过分散恶意代码到多个文件中来逃避检查。为此,YODA首先基于第一部分的AST树,以函数调用为端点嫁接这些树形成一个跨函数、跨文件的AST树,然后在上面寻找敏感API(论文表10)。这部分成为语法分析(Syntactic Analysis)部分。获得了这些敏感API之后,YODA将它们作为Sink,并预先定义一些Source(在表2的匹配规则中给出),使用php-ast工具在AST树上后向切片。若匹配到匹配规则则认定该源代码具有恶意行为。

第三和第四部分是作者对检测出的恶意插件的一些额外研究。

数据集及实验结果

YODA首先从120个网站(60个已知存在恶意插件的网站和60个随机选择的网站)中提取出了3168个插件(由第一部分完成),作者团队选择了其中3132个插件手工标注了是否恶意以及恶意类型。YODA的准确率较高,仅误判了其中5个插件为恶意插件(总恶意插件数为89)。

此外,作者还在40w+的网站备份镜像上对YODA进行了效率测试和WordPress社区的调查。

作者在其GitHub开源库中给出了恶意插件的样本

02 MalOSS

论文提出方法

MalOSS

分为三步,第一步为元数据分析,这个部分可以发现很多Typosquatting的软件包,以及确认软件包是否含有嵌入式的二进制文件。这两个特征是恶意软件包的一个重要特征。

第二步为静态分析部分。首先,作者通过对恶意软件的分析,决定将4类(网络操作类、文件系统操作类、进程操作类、动态代码执行类)近百余个API作为敏感API(在论文附录中表V可以看到)。这些敏感API在作者的标注下进一步分为了能返回敏感数据的数据源Source,和能对输入数据执行可疑操作的数据汇Sink。然后,作者通过将源代码解析为AST寻找这些敏感API。作者利用了PyT(python)、JSPrime(js)、Brakeman(Ruby)来对这些敏感API做数据流分析(污点分析),判断是否存在敏感数据流出Sink。

第三部分为动态分析部分,作者会在沙盒中运行可疑的软件包,进行动态分析来判断软件包是否为恶意软件包。

作者设定了判定为恶意软件的12条初始规则(论文表III),若满足则作为可疑软件包交由专家进行下一步分析。12条规则中三个部分每个各占4条。

数据集及实验结果

作者的规则是在实验中迭代更新的(不过作者并未透露迭代最终的规则情况)。作者分析了PyPI社区中18.7w、NPM社区中99.8w、RubyGem社区中15.1w的软件包,共发现了339个恶意软件(主要在Ruby社区)。

剩余的实验主要集中于对恶意软件特征的分析。

作者在其开源项目中给出了良性数据集恶性数据集供参考。

03 Poster

  • 论文名称:Poster: Using CodeQL to Detect Malware in npm

  • 作者及单位:Matías F. Gobbi, Johannes Kinder, Bundeswehr University Munich, Ludwig-Maximilians-Universität

  • 发表会议:CCS 23

  • 论文网址:https://dl.acm.org/doi/10.1145/3576915.3624401

  • 检测对象:NPM包

  • 主要检测方法:CodeQL规则匹配

Poster的作者首先检查了那些因安全原因被下架的NPM包(收集了75个恶意软件包),对这些NPM包进行人工筛查,确认是否具备恶意行为。然后,作者团队设计了一套CodeQL规则(12条规则)去概括匹配这些恶意行为。最后,他们拿着这些CodeQL规则去对整个NPM社区进行扫描。

作者团队最终从1.8M个包中扫描出125个恶意软件,并分析了它们的恶意行为和报告给NPM官方。

作者在其论文中并未给出12条规则的具体信息。而且作者在文中指出了,该方法的召回率可能较低。

04 Diff-CodeQL

  • 论文名称:Differential Static Analysis for Detecting Malicious Updates to Open Source Packages

  • 作者及单位:Fabian Niklas Froh, Matías Federico Gobbi, Johannes Kinder, Ludwig-Maximilians-Universität, Bundeswehr University Munich

  • 发表会议:CCS 23 WORKSHOP(SCORED 23)

  • 论文网址:https://dl.acm.org/doi/10.1145/3605770.3625211

  • GitHub项目地址: https://github.com/lmu-plai/diff-CodeQL

  • 检测对象:NPM包

  • 主要检测方法:CodeQL规则匹配

论文提出方法

Diff-CodeQL团队主要抓住被攻破的软件往往有良性的一般更新,以及更新到恶意版本的更新这两类更新的特征,编写CodeQL规则来将软件包的更新分类为良性更新以及恶性更新,以检查更新的代码方式来降低源代码检查的范围以及更好的找出恶意代码。

作者团队通过使用了Ohm et al.等人和Duan等人(也就是[MalOSS](#02 MalOSS))的恶意软件数据集作为研究的基础,设定了6个方面41条CodeQL匹配规则。不过作者并未在文中具体的给出这41条匹配规则,但是可以在GitHub库中查看。

Diff-CodeQL为他们设计的每一条规则都设定了一个0-10分的一个安全严重性分数。对于每一个输入的源代码文件,Diff-CodeQL会计算所有存在匹配的规则的严重性分数之和,超出预定义的阈值就会标记该软件包为可疑软件包。

Diff-CodeQL的工作流程如下:首先,它会下载连续的两个软件包的版本,并对其中的源代码文件分别生成CodeQL数据库,并使用编写好的规则进行匹配。Diff-CodeQL只会关注二者之间存在差异的部分,并根据上文的方法计算更新的安全严重性分数,若安全严重性分数超过阈值,则认为是潜在恶意的软件包,生成差异报告文件交由专家进行下一步处理。

数据集及实验结果

对于恶意软件包部分,作者使用的是已有的Backstabbers-Knife-Collection和MalOSS的恶意软件包,并没有直接给出全新的恶意软件包。

作者分别对已知存在恶意软件版本的9个软件包和25个流行的NPM软件包进行了检查和分析。结果显示其FP较低(平均1.3%,最高的软件为8.1%)且召回率较高(对于已知恶意软件版本全召回)。

05 Ladisa et al. (Java)

  • 论文名称:Towards the Detection of Malicious Java Packages

  • 作者及单位:Piergiorgio Ladisa, Henrik Plate, Matias Martinez, Olivier Barais, Serena Elisa Ponta, SAP Security Research et al.

  • 发表会议:CCS 22 WORKSHOP(SCORED 22)

  • 论文网址:https://doi.org/10.1145/3560835.3564548

  • 检测对象:Java软件包

  • 主要检测方法:敏感字符串分析+模拟JVM堆栈

论文提出方法

Ladisa et al. (Java)

作者首先在Backstabbers-Knife-Collection中寻找到了4个JAVA恶意软件样本进行分析。对于每一个从JAR包提取出的Class文件,作者会提取出它的常量池中的字符串以及字节码进行分析。

对于常量池中的字符串,作者通过对恶意软件样本的分析发现恶意软件往往喜欢使用base64编码隐藏一些恶意的字符串信息,而base64编码具有较高的熵值。这与普通的,良性的字符串不同。来移除良性字符串。考虑到恶意软件可能会使用base16编码这一熵值较低的编码,他们也采用了Kullbac-Leibler divergence这一方式进行检查。作者团队还使用了Compact Language Detector(CLD2)方法移除掉英语语言的字符串。对于剩余的字符串,作者团队通过设定了一些敏感字符串在不同编码方式作为指纹信息,检查这些字符串是否有可能含有这些敏感字符串。基于实验结果,最终先利用香农熵值在类级别过滤前1/4低熵编码,然后进行CLD2过滤英语编码的字符串。

对于字节码部分的信息,作者关注了6类58个API(在表7中给出具体API),以及Empty Catch这一特征。作者团队设计了数据流分析方式,通过模拟JVM堆栈,当到达敏感API时,检查JVM堆栈中是否存在可能的敏感信息。

数据集及实验结果

作者收集了热门前10的软件包,并使用ASMifier向这些软件包中添加了BKC数据集收集的三种不同的恶意行为,总共40组样本(10良性+30恶性)。最终结果显示,论文提出的方法可以全召回这些恶性的样本。

作者并没有在真实世界的恶意软件案例上测试论文提出的方法。

06 Ladisa et al. (NPM & Python)

  • 论文名称:On the Feasibility of Cross-Language Detection of Malicious Packages in npm and PyPI
  • 作者及单位:Piergiorgio Ladisa, Serena Elisa Ponta, Nicola Ronzoni, Matias Martinez, Olivier Barais, SAP Security Research et al.
  • 发表会议:ACSAC 23
  • 论文网址:https://dl.acm.org/doi/10.1145/3627106.3627138
  • 检测对象:NPM和PYPI软件包
  • 主要检测方法:特征提取+XGBoost分类

论文提出方法

作者分析了来自BKC的恶意软件包,提取出了19种metrics来形成向量(在论文Table 3有详细描述)。涵盖代码执行、代码基础特征、敏感字符串、编解码API、字符串操作API、软件包结构特征等方面。并且分析了恶意代码和良性代码在这些metrics上分布的区别。

然后,将这19个metrics整合成为一个向量,进行机器学习分类。

基于实验,作者选择了XGBoost分类器进行分类。并使用Bayesian Optimizer来找到最佳的超参数。

数据集及实验结果

作者选择了来自于BKC的102个NPM包和92个Python包来作为恶意的样本,并从liberaries.io网站收集828个流行的Python包和918个Javascript包作为良性样本。

在使用单语言的数据集中(js训练集-js检测集)(python训练集-python检测集),获得了84.4%和68.0%的F1值。在混合训练集-单语言测试集中,获得了76.3%(js)、66.9%(python)的F1值。具备一定的跨语言检测能力。但是,在对现实世界软件包的检测中发现,仅能达到4.4%的Precision,但是筛除率可达到98%。

07 MalWuKong

论文提出方法

MalWuKong

首先,MalWuKong会通过控制流图和数据流图找到敏感API,并标记其中一些为Source,另一些为Sink。然后,分析这些敏感API之间的信息流,如果有Source-Sink在预定义的受到关注的Source-Sink之中,则记录下这个疑似含有恶意的行为。对于CodeQL的配合使用,向作者询问后得知如果污点分析过程出现了错误,将会改用CodeQL查询代替原有的污点分析过程。若成功提取出了感兴趣的污点路径,则会传入下一步交由YARA规则进行匹配。

此外,基于Function Call Graph,MalWuKong可以处理跨函数的API分析。MalWuKong可以记录跨函数的函数调用,并生成这次调用中敏感API列表。并交由YARA规则进行是否为疑似恶意软件的判定。

作者等人还分析了元数据来帮助判定软件包是否存在威胁,不过这部分主要用于人工分析阶段,并没有包含在自动化的阶段中。

对于YARA规则的匹配部分,作者基于8种攻击方式设计了8个匹配规则。若匹配成功则认为疑似恶意软件。

数据集及实验结果

作者从PyPI、NPM中收集了311个恶意代码样本,并放在了他们的GitHub数据集仓库。作者分类实验的结果显示:整体的F1分数可以达到86-88%。此外,MalWuKong还与MALOSS、GUARDDOG两个现有的开源恶意软件检测工具进行了对比,与GUARDDOG的对比显示:MalWuKong的误报率更低,准确率较高。

MalWuKong也在真实世界的NPM和PYPI两个包管理网站上进行了检测,发现了107个具有恶意代码的Python软件包和23个具有恶意代码的NPM软件包。

08 Amalfi

论文提出方法

Amalfi

与前面绝大多数文章不同的是,Amalfi抛弃了数据流分析的方法,别出心裁的提出了一种基于特征分类的恶意软件分类器。Amalfi关注5种代码级别的特征:包括是否访问了敏感数据、是否访问了一些特定的系统资源(包括文件系统、进程、网络资源)、是否使用了一些特定的API(包括加密API、编码解码API、动态代码执行API)、是否使用了安装脚本以及是否存在极短代码/二进制文件等用于逃逸检测的手段。在这些代码的特征之外,Amalfi还考虑了包元数据中的一些特征,包括更新的版本号和更新的时间间隔,这两个特征是作者分析恶意软件投放时的特征得到的——恶意软件往往会在短时间内发表大量版本,或者是在沉寂多年后突然更新。

确定了关注的特征,Amalfi通过TreeSitter来解析js/ts文件的AST树。Amalfi遍历AST树,试图寻找敏感的字符串/API。Amalfi还会分析package.json文件来判断是否存在安装脚本,并通过香农熵的方式判断是否存在极短代码/二进制文件等逃逸检测的代码或者二进制文件。关于更新的间隔,Amalfi通过npm view实现。

作者联系NPM官方获得了643个具有恶意代码的软件包,自身也从NPM中收集了63个恶意的代码包和1147个良性代码包,总计获得了1790个标记好是否恶意的软件包用于实验。实验结果表明Amalfi在决策树、朴素贝叶斯树和SVM向量机之中SVM向量机表现最好,因此作者选择了SVM向量机作为分类器来分类。

为了降低SVM分类器的误报,Amalfi创新性的引入了重构器——检查NPM包是否可以由package.json文件给的源地址重构出来。如果能够重构出来,则判定这不是恶意软件包,因为恶意软件包往往为了隐藏自己不会填入真实的包源地址。此外,通过计算包里每个文件的SHA1值,Amalfi还可以识别出与已知恶意软件包相同的软件包,这是因为恶意软件发布者往往会从自己控制的多个软件包发布类似的恶意行为的包——也就是这些发布的软件包具备许多完全相同的文件。

数据集及实验结果

作者声称由于具有恶意代码,用于训练SVM向量机的恶意代码不被公开。基本上核心部分的代码由于作者声称其可能会遭到滥用都保持闭源状态。

作者在7天内扫描了约9.6w个恶意软件包,经过使用扫描获得的恶意软件包进行迭代训练之后,可以获得一个较好的TP和FP值。在7天的扫描中大约发现了数十个恶意软件包,并报告给了NPM官方。

作者还使用了MalOSS提供的恶意软件包,以及在上述实验中获得那些被NPM官方确认的恶意软件包,构建了372个软件包的数据集,其中40个已知具有恶意行为。在MalOSS的数据集上,Precsion可达到73%,Recall可达到61%。

09 Pantelaios et al.

  • 论文名称:You’ve Changed: Detecting Malicious Browser Extensions through their Update Deltas
  • 作者及单位:Nikolaos Pantelaios, Nick Nikiforakis, Alexandros Kapravelos, North Carolina State University, Stony Brook University
  • 发表会议:CCS 20
  • 论文网址:https://dl.acm.org/doi/10.1145/3372297.3423343
  • 检测对象:CRX插件(Javascript)
  • 主要检测方法:聚类分析

Pantelaios et al.

只需要关注下半部分即可,上半部分是作者寻找恶意插件的部分。

首先作者在文中详细论述了如何根据评论和评分找到恶意的插件的,作者通过文中的方法收集了45个恶意插件作为初始的插件集合。

然后,作者关注了55种API(论文表3),基于这55个API的有无构造一个One-Hot向量,然后,使用DBSCAN算法进行聚类,若两个插件之间的距离少于设定好的d则归为一类。论文没有讨论minPts的选择,可能采用的是默认值。最终作者从92.2w的插件集中获得了7419个簇。

然后,作者将与恶意代码所在的簇作为恶意簇,然后,检查恶意簇中是否存在某些插件存在于其他簇中,若存在则将后者也标记为恶意簇。第一轮标记在实验中标记了18个簇,第二轮标记在实验中额外标记了3个簇。在92.2w的插件集中发现了145个疑似恶意的插件,其中有2个误报。

10 现有Python恶意代码检测器对比

  • 论文名称:Bad Snakes: Understanding and Improving Python Package Index Malware Scanning
  • 相似论文:A Benchmark Comparison of Python Malware Detection Approaches (On Arxiv)
  • 作者及单位:Duc-Ly Vu, Zachary Newman, John Speed Meyers, Chainguard and FPT University
  • 发表会议:ICSE 23

这篇论文主要是对现有的Python恶意代码的方案进行对比。

所对比的python恶意代码检测器列表

软件名 作者 项目网址/描述
Bandit4Mal Vu et al. https://github.com/lyvd/bandit4mal
OSSGadets Microsoft https://github.com/microsoft/OSSGadget/wiki/OSS-Detect-Backdoor
PyPI MalCheck PyPI https://warehouse.pypa.io/development/malware-checks.html#malware-checks
Aura Masaryk University 大学本科2019毕业论文
JFROG XRAY 商业软件 https://jfrog.com/xray/
OSSF Package Analysis 社区软件 https://github.com/ossf/package-analysis
MalOSS Duan et al. https://github.com/osssanitizer/maloss
pypi-scan IQT 实验室 https://www.iqt.org/pypi-scan/
Sonatype 商业软件 https://www.sonatype.com/pressreleases/next-generation-nexus-intelligence
TypoGuard Network and System Security 2020

作者只选用了具有源代码、基于异常检测、规则可获得的三个项目来进行对比检测。

数据集采用与实验

作者选用了BKC数据集中的107个Python软件包和MalOSS提供的140个恶意软件包作为恶意样本,去重后恶意样本总数为168.作者从流行的python软件包中选择了1430个软件包作为流行良性样本,并随机选择了1000个软件包作为流行随机样本。

实验结果表明,尽管这三个工具的召回率可以超过50%,且具有较高的误报率,有些时候会在同一个包上连续报出多个恶意警报,增加用户的检查成本。实验在效率上的分析也表明检测工具整体的效率不佳。

11 常用检测方法&恶意代码数据库简要介绍

CodeQL

一个非商业化的数据流分析工具,可以基于现有代码构造CodeQL数据库,并编写CodeQL语句查询CodeQL数据库中是否存在感兴趣的数据流。

支持的语言涵盖C/C++,C#,Go,Java,JavaScript,Python,TypeScript等。

YARA

一个开源工具,开发者可以通过定义规则:例如是否存在某个字符串。来判断待检测的对象是否为恶意/良性的。主要用在二进制层面较多。

Backstabbers-Knife-Collection (BKC)

由Ohm et al.收集的恶意软件数据库,包含Java、NPM、Python的恶意软件包。并且合并了An Empirical Study of Malicious Code In PyPI Ecosystem的数据集。

SourceFinder

VirusTotal

一个在线网站,可以将你的上传文件通过多个杀毒软件进行检查,通常被用于初步研究阶段。

12 其余一些论文的简单介绍

这个部分主要介绍一些调研性质的、深度学习相关方案的、以及非恶意代码检测,但在恶意代码领域或其相关领域的论文,供后续论文参考

An Empirical Study of Malicious Code In PyPI Ecosystem

  • 发表会议:ASE 23

这篇文章虽然有提及使用了自动化的数据收集方案,但没有给出非常详细的方法概述,只是作为论文中的一部分进行描述。论文的恶意代码来自于SourceFinder、MalOSS、BKC数据集,以及其他的网络上的数据源。论文中提出了一种分类恶意代码的方法——首先提取出恶意的API序列,然后使用词嵌入Word2Vec的方案生成向量,而后进行聚类。通过聚类,作者获得了5个类别的恶意代码。

这篇论文主要是对恶意代码本身,以及目前社区的恶意软件代码情况进行了调查和分析。

What the fork? finding hidden code clones in npm

  • 发表会议:ICSE 22

这篇文章主要是是介绍了NPM中的克隆漏洞检测方法,粒度为包级。

检测方法为:为两个待检测软件包的每一个文件进行指纹信息提取。当两个包的除去子模块和非源代码的琐碎软件包的文件数量差值不超过2,指纹信息不重合分数(内容不同文件数+2*独有文件数)不超过12时,判定为克隆。

提供了一种在NPM中克隆检测方法。

DeepReflect: Discovering Malicious Functionality through Binary Reconstruction

  • 发表会议:USENIX SECURITY 21

这篇论文针对二进制恶意软件设计了一种深度学习的方法。提取特征的粒度到达basic block级。

DeepReflect

使用了AutoEncode来highlight 感兴趣的区域RoI,然后进行聚类分析(HDBSCAN)

恶意数据集来源于VirusTotal,而良性数据集从CNET中提取。

Malicious Package Detection in NPM and PyPI using a Single Model of Malicious Behavior Sequence

于2023年在Arxiv上公开。

论文提出方法整体架构

先生成行为序列,然后通过微调后的BERT进行分析。

在NPM和PYPI两个社区上进行了测试。NPM的恶意数据集来自于BKC,良性数据集来自于5000个社区流行的NPM包。而python的恶意数据集来自于MalOSS,良性数据集来自于Vu等人。

13 总结

大多数论文缺少与现有SOTA工具对比。所有选择的论文中,仅DeepWuKong和GUARDDOG进行了对比。剩余的论文全部都是只在证明自己的工具的有效性,而不说明自己的论文较SOTA更好。

习惯上对社区中所有软件包进行检查。很多论文做测试的时候都尝试扫描整个社区的软件包,并以此来检验工具的效率和有效性。

研究方法主要集中与数据流分析。绝大多数论文都是在数据流分析上做文章。尤其是不约而同的使用了GitHub开源的CodeQL作为数据流分析的一部分,集中精力于CodeQL的规则编写。但是也注意到有少部分论文使用了Metrics等非数据流方法来判定是否为恶意软件,但这些方法往往有较高的误报率。

对于python社区,缺少对conda-forge,poetry等新兴社区的调查。大多关注python软件供应链的论文都将目光放在pypi这个最大的社区,而忽略了conda-forge等这些较小的社区。

常用的恶意软件数据库。开源软件供应链相关的论文最常使用BKC数据库,随着MalOSS的发表,越来越多的论文开始采用MalOSS数据库。