时间:2022-11-14
概述
去年,奇安信威胁情报中心发布了《Operation(ThủyTinh)OceanStorm:隐匿在深海巨渊下的邪恶莲花》。此后海莲花的攻击活动不降反增,并在2022年入侵某地区的IOT设备作为跳板攻击对另一个地区的目标进行攻击,并首次发现了海莲花在Arm和mips平台的木马,我们将其命名为“caja”,其中mips的木马是用来针对将要铺开的定制化系统。
[1]
本文主要会介绍海莲花在过去的一段时间内网渗透过程中所用的一些手法,并披露其在2021年所使用的三个0day漏洞和数个Nday漏洞,恶意代码方面我们会披露近期使用的一些免杀loader、释放的一些功能模块和基于不同语言的隧道转发工具。
与之前的文章类似,本文内容也仅仅是对海莲花在过去一段时间内攻击手法做一个分享(0day漏洞所涉及的产品均已修补)。供友商追踪溯源。
漏洞分析
0day漏洞分析
0day漏洞一
漏洞出现在某终端管理软件中,服务端和客户端均本地监听了一个2开头的高端口(2XXXX),与该端口通信数据走的是私有协议,漏洞出现在对发来的数据包进行判断的逻辑。
这部分代码由于开发人员的疏忽在strfind之后没有将返回值置为-1。
导致在代码后续执行过程中会执行从数据包中传来的命令
海莲花利用此漏洞可以在内网中进行漫游,对装有某终端管理软件的机器执行任意命令。
0day漏洞二
漏洞出现在某终端管理系统服务端web管理页面,由于登录页面需要令牌验证,安全性很高,但海莲花可能在之前拿到了整站源码找到一个隐藏的登录页面(该页面只需要输入账号密码没有多余的验证),并且拿到了登录的账号密码,成功登录到web端管理后台,并通过其中的一个带有漏洞页面,写入恶意脚本,从而实现命令执行。
0day漏洞三
某杀毒软件服务端存在RCE漏洞,海莲花使用该漏洞入侵杀软服务器端,并向服务端下的所有机器下发木马。
渗透以及横向移动
海莲花非常善于使用测绘平台对全网进行测绘。在使用Nday漏洞时并没有我们想象的具有定向性,批量入侵所有带有漏洞的站点并进行筛选,如果存在高价值的目标则进一步横向移动,其余的当作代理方便海莲花的活动。例如,我们曾在一个色情网站上发现了海莲花投递的webshell和木马。
海莲花利用老版本showdoc任意文件上传漏洞上传webshell
接着上传了使用开源loader生成的CS木马。
木马回连的C2为海莲花控制的IOT跳板,海莲花从去年初就开始对路由器、摄像头等IOT设备进行攻击,入侵成功后植入tinyPortMapper端口转发软件,将跳板服务器的高端口的流量转发到攻击者真正的CS服务器上。
之后的一段时间,海莲花开始对韩国地区的一些三星路由设备进行攻击并当作跳板,但整体数量不是很大,我们推测海莲花可能在韩国也有相应的“政治任务”,而到了今年上半年开始针对台湾地区的IOT设备进行攻击,与IOT设备建立连接后,海莲花会尝试在IOT设备上上传busybox或者dropbear便于攻击者进一步渗透。
上传的Busybox如下所示
上传的dropbear如下图所示
最终攻击者植入的了一个基于arm架构的linux木马,方便长期控制,之后会根据业务方向设置转发,最近我们观察到海莲花将转发软件从tinyPortMapper换成了Gost。
在内网横向移动方面,我们观察到海莲花使用CVE-2020–14882WebLogic远程命令执行漏洞、CVE-2021-22986F5BIG-IPiControlREST未授权远程命令执行漏洞和Jboss反序列化漏洞在内网中漫游,然后会在内网重要节点的服务器上创建PowershellWebserver,并在上面存储加密的CSpayload。
代码源于github项目Powershell-Webserver
通过powershell内存加载mimikatz的方式拿到域管的账号密码后开始使用windows.vbs进行横向移动投递木马。
经过分析发现该VBS源于github项目WMIHACKER
投递的木马会向内网powershell服务器请求加密的payload并加载。
最近我们观察到海莲花针对运维人员的攻击活动,通过CNVD-2022-03672漏洞拿下运维人员的电脑,从桌面的密码本上窃取了连接服务器todesk服务的口令,之后海莲花通过todesk远程登录服务器手动拷贝带有木马文件的压缩包,并右键解压执行。
木马载荷介绍
Windows
最近我们观察到海莲花开始使用亚马逊的cdn云函数作为CobaltStrike的C2服务器。
Loader
海莲花会使用各式各样的免杀loader去加载CS后门从而绕过杀软查杀,如使用NIM语音编写的loader
或者使用github上最新开源的loader,
这两个Loader分别为shhhloader和MortarLoader
除此之外还会使用“msbuild.exe源码”的方式加载CS
源码内容如下:
隧道木马
除了CS后门,海莲花还会使用开源或者魔改的隧道木马来与目标服务器建立连接
第一个样本为python打包的exe,解出来脚本如下:
经过对比发现为开源隧道工具RPIVOT
第二个样本为Golang编写隧道木马,该样本一般会注入到系统进程中不落地,我们推测海莲花是基于smux和cli两个库自行开发的隧道木马。
插件
目前我们仅从内存和日志中捕获到以下三个插件
窃密PS脚本如下:
接着将获取到的数据通过内网代理的方式加密发送到图床网站上。
海莲花只需要下载图床对应的URL即可拿到相关数据。
插件二的功能逻辑如下:
找到日志服务的进程PID,接着挂起该进程。
插件三的功能逻辑如下,加载资源节中的shellcode
添加新账号,账号名称和密码分别为"DefaultAccount2"、"!2345^Abc"
把新账号加入管理员组,并禁用UAC远程限制
Linux
Linux平台我们一共发现了三种架构的木马,分别为x86、Arm、Mips。通过对样本进行分析我们发现三种架构的木马是基于一套源码交叉编译而来,其通讯协议完全相同,我们将其命名为“caja”木马。我们以Mips架构的为例做详细分析
caja善用XOR编码和AES加密的方式隐藏关键信息。其用到的关键字符串,全部用硬编码的固定Key进行XOR编码处理,在运行中动态解码后再使用。而网络流量中的信息,则结合了AES加密和随机XOR编码两种方式。值得一提的是其上线包中包含的多个字段,每一个字段的XORKey都不相同,且仅会对目标数据中处于奇数序的字符做XOR编码,对偶数序的字符进行逻辑非处理。caja可以接收C&C下发的13种指令,恶意功能主要有以下几种:
释放文件、执行文件
访问指定URL下载文件
检查指定文件
读取指定文件中指定偏移、指定长度的数据
删除指定文件/目录
执行Shell命令
caja的整体执行流程如下:
caja与双头龙和Buni功能不同,不是同一个家族的变种。其中Buni由C++编写,caja与双头龙都由C编写。不过它们之间还是有一些类似之处:
都惯用AES加密和XOR编码
对于失陷主机的root用户和非root用户区别对待
网络数据包整体结构,都是Header,Key,Payload三段拼接
都会用cat/etc/*release,cat/etc/issue等命令来获取系统信息
AES加解密的IV都是硬编码的\x00\x00\x00\x00\x00\x00\x00\x00
当然,不同之处也很明显:
双头龙的关键字符串会用StackString的方式做隐藏,caja没有使用StackStrings
caja的C&C由硬编码Key的XOR编码处理,而双头龙的C&C则使用AES加密和Rotate编码
双头龙的AESS_Box是动态生成的,而caja的AESS_Box是硬编码的
双头龙还会对关键信息进行ZLib压缩,caja没有使用压缩处理
创建守护进程的方式不同,双头龙会直接调用daemon()系统接口来创建守护进程,caja会有条件地通过手动fork的方式创建守护进程
指令码没有相同之处,各个指令对应的功能也大不相同
caja进程启动时,如果传入参数的数量(argc)小于或等于2,则会创建守护进程,否则就以普通进程的方式运行:
caja的C&C通过固定的Key0xFFABFACB经过XOR循环解码得来:
caja样本中还有很多关键字符串,都用与C&C编码同样的方式做了循环XOR编码,解码之后如下:
/dev/urandom
/dev/random
/var/lib/libuuid/clock.txt
clock:%04xtv:%lu%luadj:%d\n
clock:%04xtv:%016lu%08luadj:%08d\n
address
uid=%d(%s)
/system/build.prop
ro.product.manufacturer
ro.product.model
pvXqjwrSRtNNKMcouPJIAheNqthopLtFgqxSpqKglZTWLxkfmTpMCWcupjkhwfMeYLWncHtPiOLUlxBaStovpqrEbeLxjZChnyup
IENyfwOXIDiMTQYWdduYtHWSxRLhxKhgQUgxTwuBZDQvVqrZVnzpUXJrPWbmGiUYcCvVYsZAxrVsHOrfbsuVqFPfBQTJYqHCSEat
rylfAbMCDurbSirYTgDrGhazjRPMzphRptWPuIUXclAwVRWPYbIELIeUbviBmqsBJQTFyNfcAFavxXkXASdlchfeeQFqgzurpnWp
TfpnZdTBdWnUyiYQPlveDFywVbvWHOfATupSZiVEGLyfTYVJkSNpxNLUrIRYwyySSqmtyiAfTYMoXjXJbnYaCJwTUPRqnSKHiXbi
GVfiOoOWcjaWKOdGCIkIcESiCjDkrieXFjHtZvREhRAtFfZJpkssOkcTVhFmRJMxStsuPkYybaRjHsSWCMQTyuMuBrGtassuMKqd
ekmMtOJFoBcgWaEkUNqLBQDaYJDWpDNVNBjhpTofWrNTrrFNexahnfJOOOKGrZBfALOrgcZctMxnGcCKAfupkdFBSRhjQIQSVEMb
WJgsviUIHWIPfeIsqCTBVAuWhxSUgsjEbpWYxRieNRvvVdpNhipEklATlUprnyVQptPokXtAqqxluMBdxQIHDKdOFsHutekIyBXk
iIOfeDzvkmWweezveDUBzsfbHKNLMgjwOABSFaQQmomrsLoYQicqdhrKRfvflhBZHctmEjEsyQJsezrUItMLAeXTLUAybDZkFsZL
/sys/class/net
id2>/dev/null
uname-a2>/dev/null
whoami2>/dev/null
cat/proc/cpuinfo2>/dev/null
cat/proc/meminfo2>/dev/null
cat/proc/version2>/dev/null
cat/proc/partitions2>/dev/null
cat/etc/*release/etc/issue2>/dev/null
00:00:00:00:00:00
/sys/devices/virtual
device
/proc/self/exe
/dev
/etc
/var/tmp
/tmp
GET%sHTTP/1.1\r\nHost:%s\r\nConnection:close\r\n\r\n
其中以下几条命令用来收集失陷主机信息:
cat/proc/cpuinfo2>/dev/null
cat/proc/meminfo2>/dev/null
cat/proc/version2>/dev/null
cat/proc/partitions2>/dev/null
cat/etc/*release/etc/issue2>/dev/null
以下4个目录,caja会探测是否有写权限后,选择一个目录写入单一实例的Lock文件:
#针对root用户的单一实例Lock文件目录
/dev
/etc
#针对非root用户的单一实例Lock文件目录
/var/tmp
/tmp
caja会获取失陷主机本地大量的系统信息、网络配置信息和用户信息,其中网络接口名和网卡硬件地址会被拼接起来计算一个哈希值,并把长度为16字节的原始二进制哈希值保存到本地文件中。这一串哈希值,可以看作是caja为每一台失陷主机生成的UUID。
该文件的文件名生成逻辑与上述单例Lock文件类似,不过种子字符串则是另外两条:
#非root用户
TfpnZdTBdWnUyiYQPlveDFywVbvWHOfATupSZiVEGLyfTYVJkSNpxNLUrIRYwyySSqmtyiAfTYMoXjXJbnYaCJwTUPRqnSKHiXbi
#root用户
iIOfeDzvkmWweezveDUBzsfbHKNLMgjwOABSFaQQmomrsLoYQicqdhrKRfvflhBZHctmEjEsyQJsezrUItMLAeXTLUAybDZkFsZL
生成的目标文件名:
root用户:.MgjwOABSFaQ
非root用户:.HOfATupSZiV
文件最终存入的目录为以下目录之一:
/dev/
$HOME
/etc/
当前进程文件所在的目录
/var/tmp/
/tmp/
执行起来后会随机伪造一个进程名
生成10-15个随机小写字母字符串
将上述字符串用[]括起来,形成一个如[lkjsdiorethgn]的进程名
接着获取本机信息,之后进入生成上线包的流程,caja上线包的Payload部分,按顺序包含以下信息:
UUIDBytes
MagicNumber(VersionNumber)
hostname
未修改进程名之前的进程文件路径
网卡接口及IP地址
系统和网络配置信息
一系列cat命令执行查到的详细系统配置信息
第二个字段是硬编码在样本中的一个常量数值:0x32,这个数值在caja的MIPS版和x86-64版本的样本中是相同的,所以我们可以把它当作是一个版本号,或者标志此款木马的MagicNumber。
其中涉及的三个主要函数enc_and_append_field_data_*(),主要功能是对int类型的数据(主要是PID)、c_string类型的数据(各种系统信息)和目标数据对象分别做的编码和拼接处理。对于int类型数据,直接以4字节的int_32类型表述,对于c_string类型的数据,先转成目标数据对象在处理。目标数据对象结构如下:
structpayload_field{
char*data_ptr;
intdata_len;
以其中UUID字段的处理流程为例:
分为以下几个步骤:
生成随机的单字节XORKey
对UUID字节串中的每个字节,奇数序的字节做XOR编码,偶数序的字节做逻辑非运算
将UUID的data_len/XORKey/编码后的字节数据拼接起来,形成如下结构:
后面的每个Payload字段,都用相同的逻辑进行编码、拼接处理,最后整体的结构如下:
可以看到最前面的uuid字段,前4个字节表示长度0x10,第5个字节0x3d是本字段的随机XORKey,后面0x10的字节就是实际的数据字节,后面依此类推。
生成Payload完成后开始进入Header包构造流程在样本中用长度为0x35的结构体表述,结构体对象创建代码如下:
上线包Header结构体创建之后,会对以下关键数据做初始化:
生成[0x5,0xF]之间随机长度的一段数据,作为PayloadAES加密的密钥。该密钥的长度存放在RegisterHeader偏移0x08处,密钥数据的地址存放在偏移0x25处;
把前面生成的RegisterPayload数据的地址赋予Header偏移0x2D,数据长度存放于Header的偏移0x0B和0x15处
在Header偏移0x11处设置上线包的指令码为0xB76E
前面随机生成的长度为[0x5,0xF]之间的XORKey,此处将前序环节编码、拼接好的上线包Payload再做一次AES-256CBC模式的加密,AES的IV为硬编码的\x00\x00\x00\x00\x00\x00\x00\x00。
前面处理好了上线包的Payload,caja就把上线包结构体对象的前0x25个字节,和上线包Payload用到的AES密钥以及加密过后的上线包Payload拼接起来。步骤如下:
最后,caja为上线包的Header也做了单独的编码,编码过程与前面Payload各字段的处理稍有不同:
从第6个字节开始,先进行逐字节编码(XOR/逻辑非和其他),XORKey为前5个字节
再把第一步编码过后的0x25个字节做翻转(Reverse)
最终形成的上线包概要结构如下:
指令功能部分如下:
对于C&C响应数据包的结构,与上线包结构一致,也分Header,AES_Key,AES_Encrypted_Payload三段,解密/解码逻辑为前面上线包数据加密/编码过程的逆序即可。
总结
目前,基于奇安信威胁情报中心的威胁情报数据的全线产品,包括奇安信威胁情报平台(TIP)、奇安信天狗漏洞攻击防护系统、天擎、天眼高级威胁检测系统、奇安信NGSOC、奇安信态势感知等,都已经支持对此类攻击的精确检测。
IOC
MD5:
b217729d1da6363232d4724f9696b6bb
3c7c1dc5f88267fc2cec0b8e412a5a49
64e7ec81190ecada6848dae767c740eb
0152aadab26b41e3f53c95096d0e3a2e
c93ceb5c5983e1c2ddfa035ee398022c
7913d1a143e6fd3a8621fd22bb712200
69c7a7c5adda09c3ce6e47c7e76d7e7e
4B2DF0098372485369E8088EEB4CD554
641b7ab0d42d283f5b34de84cdcdcdc6
a2d70e7ab7dccf5efcc32b5bbfdecad9
a54330bc0fdc9c9585f6024dde340177
参考链接
【1】https://mp.weixin.qq.com/s/dGW0FrbZZ5UA6KuuZB8J_g