前言
2020年5月28日,Github安全团队发表了文章称Github上存在一组代码仓库正在服务于感染了恶意代码的开源项目(https://securitylab.github.com/research/octopus-scanner-malware-open-source-supply-chain),根据实际文章内容理解,攻击者通过提交恶意代码至开源项目,并被其他开源项目所引用。这些存在恶意代码的开源项目被开发人员使用后,会在开发人员机器中寻找NetBeans IDE,如果开发人员的机器中存在该IDE,则对NetBeans构建的所有JAR文件进行感染,植入恶意软件加载器,以确保项目运行时会释放出一个远程管理工具(RAT)。
换句话说,本次供应链攻击针对的是经常使用开源项目的开发人员。通过感染开发人员使用的IDE(集成开发环境),以达到在开发人员开发的所有项目植入有恶意软件的目的。目前来看,该攻击者只针对JAVA项目。
事件分析及恶意软件分析
事件关键信息
根据事件披露的情况,我们整理了该次供应链攻击事件的时间线:

通过对恶意软件的分析以及GitHub安全团队的披露,我们可以对可能感染的环境进行排查,条件如下:
- 是否存在NetBeans IDE环境
- 在NetBeans项目目录中寻找cache.dat和nbproject/cache.dat
- 排查是否新生成的项目中自带上述文件
根据Github安全团队描述,在3月9日就已经接收到安全研究人员消息,并着手对此次事件进行分析和处理。根据目前分析到的信息,在Github上进行搜索,还能够找到12个开放的issue和1个处理过的issue,包含了项目名,在此贴出供查询和处理:
项目名称 | 链接 | issue处理情况 |
george-bennett/V2Mp3Player | https://github.com/george-bennett/V2Mp3Player/issues/1 | 未回应 |
KosimCorp/Kosim-Framework | https://github.com/KosimCorp/Kosim-Framework/issues/1 | 未回应 |
SebasR16/Punto-de-venta | https://github.com/SebasR16/Punto-de-venta/issues/1 | 未回应 |
PratDaBrat/JavaPacman | https://github.com/PratDaBrat/JavaPacman/issues/2 | 未回应 |
BarbosaO/2D-Physics-Simulations | https://github.com/BarbosaO/2D-Physics-Simulations/issues/1 | 未回应 |
Sliray/Secuencia-Numerica | https://github.com/Sliray/Secuencia-Numerica/issues/1 | 未回应 |
hawacodes/CallCenter | https://github.com/hawacodes/CallCenter/issues/1 | 未回应 |
SierraBrandt/GuessTheAnimal | https://github.com/SierraBrandt/GuessTheAnimal/issues/1 | 未回应 |
callmehetch/PacmanGame | https://github.com/callmehetch/PacmanGame/issues/1 | 未回应 |
jyeemvhs/SnakeCenterBox4 | https://github.com/jyeemvhs/SnakeCenterBox4/issues/1 | 未回应 |
FelixGtz99/ProyectoGerundio | https://github.com/FelixGtz99/ProyectoGerundio/issues/1 | 未回应 |
nk-fouque/pacman-java_ia | https://github.com/nk-fouque/pacman-java_ia/issues/1 | 未回应 |
cjthimm/SuperMario-FR- | https://github.com/cjthimm/SuperMario-FR-/issues/1 | 已处理 |
恶意文件分析
本次攻击过程中,恶意文件主要是JAVA编写的JAR文件,在整个攻击过程按照不同的功能分为多个模块。

ocs.txt
恶意文件以txt为扩展名进行伪装,实际是JAR文件。ocs.txt恶意软件的主要功能是释放第二阶段的攻击载荷到被感染的系统中。
由于JAR文件支持多平台运行,因此该恶意文件在编写的代码中针对不同的系统分别进行了处理。从反编译的代码逻辑上可以看出,原始的恶意软件支持windows和Linux系统。
在Linux系统上,恶意软件提取第二阶段攻击载荷octopus.dat到$HOME/.local/share/octo.并在$HOME/.config/autostart目录下创建自启动脚本octo.destop:

在Windows系统上,恶意文件提取第二阶段攻击载荷到用户目录下AppData\Local\Microsoft\Cache134.dat,设置计划任务启动。

octopus.dat
octopus.dat内置文件名为 Octopus Scanner,根据文件中的静态字符串我们识别到其版本为3.2.01,该文件以文件名octo释放到受害者系统中,实现关键的感染功能,主要过程为:
- 在系统对应目录下查找Netbeans项目信息,并在目录下查找项目属性文件,寻找感染目标:
- $APPDATA/NetBeans
- $HOME/.netbeans
- config/Preferences/org/netbeans/modules/projectui.properties
找到projectui.properties后恶意代码将使用WatchService注册监控服务,监控其目录下发生的文件新增、修改和删除事件。一旦检测到相关事件,且对应文件名不为uihandler.properties,则将相关文件名、事件名和时间加密后写入TEMP目录下.eSv31410a81lL.dat或HOME路径下名为.local/share/.eSv31410a81lL.dat的文件中。 而攻击者可通过后续的RAT来得到该文件的内容。
- 在项目属性文件中通过openProjectsURLs查找到目标项目路径,并通过以下过程进行感染:
- 对nbproject/build-impl.xml进行修改,在xml文件中增加以下内容:

这两个配置在NetBeans项目生成过程中发生作用。pre-jar在类构建之后JAR包生成之前提供挂钩操作,post-jar在生成JAR包的过程中提供挂钩操作。
- 提取资源文件下的第三阶段攻击载荷到nbproject/cache.dat,配合前面的挂钩操作。

cache.dat
在Netbeans项目的构建过程中,cache.dat会试图在项目中插入自身的一个类文件。并设置标记文件,防止被感染的项目重新构建。当这些被感染的项目提交到GitHub等开源平台,可能会有新的开发者受到感染。
插入到项目中的类文件本身也会被cache.dat执行,主要作用是释放另外一个JAVA组件,为其设置计划任务,而该组件执行之后会下载一个RAT程序并执行。
RAT- FEimea Portable App工具
下载的data.txt即为最终的RAT工具:


RAT执行过程中,首先会检查当前系统是否被感染,当发现系统并未感染时,会从C&C下载ocs.txt并执行。据此猜测受害者被感染的时机除了下载到受感染的项目之外,还有可能是先中招RAT,随后下载到恶意软件,进而影响到本地的JAVA项目。


该RAT包含的指令如下:
命令 | 功能 |
SELECT | 保存指定路径 |
LIST | 获取指定目录下文件和子目录列表 |
STAT | 列出指定文件或目录的具体情况,包括路径、类型、最后修改时间。对于目录,还会收集目录下的文件列表,对于文件,还会收集文件大小和读写权限 |
PWD | 得到当前路径 |
RENAME | 重命名 |
HASH | 得到特定文件的sha-256 |
COPY | 复制文件 |
APPEND | 若参数为目录名,则创建目录并写入文件;若为文件则追加写入特定内容。 |
FETCH | 上传指定文件内容 |
REMOVE | 删除文件 |
NOOP | 无实际操作 |
ACCESS | 若副参数为STOP则立即退出程序;若副参数为VERSION则收集当前程序信息,包括版本、音频信息(实际没有)操作系统名称和架构;若副参数为DOWNLOAD则下载指定文件 |
BYE | 不再进行接发指令 |
RAT会向指定的C&C回传操作系统的名称、架构和用户名,以及从.gitconfig文件中获取的用户名。攻击者可根据用户名等信息注册特定域名并上传恶意jar,并发送ACCESS指令使肉鸡下载该组件。这在下一阶段组件a2s中体现得更为明显。


a2s.txt
特别的,当受感染主机为Windows时,RAT会从C&C下载新的class组件a2s.txt并执行。

该组件会判断系统位数以释放出对应的dll模块以记录用户键盘输入。

记录的内容写入名为async3.log的文件中。

同时,a2s组件负责将async3.log的内容回传至C&C,仅当新增内容超过4096字节时回传。a2s每次会将log文件总长度保存在名为async3.off的文件中,下一次读取时获得新增内容的偏移。如果请求成功,服务端的回复会包含字符串”A2SOK”的数据包。




除此之外,A2S还会利用当前用户名生成一个url,并释放一个附带url的class文件,按照与前面相同的方法设置class脚本自启动,之后将本机系统信息和用户名发送给服务端。
在这个class文件中,攻击者使用URLClassLoader加载URL并执行下载到的class文件的main方法。从这一点可以看出,攻击者有长期打算,以用户名相关信息注册不同对应域名,并为域名配置JAVA程序,达到在受害者系统中执行任意的JAVA程序,实现针对不同用户定制化攻击的目的。

总结
本次事件是典型的供应链攻击事件,攻击过程中利用了Github这一最大的代码共享平台完成大范围攻击。通常攻击者会利用Github进行C2托管或恶意代码托管,但在本次事件中,攻击者通过对其他开源项目的攻击,植入恶意代码,让开发人员“主动”下载带有恶意代码的开源项目,对开发者开发的所有应用程序感染。这在一定程度上利用了开发人员的侥幸心理:“开源的项目代码都已经公开了,怎么可能出现问题”,在使用开源项目时应关注开源项目相关的其他的项目以及加强对开源代码的审计力度,从源头上避免此类事件的发生。
IOC
Domain:
utelemetrics.atwebpages.com,
ecc.freeddns.org,
san.strangled.net,
ntpsysse.duckdns.org