事情是这样的,为了存放qq机器人的用户数据,昨天我下载了PostgreSQL的docker镜像,当时docker运行一切正常。然后今天下午3点过,服务器商那边发了个邮件提醒服务器存在恶意文件,一连发了三条:
好家伙,赶紧ssh登录服务器,一眼就看到cpu被干爆了(直接100%占用,还能ssh上也挺神奇的)。
1. 分析排查
首先用top
看看什么程序占用了cpu资源:
一个名为kdevtmpfsi
的进程占用了几乎所有cpu算力资源,想都不用想,这肯定是一个挖矿病毒了,赶紧百度查了下确实如此:
还好这个病毒并不会破坏计算机内的文件,只是占用你的CPU。这个病毒还有一个守护进程名字是kinsing
。
服务器商提醒我恶意文件来自于/tmp/kdevtmpfsi
、/var/tmp/kdevtmpfsi
和/tmp/kinsing
,然而我在主机相应路径下并没有找到对应的文件,要么就两种情况,病毒在执行文件后删除了原文件,或者这个病毒在docker文件中。
直接在进程中查这两个程序对应的PID:
1 | ps -aux | grep kinsing |
然后直接kill掉(先kill守护进程kinsing
,再kill挖矿病毒kdevtmpfsi
):
1 | kill -9 7842 |
直接kill是因为现在需要先把CPU资源暂时释放出来,防止你在登录界面卡死。这种病毒一般会隔一段时间重新运行,因此我们需要找到问题的根源在哪。
从根目录开始找这两个文件的位置,并删除:
1 | find / -name kdevtmpfsi |
我这里仍然不清楚为什么搜到两个文件却只能删一个,可能在删除的时候已经引起病毒脚本删除另一个文件了?总之能找到文件就删,一个不要放过。
接下来检查是否有异常启动的定时任务(因为这个病毒会定时重启,所以要考虑这种可能):
1 | crontab -l |
这里能看到有一个定时任务,我印象里没有制定过定时任务,所以直接将账户的定时任务取消(谨慎!不可恢复,看到来自别的ip的可疑定时任务,建议用crontab -e进入配置界面,删除异常定时任务,wq保存退出):
1 | crontab -r # 不建议这样做!这里只是记录我的操作 |
还有一种方法可以查所有账户的定时任务:
1 | cat /etc/passwd | cut -f 1 -d : |xargs -I {} crontab -l -u {} |
这里相当于将所有用户名提取出来,执行crontab -l
,同样是发现异常定时任务的话删除。
2. 病毒溯源
在一边删除病毒的同时,我这里一边在溯源病毒的来源= =
首先看看是否有人用ssh黑入root账户:
1 | less /var/log/secure|grep 'Accepted' |
然而ip登录地址全是我常用的ip地址,说明不是通过ssh登录root账号注入的病毒。
再看看TCP连接和监听端口是否运行可疑程序:
1 | netstat -anltp |
并没有任何可疑程序的运行。
这个时候我发现这些病毒文件毫无例外来自于docker
的overlay2
文件系统,想着最近用过的只有PostgreSQL
容器,内鬼八成是它了。
查看我的本地docker镜像库:
1 | docker images |
前面查到的kinsing
和kdevtmpfsi
文件来自于以下文件夹:
/var/lib/docker/overlay2/cb454dcc5c6592a9389757846a15e41d8bf6d68a7480f59aab579bd307baaeca
问题来了,怎么查看后面这一长串哈希值文件对应哪个镜像?
查看现在正在运行的docker镜像:
1 | docker ps -a |
查看可疑的postgresql镜像元数据:
1 | docker inspect 27d1f4378405 |
返回的是一个json格式的元数据,也可以参数-f获得更具体的key:
1 | docker inspect -f '{{.GraphDriver.Data}}' 27d1f4378405 |
好家伙,在得到的postgresql镜像元数据中可以找到上面那个一长串哈希值文件夹,真相大白了:病毒就是从postgresql容器注入的。
找到病毒起源后,那就是停止删除一条龙,拜拜了您内~
1 | docker stop pgsql # 停止实例 |
其实在上面删除病毒源文件和进程后,病毒就已经不再重新运行了。此时我的数据库已经因为不明原因被破坏,且查到了病毒来源的docker镜像,就顺便删了= =
3. 复盘攻击原因
一开始我以为这个病毒是通过端口扫描工具,找到端口漏洞后注入病毒的,然而并不是。
在找到kinsing
和kdevtmpfsi
两个文件的时候,我还在同一个文件夹中找到curl
文件,基本上可以确定这个挖矿病毒是通过curl
命令不断下载病毒并执行的。容器一开始是不存在问题的,病毒为何在两天后突然爆发?
从一开始服务器商提醒有恶意文件开始,那个时候并没有在对应的位置发现有恶意文件,而docker中可以找到,也可以说明是docker被入侵导致的注入病毒程序。可惜docker被我删除了,无法进一步看到病毒在我的postgresql容器中具体做了哪些文件的改动。
复盘前两天的操作,我在运行postgresql的docker镜像后,为了方便远程连接数据库以及可视化操作,我开放了postgresql的默认端口,并改为了所有ip均可接入(0.0.0.0/0)。postgresql的默认用户是postgres
,当然,我为了安全起见更改了密码(纯字母和下划线),不限制ip段的接入,可能给了黑客广撒网的机会,暴力攻破我的密码并下载了病毒(postgres账户下)。由于我的postgresql是在容器中运行的,所以病毒能在docker的overlay2
文件系统中找到,它不能改变我宿主机的文件系统,作为一个挖矿病毒,只要能用上我宿主机的算力即可。
以下这篇文章支持我的假想,具体说了黑客如何利用PostgreSQL的远程代码执行漏洞(RCE)攻击数据库服务器进行加密货币挖矿,一旦攻破数据库账户,就可以用PostgreSQL的“复制程序”功能下载并启动挖矿脚本:
PGMiner:利用PostgreSQL漏洞的新的加密货币挖矿僵尸网络 (qq.com)
还是要多注意自己的数据库安全,设置复杂一些的密码,并且限制ip段接入才是避免黑客攻击的最好方法。还有经过这次攻击后,我也顺便改了服务器的登录密码,关闭了一些用不到的端口,小心驶得万年船~
这次入侵的病毒文件我也下载到本地了,本来想了解一下是怎么实现的,可惜是二进制文件,没办法就去google了一下,果然有做网安的大佬详细解释了kinsing
作为守护进程是如何运作的,以及挖矿病毒kdevtmpfsi
的详细运作方式:
Learn the Attack Patterns of Kinsing with Sysdig
因为我是docker被入侵,直接删了出问题的镜像一了百了,如果你是linux服务器被入侵,这里有几个细节值得注意:
kinsing
会添加定时任务,一定要删除(我应该是docker中被添加了,所以宿主机中找不到);这个守护进程会检查kdevtmpfsi
进程的状态,若被删除会重启,所以要先删除这个守护进程;并且这个守护进程会读取系统中的SSH密钥,通过密钥横向转移到你其他机子上:
所以最好再看看自己的密钥中是否有可疑的数据,防止黑客留下后门。
至于这个kdevtmpfsi
挖矿病毒如何分配你的系统资源,何如与矿池通信,都可以在上面的文章中看到。既然是个linux二进制可执行文件,反汇编拿到源码也不是不行,现在看看病毒原理就好,其他的就不整了。