摘要
莫名其妙的服务器就被攻击了,又被薅了羊毛,当做免费的挖矿劳动力了。

一、起因

上班(摸鱼)好好的,突然收到一条阿里云的推送短信,不看不知道,两台服务器被拉去作为苦力,挖矿去了。这不是耽误我摸鱼吗,再说你挖到的矿币又不带我分,岂能忍。本着对公司负责任的态度(实在没办法),这不收拾一下过分的挖矿脚本,对不起这么多年积攒的专业知识。

登录服务器,top 一下,ps 一下,crontab -l 一下,好家伙,只看到 CPU 异常占用了,却没发现到底是哪个玩意贪了我这么多资源。与以往的不太一样啊(你特么在逗我?)。

按照以往的经验,ps -aux --sort=-pcpu|head -10 一下,贪渎者肯定原形毕露。难不成穿了个马甲。仔细分析,可能不仅仅是马甲这么简单,更有可能是隐身衣。使出万能的百度大法,果然有几篇秘籍指出问题,一一对照下,只能发现大概,定位不到最终的“宝藏”地点。看来百度不行,得 google 一下了。这次秘籍多了起来,给出了一项专门破解隐藏进程的功法。

二、寻“宝”

BusyBox 是一个集成了 300 多个最常用 Linux 命令和工具的软件。甚至还集成了一个 http 服务器和 telnet 服务器,集成的包大小只有 1M 左右。有人将 BusyBox 称为 Linux 工具里的瑞士军刀。简单点说 BusyBox 就是一个集成了许多 Linux 工具和命令的大的工具箱。在嵌入式软件中,BusyBox 有着广泛的运用。

所以,下载 BusyBox,安装:

$ wget https://busybox.net/downloads/binaries/1.30.0-i686/busybox$ mv busybox /usr/bin/busybox$ chmod +x /usr/bin/busybox

查看 BusyBox 基本功能

$ busybox --help

使用瑞士军刀查看一下进程信息

$ busybox top

作祟者原型毕露,有个 /bin/daemon 进程,占用过高的 CPU 使用

同时使用 netstat 查看一下程序端口占用

$ netstat -anp | grep ESTAB

结果如下:

可以看到有一个程序占用端口 14444,连接的ip为 217.182.169.148,却并没有打印出程序的进程号,在shadan搜索一下,ip 为法国的,基本确定入侵使用的端口为 14444,先把端口禁用掉。

三、“六娃”的能力

既然确定是 /bin/daemon,那就需要找出这个玩意是怎么具有“六娃”的能力,又是如何进行挖矿的。

首先可以确定的是 /bin/daemon 是一个二进制执行程序,那就可以看看它的动态库依赖关系

$ ldd /bin/daemon

此时还未发现有任何异常的结果(请原谅眼神不好使,四个眼睛都没发现问题)

既然 ldd 无法找出异常,祭出大招,看看 /bin/daemon 所执行的系统调用

$ strace /bin/deamon


好家伙,不看不知道,居然有一个 ld.so.preload,来了个预加载。

一般来说,预加载 so 有两种方式:

  1. 修改/etc/ld.so.preload配置文件,这种方法对配置修改后运行的进程有效,而无法影响已经在运行的进程
  2. 启动进程前设置LD_PRELOAD环境变量,此方法只对当前进程生效

LD_PRELOAD 可以影响程序的运行时链接,它允许定义在程序运行前优先加载的动态链接库,通过这个环境变量,可以在主程序和其动态链接库的中间加载别的动态链接库,甚至覆盖正常的函数。

进程在启动后,会按照一定的顺序加载动态库:

  • 加载环境变量 LD_PRELOAD 指定的动态库
  • 加载文件 /etc/ld.so.preload 指定的动态库
  • 搜索环境变量 LD_LIBRARY_PATH 指定的动态库搜索路径
  • 搜索路径 /lib64 下的动态库文件

从上面的结果来看,加载了一个 /usr/local/lib/libprocesshider.so 动态库,从上面的 ldd 返回结果也看到了这个动态库,再仔细一看,这名字,不就是 process+hider
libprocesshider.so,Hide a process under Linux using the ld preloader. 官方的解释,本来可能只是作者觉得一个好玩的玩意,却被别有用心的人拿来做坏事。

找到这家伙,那好办了,先把它直接干掉。

$ rm -rf /usr/local/lib/libprocesshider.so

啥?万能的 rm -rf 大法居然失效了,这家伙身上居然给自己加了个盾,大招居然没有收到人头。

冷静一下,仔细分析。既然不能删除,那就是有着隐藏属性,等待技能冷却,我还有招。

$ lsattr /usr/local/lib/libprocesshider.so

果然,文件被追加了隐藏属性。可以看到有 ia 属性。

文件隐藏属性解释:

