Fork me on GitHub

记一次耗时几天的挖矿脚本应急响应

record a server emergency response

其实距离这次响应已经有一段时间了,之前因为各种开发任务一直排得满满当当,无暇整理,但为防遗忘,决定还是得抽时间记录成文,时刻提醒自己,写得略长,主要是复盘当时自己和小伙伴的思路和操作。完全解决问题虽然耗时几天,实际处理问题也就几个小时,但是因为当时我和小伙伴对于这类问题都没什么处理经验,所以排查不够充分,又让服务器白给别人当了一天矿机。

发现问题

某日,正当我和小伙伴分好任务敲着代码时,其它组员报告公司A站点的搜索服务S工作不正常,搜索多个高频关键词后无任何返回结果,这个问题最近发生得有点频繁了,第一、二次发生时我们只是重启了服务。但是当第三天差不多同一个时间又接到报告说搜索服务挂了的时候(离上次服务挂掉只隔1天),我们嗅到了不一样的味道。

排查过程

1.开发自查

搜索服务S这个业务之前一直稳定运行(一年不重启都不会挂的那种),且系统资源占用也不高,最近几个月开发都没有做过任何涉及此搜索服务的修改。再者,根据现有系统架构设计,很容易分析出就算那个站点A挂了,这个搜索服务S都应该不会挂的,所以我们立刻开始着手排查问题。

2.服务器站点漏洞扫描

以前架构设计的时候,为了减轻服务器A的压力,服务S是部署在服务器B上的。虽然服务器B有公网IP,但是上面部署的都是公司内部的各种平台。不过为了以防万一,我们还是用线上漏洞检测基本扫描了DNS解析到这台服务器上的域名。

3.服务器自查

一般来说,平时稳定的服务挂掉一般是资源不足引发的,所以果断htop(Linux系统中的一个互动的进程查看器,一个文本模式的应用程序)了一下。

一看吓一跳,4核CPU占用100%,平时大概40%,立刻htop中按Shift+P查看CPU占用高的进程,发现是root用户启动的crontab任务,果断kill掉,服务器瞬间恢复正常。

然后自然去排查了相关进程,但是,奇怪的是本地crontab任务没找到,后来又和小伙伴找了半天,发现竟然这个crontab任务居然是root用户启动。然而我们一般登录服务器和部署应用默认是用具有root权限的x账号,瞬间凉凉,都获得root权限了吗?然后我们去相关目录下进行了取样。打包了(ssh.tar.bz2和ttp.tar.bz2)两个样本。

当时扔到一些在线病毒检测网站上,但仅有少数提示可能是病毒或木马,但并没有更具体的信息。所以我和小伙伴也只能在服务器上继续探索,顺便检查下打包的样本。

查看了pools.txt,发现关键词“Monero”,当然也有钱包地址等信息,看来是挖矿脚本无疑。安装可执行文件配置完备orz…另外还发现一个ip_info.txt,怀疑是其它已被攻击者用于挖矿的服务器。

monero

然后又是一阵搜索,发现cron.d的内容,于是赶紧去到相关目录下,把内容都清理了。大致看了下任务,一堆定时重启任务让木马保活,还重定向了标准输出和错误输出,让服务器维护人员排查时无法从crotab log中找到信息。

(补充:/dev/null 2>&1, 准确的说是先将标准输出1重定向到/dev/null中,再将错误输出2绑定到标准输出1上。 /dev/null代表linux的空设备文件,所有往这个文件里写入的内容都会丢失,俗称“黑洞”。)

crontab

然后搜索引擎一波看服务器被挖矿的问题,发现关键词Redis未授权访问漏洞,仔细查阅了一下,终于回忆起以前做过的靶机联系,心下了然,因为我记得服务器B这台服务器上的确有redis是用的默认配置,而且一直没设置认证,然后又去防火墙看,果然6379的访问没有限制,赶紧redis加密码认证,和现有权限的人check并clear一遍authotrized_keys。

但是哪个账户是提权设置的尚未确定,所以执行cat /etc/passwd也检查了下,虽然有一堆用户,但是没有发现什么明显异常,而且因为担心影响线上业务,也不敢随便禁用。

习惯性检查了权限,正常:

1
2
查询特权用户特权用户(uid 为0)
[root@x.x.x. ~]# awk -F: '$3==0{print $1}' /etc/passwd

然后就停止处理了,准备第二日(第4天)看下情况。结果,不出所料,第4天同一时间,木马挖矿脚本又被启动了。这下确认肯定是入侵者留的登录账号还可用。

