【安全研究】Symbiote分析与检测

2023-02-06 12,395

↑ 点击上方 关注我们

一、概述


近期,我们发现一种新型的Linux恶意软件Symbiote被报道出来,该恶意软件被描述为“几乎不可能被检测到”。之所以被命名为Symbiote(中文含义:共生体),也是基于该样本的攻击性质:作为非独立运行的共享库文件加载到其他正在运行的进程中。其目的是窃取远程主机的登录凭证以及后门访问。


下面将对该恶意软件的其中一个样本进行详细分析。


二、详情分析

1加载方式


LD_PRELOAD是Linux系统的一个环境变量,它可以影响程序的运行时的链接(Runtime linker),允许你定义在程序运行前优先加载的动态链接库。通过这个环境变量,可以在主程序和其动态链接库的中间加载别的动态链接库。通过覆盖正常的库函数,注入到正在运行的进程,从而达到特定的目的。


该样本使用同名、同参数的自定义函数,通过LD_PRELOAD的方式加载到其他进程中,进而覆盖掉同名的系统函数,优先调用自定义函数,达到调用过程劫持效果。


所有的劫持函数都如下图逻辑:


 图1

2进程隐藏


该样本会隐藏自身加载到其他程序中的共享库痕迹,以及隐藏一起部署的其他恶意程序。


  • 隐藏其他恶意程序

实现方式为,挂钩readdir、readdir64、stat、statx、fstatat、fstatat64等函数,目标文件在/proc下时,获取执行命令,判断是否为需要隐藏的进程,若是,则跳过该条目信息,继续执行返回下一个无需隐藏的文件条目信息。


 图2


 图3


本样本隐藏的进程名

certbotx64

certbotx86
javautils

  • 隐藏共享库痕迹

除了隐藏一起部署的其他恶意程序,还会隐藏自身模块。如用户可通过ldd命令输出指定的每个程序或共享对象所需的共享对象(共享库)。如下图所示,ldd命令会调用execve函数,该样本就通过挂钩execve的方式劫持返回结果。


图4


通过LD_TRACE_LOADED_OBJECTS环境变量判断是否为列出其动态库依赖项(ldd命令)。



图5


具体隐藏过程如下,fork一个子进程去执行命令,返回结果到管道。


图6


在本进程中,使用后面的字符串数据覆盖掉需要隐藏的自身库字符串再输出,达到隐藏效果。


图7


运行效果图如下,该样本目前只是过滤硬编码写入的文件名,改名后就会显示出来,不排除后续版本会更新为自动获取名称。


图8


3文件隐藏


除了隐藏进程相关的文件,还会隐藏其他非进程的信息存储文件。


在Linux系统中,使用ls、dir、tree等命令显示出目录下的文件信息,通过挂钩文件相关函数readdir、readdir64就可以实现文件隐藏。


具体细节如下,读取到需隐藏的文件流时,继续读取下一个,直至该文件流为非隐藏文件或为空才返回。这样就跳过了恶意文件,达到隐藏目的。

图9


 图10


隐藏的文件列表

certbotx64

certbotx86
javautils
bancodobrasildev
search.so
certbot.h
cert.h


4网络隐藏


该样本采用了三种流量隐藏的方法,分别是劫持fopen函数、劫持注入eBPF、劫持libpcap库函数。


  • 劫持fopen函数

检测到程序使用fopen读取procnet目录下的文件时,便会生成一个临时文件,读取源文件的每一行并将过滤掉指定端口的数据写入临时文件,最后将过滤后的临时文件句柄返回调用者,达到隐藏效果。


图11


图12


  • 劫持注入eBPF

BPF(Berkeley Packet Filter), 中文翻译就是伯克利包过滤器。从字面意思可以知道它的主要功能是用来过滤数据包的。根据介绍,BPF 钩子位于网络驱动中尽可能早的位置,无需进行原始包的复制就可以实现最佳的数据包处理性能,挂载的BPF程序是运行过滤的理想选择。


下面是BPF流程图:


 图13


劫持方法是挂钩函数setsockeopt,该函数用于设置socket状态。


