道路千万条,安全第一条——一次服务器被入侵的处理经过

容器为何自动停止?

服务器为何操作卡顿?

进程的神秘连接到底指向何处?

发现——自动停止的容器

某日发现部署在服务器上的一个容器被停掉了,开始以为是同事误操作停止或删除了。

但登录服务器重新启动容器的时候发现一个奇怪的现象:容器启动后几秒钟便会自动停止。

一般来说这种情况可能是容器本身有问题。

但是查看容器日志并未得到任何错误信息,而且该容器镜像已在其它服务器稳定部署运行,应该不会有bug。

所以猜测是系统资源不足,例如磁盘、内存、CPU。

查看磁盘剩余量还比较多,但是在用top命令查看CPU和内存的时候发现了异常:某个进程CPU使用率达到了99%。

当然这种情况对于我们公司的服务器来说也不是什么特别惊奇的事,因为我们通常会在服务器上执行一些计算任务,占用大量CPU也是很正常的事情。

但由于这台服务器除了我几乎没有其他同事使用,而且进程命令行看不到,所以引起了我的怀疑。

验证——异常不止一处

挖矿进程身份确认

如此高的CPU使用率,让我想到的是最近流行的挖矿病毒。

通过netstat -anp命令查看该进程是否建立了外部网络连接。

果然建立一个连接,指向 5.196.26.96 这个IP地址。在 https://www.ipip.net/ip.html 查询一下该IP地址,指向国外某地。

进一步验证了我的猜测。因为国内的服务器有严格的备案管理机制,所以很多攻击者都会将服务器部署到国外。

为了进一步确认,再次到威胁情报平台进行查询 https://x.threatbook.cn/ip/5.196.26.96

平台也给出了威胁警告,可以大胆的推定这就是一个挖矿进程。

当然如果想进一步确认,可以提取执行文件的md5值到相关网站进行辨认。

挖矿程序从哪里来?

挖矿程序一般都是由木马下载脚本然后执行,所以用history命令检查一下下载行为。

没有找到可疑的下载,很可能黑客清除了操作记录或者是通过别的途径下载。

为了进一步排除可能有其它病毒程序作为守护进程定时启动或者开机启动挖矿进程,检查一下crontab配置信息。

也未找到新添加的可疑文件,所以黑客应该并没有设置定时任务。

同时也未找到可疑的开机启动项配置。

可疑的镜像与容器

到了这一步,线索中断。只能换个角度思考了~

据管理员说平时这台服务器很少使用,而且使用的是强密码,密码泄露的可能性很小。

再结合我部署的容器停止时间进行分析,应该是在我部署完成后几小时内服务器被入侵的。

所以怀疑很可能和我的操作有关系。

在使用docker命令进行查找的时候又发现了新的情况。

一些容器使用了未知镜像(heybb/theimg2)或者使用了非官方的镜像(zoolu/ubuntu)。

上docker hub上搜索这些镜像,都找不到Dockerfile,也无readme之类的说明。而且上传时间都很新,但是下载量增长却很快。

这就奇怪了,这种既无说明,命名也十分怪异的镜像竟然会被多次下载,所以可以推断就是黑客上传的携带木马的镜像。

再利用docker inspect命令查看这些容器,发现该容器并没有通过挂载目录的方式写入系统文件,而是会执行一个 mac.sh 的脚本文件。

cat命令查看该文件,只有一行命令

显然这是在挖门罗币。

小结

现在发现不止一个黑客入侵了服务器,有的黑客部署了挖矿容器,有的黑客部署了挖矿进程并删除了记录。

处理——清除进程,关闭漏洞

首要任务当然是清除挖矿进程和容器,以及对应的执行文件和镜像。

当然这只是治标不治本的方法。

要从根本上解决问题需要进行溯源分析,避免服务器再次被入侵。

结合以上线索以及个人经验分析,很可能利用Docker的漏洞进行入侵的。

我在部署容器的时候启动 Docker remote API 服务,很可能这个服务暴露到了公网上,立即在浏览器中输入服务器IP地址和对应端口,果然可以访问!

原来服务器运营商并没有提供默认的防火墙服务,机器上的端口是直接暴露在公网上的。

黑客入侵的途径也基本上可以猜测了,通过 Docker remote API 服务器操作容器,将带有挖矿进程的容器部署到服务器上。

或者将挖矿程序通过目录挂载的方式拷贝到服务器上,以某种方式触发并执行。

要修复这个漏洞也很简单,停止对外暴露服务。

建议

网络安全其实是一个很重要的课题,但是开发人员很多时候都缺乏对其足够重视。

针对这次事件,总结了几个经验:

除了一些 web 服务(http/https),不要使用默认端口。

黑客的入侵操作一般都是自动化的、批量的。

操作是使用端口扫描工具,对特定的默认端口扫描。

比如本例中肯定是扫描到本服务器的 2375 端口(2375是Docker remote API的默认端口)之后进行攻击的。

这个原理其实有点像打电话诈骗,用一些很低级的骗术把容易受骗的人群筛选出来。

所以我们平常在编写程序时尽量避免使用默认端口。

不要通过绑定 0.0.0.0 的方式暴露本不需要对外提供访问的服务。

之前在启动 Docker remote API 服务时监听 0.0.0.0 IP,是因为看到很多网上教程都是如此配置,但其实存在了很大的安全隐患。(把事情做好把事情做完区别真的很大!)

其实该服务在使用中并不需要提供给外网,实际上只要监听子网IP就够了。比如 127.0.0.1、 172.17.0.1。

尽可能多的考虑非正常情况

在开发的时候我们除了考虑程序正常的输入输出之外,还需要假设一些特殊的情况来进行测试。

下面是开发者和黑客的思维方式区别:

1
2
3
开发者:A -> 程序 -> B

黑客:S -> 程序 -> ?

开发者考虑的是保证输入A,就可以得到B。黑客很多时候会输入开发者未考虑的S,从而发现bug或漏洞。

使用防火墙限制端口访问。

网络服务,防火墙很重要。

这次的入侵和云服务器厂商都会自带防火墙的思维定势有关系。

通过证书验证访问者的身份。

对于需要提供对外访问的服务,使用身份验证也是一种有效避免攻击的手段。

例如Docker就支持TLS证书来验证服务端和客户端的身份。

总结

排查入侵木马的过程很像扮演一个侦探,通过犯罪现场的蛛丝马迹找到凶手以及行凶手法。

还好当初在发现问题的时候并没有马上采取重装系统这种简单粗暴的方式解决问题,不然漏洞依旧存在,服务器依然会被攻击。

关于更多更权威网络安全的知识可以参考《OWASP TOP10 2017》,里面有最常见的10类漏洞以及防御措施。

像本文中的Docker远程未授权漏洞以及类似的redis未授权漏洞都属于 OWASP TOP 10 中的漏洞。


作者信息:朱德龙人和未来高级前端工程师。