属性选项功能
i如果对文件设置 i 属性,不允许对文件进行删除、改名,也不能添加和修改数据;如果对目录设置 i 属性,只能修改目录下文件中的数据,但不允许建立和删除文件
a如果对文件设置 a 属性,只能在文件中增加数据,不能删除和修改数据;如果对目录设置 a 属性,只允许在目录中建立和修改文件,不允许删除文件
u设置此属性的文件或目录,在删除时,其内容会被保存,以保证后期能够恢复,常用来防止意外删除文件或目录
s和 u 相反,删除文件或目录时,会被彻底删除(直接从硬盘上删除,然后用 0 填充所占用的区域),不可恢复

既然加了盾,那把盾给破了就是:

$ chattr -ia /usr/local/lib/libprocesshider.so

什么,chattr 没权限,这是反弹伤害吗?这,玩不下去了啊。

试试分身术吧。

$ cp /usr/bin/chattr /usr/bin/chattr2$ chattr2 -ia /usr/bin/chattr

没报错,嗯,再试试

$ chattr -ia /usr/local/lib/libprocesshider.so

咋,还提示没权限。

再看一下 chattr

$ file /usr/bin/chattr

这这这,跟我这虚晃一枪呢。你把我原来的文件删了,给我放个空文件,你是想骗谁呢。

看来要重装 chattr 了,但是机器上跑了不少服务,担心有影响。集中精力,冥想三分钟,条条大路通罗马,此路不通,换路走。谁让咱兄弟姐妹多呢。

服务器都是选择的一样的镜像,版本一致,从其它未被攻击的系统中拷贝一份 chattr,(划重点)拷贝到服务器上时,请换一个文件名称,通过新的文件修改原来的文件。如 chattr2

$ chattr2 -ia /usr/bin/chattr$ rm -rf /usr/bin/chattr$ mv /usr/bin/chattr2 /usr/bin/chattr

正主归位,一切妖魔邪道即将化为无形。

$ chattr -ia /usr/local/lib/libprocesshider.so$ chattr -ia /etc/ld.so.preload$ rm -rf /usr/local/lib/libprocesshider.so$ rm -rf /etc/ld.so.preload

此时,通过 top 即可看到 /bin/daemon 进程。没有了隐身衣,无所遁形了吧。

那么,接下来,就应该干掉“罪魁祸首”了。大蛇精和蝎子精已死,救爷爷终于有希望了。

/bin/daemon 是通过软链指向 /usr/bin/daemon,不墨迹,直接干掉本尊。

$ chattr -ia /usr/bin/daemon$ rm -rf /usr/bin/daemon

当然,记得杀掉运行中的 /bin/daemon 进程

$ kill -9 2415

四、守护者

一般的挖矿脚本程序肯定都有一个守护进程,保证挖矿的进程被杀之后,可以重新启动,绝大多数是用的定时任务的方式。既然通过 crontab -l 没看到定时任务,那就看看 /etc/cron.d 目录下有没有:


果然,在 /etc/cron.d 目录下,存在着定时任务脚本,查看脚本内容:

$ cat /etc/cron.d/systemd

果然运行了一条定时任务,查看指向的脚本内容:

$ cat /lib/systemd/systemd-login

脚本文件没有内容,file /lib/systemd/systemd-login

very short file(no magic)

什么 ,先不管了,干掉再说。

$ rm -rf /lib/systemd/systemd-login$ rm -rf /etc/cron.d/systemd$ rm -rf /etc/cron.d/systemd~$ rm -rf /etc/cron.d/systemz~

打完野怪打小龙,打完小龙打大龙,等一段时间看看,还好,己方水晶没爆。

运行一段时间,一切稳定,算是暂告一段落。

五、总结

本篇文章还有很多的不足之处,并没有找到病毒攻击的入口,又是如何入侵到系统的,挖矿的脚本究竟运行在哪?按照正常的被攻击排错方式,一开始并不顺利。总结一下系统被入侵的排查思路,只是给后来者提供一下解决思路(希望大家的系统都很健壮,不被攻击)。

  • 查看系统的 CPU内存占用
  • 查询占用系统资源过高的进程
  • 排查定时任务,crontab -l 或者 /etc/cron.d 目录
  • 检查异常端口,如发现,禁用端口,堵漏
  • 使用 last 命令查看系统异常登录情况(一般攻击者会抹去入侵记录)
  • 使用 history 命令查看系统历史执行命令(一般攻击者会抹去历史命令)
  • 查看开机启动脚本 /etc/rc.local ,是否插入了开机启动进程
  • 通过 find /etc/cron.daily/* -mtime -1 查找前一天到现在被修改的文件
  • 找一台正常的机器,比较一下被修改文件的 md5

后续救援不如从源头堵住疏漏,平时使用系统时,可以从以下方面尽量保证系统安全:

  • 检查弱口令,使用强口令,能用证书的,尽量不使用密码
  • 不需要在外网访问的端口,尽量不开启,只开放在内网
  • 尽量使用普通用户启动服务,不要使用 root 用户启动服务
  • 系统被入侵,一般都是通过部署的服务暴露出来的漏洞,及时更新软件版本,加固系统
  • 修改常用软件服务的端口,尽量不要使用原有端口
  • 定时备份重要的文件数据,以防止服务器被入侵时,丢失重要数据

未完待续…