习惯性用who检查了一下,无可疑用户在线。例行清理定时任务和保活脚本之后我陷入沉思,到底该怎么排查出可疑用户,这时小伙伴突然提问检查可远程登录的用户没有,一语惊醒梦中人。

1
2
查询可以远程登录的帐号信息
[root@localhost ~]# awk '/\$1|\$6/{print $1}' /etc/shadow

发现一个名为ftpuser的用户有远程登录权限,颇为可疑,赶紧cat /etc/passwd对比检查。

ftpuser0

图中ftpuser的权限是我们修改后的,当时检查时发现的权限为:/bin/bash

因为一看权限和目录可知上方ftp用户才是ftp服务在用,那么下方这个ftpuser就显得相当可疑了。

但是为防误伤,我们只是先修改了:/bin/bash为其它内容,使其不能正常登录。

从第5天后又持续观察了约一周,服务器B上各性能参数一直正常,且S服务一直稳定运行。我和小伙伴们才放下心来,这次应该是真的排除隐患了。

后来和Leader沟通后,Leader觉得还是不够安全,一周后让我们重新部署了一台和服务器C业务完全一致的服务器D,将公司所有请求服务器C的业务都改为向服务器D请求了。(完全理解,毕竟那台服务器的IP已经被攻击方盯上了。)

排查结果

  1. 主要原因:服务器B上的redis服务以root权限运行且没有设置password,直接导致Redis未授权访问漏洞出现并被利用。

  2. 次要原因:公司服务器安全加固不足,导致敏感服务直接被公网访问,sudo命令可不用密码执行。

  3. 再次要原因:SEO使用的一些封装好的扫描和优化工具将服务器IP暴露给了黑产,增加了服务器被攻击的概率。

    这条是技术组内部推测,所以最终没有上报,一是因为缺乏证据站不住脚,二是这点相较前面2点就显得微不足道了(但是原则上如果有确凿证据,还是应该上报)。

解决方案

  1. Redis设置密码,以便提供远程登陆

    打开redis.conf配置文件,找到requirepass,添加requirepass yourpassword后带配置文件重启redis,yourpassword为远程连接redis的密码。

    1
    requirepass yourpassword
  2. 修改redis.conf的默认配置并带配置文件重启redis,采用绑定IP的方式来进行访问控制

    1
    2
    3
    4
    # If you want you can bind a single interface, if the bind option is not
    # specified all the interfaces will listen for incoming connections.
    #
    # bind 127.0.0.1

    把 #bind 127.0.0.1前面的注释#号去掉,然后把127.0.0.1改成你允许访问你的redis服务器的ip地址,表示只允许该ip进行访问。

  3. 清除./ssh/authotrized_keys中可疑的公钥

  4. 清除挖矿脚本

  5. 限制或清楚被攻击者利用的带远程登录权限的账户

  6. 重新部署一台带公网IP的服务器,替换被攻击的服务器工作

问题反思

  1. 开发人员安全意识薄弱,虽然知道redis没有密码,却忽视了Redis未授权访问漏洞的问题。
  2. 服务器上关键信息管理不足,导致发生问题时,难以排查问题用户。
  3. 服务器监控不到位,直到业务挂了多次后才发现问题。
  4. 问题排查经验不足,没能及时彻底根除问题,还需多学多练积累经验。

预防措施

  1. 做好服务器的基本加固和防火墙设置。
  2. 做好服务器关键业务的监控, 线上运行业务发生异常时能及时提醒。
  3. 定期关注安全事件,发现相关业务有风险时要及时自查。
  4. 定期给服务器升级和打补丁。

后记

幸好这次服务器漏洞只是被批量操作用来挖矿,如果是针对公司的恶意入侵行为,后果不堪设想。所以,但凡有公网IP的服务器,一定要做好安全加固和灾难备份,不要有一丝侥幸心理。另外通过反思自己在此次应急响应中的一些不足,给后来人提供一些参考。

(PS: 首发于某低调的论坛,虽然目前还没过审TAT)

REF

10.Redis未授权访问漏洞复现与利用

-------------  Fin    Thanks for reading!  -------------

本文标题:记一次耗时几天的挖矿脚本应急响应

文章作者:TesterCC

发布时间:2020年04月14日 - 21:04

最后更新:2020年04月15日 - 20:04

原始链接:http://blog.fullstackpentest.com/record-a-server-emergency-response.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。