检测到使用SO_ATTACH_FILTER方式调用时,表示该调用用于数据包过滤。此时就会先将自身的BPF字节码添加到其他软件的BPF字节码前,先一步过滤掉需隐藏的流量,再执行其他软件注入的BPF字节码进行过滤。


本样本用此方法过滤TCP连接中指定端口的流量(包括入站出站)。



图14


  • 劫持libpcap库函数

实现方法是挂钩函数pcap_loop、pcap_stats这两个函数。


挂钩函数pcap_loop、pcap_stats这两个函数,在函数pcap_loop中,劫持捕获流量后执行的回调函数,在恶意回调函数中,匹配流量中需要过滤的域字符串,通过包数计数器加一,丢掉这个流量包。


本样本中用此方法隐藏UDP流量数据。



图15



图16

5恶意功能


该样本的主要目的有:窃取用户登入凭证,后门远程访问、文件下载命令执行。


  • 凭证记录

当用户使用ssh或者scp并通过公私密钥key进行远程主机访问时,挂钩后的read便会获取调用程序命令行参数,获取远程主机的地址、连接RSA私钥等信息。



图17



图18


使用简化的CR4算法加密后,存放在/usr/include/cerbot.h文件中,并通过 DNS 地址 (A) 记录请求泄露到攻击者的控制的域名。



图19



图20


  • 后门远程访问

该样本劫持Linux系统上可插拔认证模块(PAM)的关键函数pam_set_item、pam_authenticate、pam_acct_mgmt。其中pam_set_item函数用于截取用户登入密码,pam_authenticate函数用于校验密码。



图21



图22


这意味着攻击者可以使用写入的硬编码口令,以任意用户远程访问受害者服务器。


而当其他用户使用远程访问工具(ssh)访问受害者服务器时,便会获取远程主机ip、登入口令等信息,作为凭证窃取的一部分发送至攻击者域名。


  • 文件下载命令执行

在使用pam_authenticate函数进行身份验证时,若不是攻击者访问,还会向其命令与控制域C&C发送 DNS 地址 (TXT) 记录请求。TXT 记录的格式为%MACHINEID%.%C2_DOMAIN%。


如果收到响应,恶意软件使用 base64 解码内容,使用Ed25519算法检查内容钥签名,使用 R** 解密内容,并在生成的 bash 进程中执行 shell 脚本。


6CR4


在该样本中,所有的字符串都是通过简化的CR4算法获取,该CR4算法核心如下:

















S = [0]*256for i in range(256):    S[i] = i    index = 0for j in range(256):    index = (S[j] + index + initKey[(j%keylen)]) % 256    S[j],S[index] = S[index],S[j]
index = 0j = 0for OdrText in range(textlen):    j = (j+1) % 256    index = (index + S[j]) % 256    S[j],S[index] = S[index],S[j]    hexList[OdrText] ^= S[(S[j] + S[index])%256]


三、检测思路

底层函数绕过:该样本是通过挂钩用户层的一些关键函数进行隐藏,可以通过更底层的文件操作函数进行检测。


特殊工具:还可以使用完全静态编译的工具,如busybox,该工具静态编译Linux常用命令,不依赖共享库,此方式可以破解该样本的隐藏手段。


行为特征检测:该样本目前还未隐藏export与环境变量显示相关的命令结果,所以还可以检测环境变量LD_PRELOAD,进而发现问题。


流量特征检测:既然在终端上不好检测流量,那就在在网络出口处进行流量检测。


欺骗检测:针对搜集到的隐藏文件信息,创建同名文件判断是否被隐藏,也可以检测。


内存特征匹配:经过测试,可以使用yara规则扫描进程内存检测╭( `∀′ )╯。


四、IOC

用于接收凭证记录数据

x3206.caixa.cx

dev42.bancodobrasil.dev

用于下发命令执行数据

x4206.caixa.cx

dev21.bancodobrasil.dev

凭证存储路径

/usr/include/cerbot.h

/usr/include/java.h
/etc/mpt64.h



本文作者:安全狗

本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/195368.html

Tags:
评论  (0)
快来写下你的想法吧!

安全狗

文章数:32 积分: 180

基于智能驱动的新一代云安全公司

安全问答社区

安全问答社区

脉搏官方公众号

脉搏公众号