返回

记一次服务器被入侵经历

作为一个练习时长4年半的运维工程师,对于服务器的安全性一直有很高的意识。 虽然本人平常很懒不大更新博客,但是也记录过诸如《Linux登录的一些安全优化》《Linux服务器启用两步验证方式登录》这样的文章,深刻意识到守好登录口这扇大门的重要性。

可就在昨天,凌晨吃完了Bilibili的瓜,万万没有想到自己的生产服务器也出现了故障🤡小丑居然是我自己

发生肾么事了?

其实从登录到管理服务器过程都充满了各种不安全的因素,且让我慢慢梳理。

  • 故障的发生

7月14日下午,本是平凡打工的一个下午,突然天降一封邮件,内容大概就是生产的一个API接口可用性于16:27发生告警,可用性降为0%。 吓得我一下精神集中提高100%,准备先分析一下这个接口部署在哪里,继而又收到了我刚部署好不久的zabbix发来的CPU利用率极高的告警,此时是16:29

High CPU utilization (over 90% for 5m) CPU utilization is too high.The system might be slow to respond.

由于告警也带上了主机名,那么很明确快速锁定故障的节点了。

  • 服务器上的分析

于是我连忙登上了那台服务器,这时用户开始报故障了,问题变得严重了起来。 不过,作为练习时长4年半的运维工程师,此刻非常的淡定。

先使用top看看哪个进程在搞事情把cpu都抢了吧,超出我意料的java进程以外,是一个很陌生的进程占用几乎100%的cpu。 锁定了它的位置ls -l /usr/games/.../.miner/syst3md

-rwxr-xr-x 1 root root 6960840 8月 22 2020 /usr/games/…/.miner/syst3md

直觉告诉我,这个玩意不是我们的东西(后来觉得最应该使用stat+文件来查看,ls默认是上次修改时间)。

  • 故障分析

询问过开发后开始杀掉它的进程。杀完之后再次查看,又起起来了。

暂时先把它移动到/tmpmv /usr/games/.../.miner/syst3md /tmp 将进程pid再次杀掉,发现不再起来了。

检测进程和资源占用情况都正常了,此时是16:32

确认之前计划任务什么没有,怀疑是这个病毒文件起来时候建立了计划任务,后面的分析过程印证了这个想法。

所以使用last查看这个时间有谁登录过服务器

j        pts/4        192.168.10.100   Wed Jul 14 16:21 - 16:24  (00:02)
j        pts/3        192.168.122.1    Wed Jul 14 16:21 - 16:24  (00:02)
j        pts/3        server1          Wed Jul 14 16:20 - 16:21  (00:00)
j        pts/2        192.168.11.100   Wed Jul 14 16:19 - 16:24  (00:04)
j        pts/1        192.168.11.100   Wed Jul 14 16:15 - 16:21  (00:05)
j        pts/0        192.168.11.100   Wed Jul 14 16:06 - 16:24  (00:17)

好家伙,有一个j的家伙在下午16:06开始到16:24多频次多来源ip登录过服务器。

生产服务器不安全的点

这里说一下故障涉及的生产服务器不安全的几个因素:

  1. 我接手服务器时本想第一时间修改root密码,因为一些原因没有进行修改;
  2. 生产服务器环境连入其实有VPN的,但是我来的时候已经使用了nginx做了端口的反向代理(使得ssh端口暴露在互联网中,当时有提出疑问但是没有进行整改);
  3. mysql通过nginx做了端口的反向代理(使得数据库端口暴露在互联网中);
  4. Jenkins通过nginx做了端口的反向代理(使得Jenkins暴露在互联网中);
  5. 以上的反向代理都没有日志记录,后期排查时,找不到侵入者的公网ip(虽然这种情况找到ip意义也不大);
  6. 生产服务器进程使用root起停,Jenkins也一样,所以只要攻破了Jenkins,就可以拿到服务器得root权限;
  7. 生产服务器情况比较复杂,我没有做用户的筛选管理(有的用户和日志审核系统相关,没有人清楚情况,也不敢乱动);
  8. 出问题的服务器托管在机房,那边的服务团队没有将详细架构交予我这边,远程沟通效率低,终于无果;
  9. 日志审计、防毒墙硬件设备形同虚设。

这些不安全的因素大多为了图方便,还有一些复杂原因没有推动下去进行整改,当然有了这次的教训,这些点都是优先考虑整改的方向。

  • 继续故障分析

16:36:34又收到了zabbix的告警信息

/etc/passwd has been changed

发现了/etc/passwd内被新建了一个server的用户

使用userdel -r server进行删除。

上面说到有不明用户登录了服务器,流程很明确先让它无法登录,修改j用户以及root用户的密码,如果j或root还保持登录应该将其强制登出。

临时排除不安全的因素不会从外部引入,此时,故障还没有得到处理。因为java项目的进程全部都不存在了,手动启动主要的java项目以及Jenkins。

API可用性于16:57恢复正常,可用探测点百分比为100%,持续时间33分钟,其中大部分时间是在排除j用户再次登录的可能性。

  • 关于j用户

前面的syst3md可疑进程是root起的,但是发现使用visudo命令(或查看/etc/sudoers文件),j都不在其中,它是怎么提权的呢?

其实还有其它疑点,第一时间我其实是想删除j用户的。

使用root删除它userdel -r j提示

userdel: user j is currently used by process 1

process 1 是什么我相信运维很清楚,这个j用户还不算简单呐,所以才曲线先修改了它的密码,让它不能再登录到服务器上操作。 再来分析这个用户为什么这么🐂🍺连root用户都删除不了它。使用cat /etc/passwd | grep ^j

j:x:0:0::/root:/bin/bash

它的uid,gid都是0,家目录为/root,翻译成人话就是使用它登录成功就是root用户,我直呼妙啊! 再查看/etc/passwd文件发现它还是一个老朋友了。

还有它登录服务器的地址有四个

  • 192.168.10.100

这个就是本机内网ip地址,本机登录本机?

  • 192.168.122.1

不在认知范围的内网地址,后来经过确认,给我们做网络服务团队也不知道这是什么地址。但是对方提到监管的线,所以使用ifconfig查看到是本机的网卡virbr0地址,又使用本机的ip地址登录本机(正常人都干不出这事),唯一的解释就是木马程序扫描所有的网卡之后扫描网段在线的ip,再使用j账户密码登录(后面的的server1地址以及同网段的其它主机登录日志可佐证)。

  • server1

ping server1返回的IP是10.10.100.3 ,也是不在认知范围的内网地址,发现server1是写在了/etc/hosts内。后来经过确认,给我们做网络服务团队也不知道这是什么地址,同理上面的ip地址,是本机的enp2s0f1网卡获取的地址,还是监管的线路吗?又进行了本机登录本机的操作,确认不是正常人(是正常机器人)的操作了。

  • 192.168.11.100

前面隐患说到的,通过nginx端口转发到本机的地址,不论是直连这台服务器的外网ip还是从这台服务器ssh故障服务器都会显示来源为这个ip。

有害程序的分析

好在我第一时间不是删除了/usr/games/.../.miner/syst3md这个文件,而是移动到了/tmp下,让我空下来可以分析一下这个文件。

我将其从服务器上拉了下来,不出意外的它就是一个二进制文件。 file syst3md

syst3md: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux),statically linked, for GNU/Linux 2.6.18,BuildID[sha1]=abbd7cc45284dffd19b3e61e1f31b03e44addc00, stripped

文件更详细特征值为: 名称: syst3md 大小: 6960840 字节 (6797 KiB) CRC32: F504C8AF CRC64: A479CAC1E9F66F36 SHA256: EFA9CF5AD8EB73556E34F2CBF4FB71DF19E9956A4F0332A714BB6307395F3DCC SHA1: 732186C30BCC72F0A295284FC4593B200AA84779 BLAKE2sp: 5ECB796F79A58D3B8D4E9E333E08F320A153AA61F2D63AE2381C258DE1A30A95

通过搜索,果然发现有人早已中招过了

上面的报告是在windows主机上跑的,但我们无法看到它到底是个啥,从火绒的扫描分析来看它是linux下的一个黑客工具。

只有另辟蹊径从/usr/games/这个文件夹着手了,ls -la /usr/games/,有一个...的文件夹

drwxr-xr-x. 3 root root 36 7月 14 16:21 …

进一步查看 ls -la /usr/games/.../

drwxr-xr-x. 3 root root 123 7月 14 16:36 .miner -rw-r–r–. 1 root root 1985344 7月 14 16:21 x.tar.gz

ls -la /usr/games/.../.miner/

-rwxr-xr-x. 1 root root 922808 8月 21 2020 1 -rwxr-xr-x. 1 root root 923336 8月 21 2020 apachelogs -rwxr-xr-x. 1 root root 4350 5月 18 22:27 config.json -rwxr-xr-x. 1 root root 926112 8月 21 2020 run drwxr-xr-x. 2 root root 56 5月 18 19:41 .settings -rwxr-xr-x. 1 root root 926272 8月 21 2020 setup -rwxr-xr-x. 1 root root 575 9月 9 2020 status -rwxr-xr-x. 1 root root 182 5月 18 20:27 wget-log

这里有一个config.json还有一个wget-log文件上次修改时5月18日,好家伙,这么分析是有计划任务的呀!

查看config.json发现了一些信息。

 "url": "139.99.123.196:443",
 "user": "849vdbnAgbXdyx5QBTWf29QH3DvkCVo3WZjoDKtFU16GMo1TnA73TVcFCk5s1ET1GF9aNqPcsq81ZXYZAswPWBuZKXvAqaq",
 "pass": "Minerii",

看看是个啥网站 curl -k https://139.99.123.196

Mining Pool Online

好家伙是个矿场啊,侵入我们服务器来挖矿的。

切断j再次登录管道

增加了计划任务,代表有死灰复燃的可能性。

/etc/crontab没有可疑内容然后查看单个用户的计划任务ls /var/spool/cron/ -lh

-rw——-. 1 root root 198 7月 14 16:34 root

使用root账户crontab -lcat /var/spool/cron/root可以查看内容。

          • /usr/games/…/.miner/1 > /dev/null <&1 2>&1 & disown @monthly /usr/games/…/.miner/1 > /dev/null <&1 2>&1 & disown @reboot /usr/games/…/.miner/apachelogs > /dev/null <&1 2>&1 & disown

嗯,临死之前还要留下个种子,有一个每分钟都运行和每个月,每次重启运行的计划任务。由于执行的脚本是二进制文件,也看不出什么,做一个文件夹备份拉到本地后先删除它吧,把计划任务也清空掉。

rm -rf /usr/games
> /var/spool/cron/root

到此为止堵上了大部分的漏洞,而后对方还有一个骚操作也被我揪出来,那就是使用密钥登录了。 是此前在这个目录下看到的rsakey

ls -la /usr/games/.../.miner/.settings/

-rw-r–r–. 1 root root 399 7月 14 16:23 .rsakey -rw-r–r–. 1 root root 28 10月 18 2020 .usercreated -rw-r–r–. 1 root root 13 10月 18 2020 .worker

ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAkVgakr9+hG15jNtsAvFgXeTEuAtZ4M1Qtjmhtf68O6KeXbZ8EYt5M0DXEFOibWqMD8GURCchBItlWtlq825vQ7mGtyNHzzRLt5Hyjx2156Mz4B6oPPrw8LPJ273owYkJ8UCwpgYkoNdgeUaHtVcQM8K3GtRrikdtRewisRUlbp+f6zxqTWKIIouNOw0xOaCp5SihZHghPPibNTxSBZtkxGgsNmmcKXf3wvt/mB/3g6DoEHU+q++gajiA+aUCVfLzqKZ838R4S82valRmwoIYPE8eK776zQoJ7fpxOMLRM+ISryRPXgk/vxHRvMtrJNnMLhVo25h8/6dIkhVgUF9qkQ== universal-ssh-key

果不其然 cat /root/.ssh/authorized_keys发现了这个ssh-key。 临死前还要摆这么多道,就算改了j的密码它还可以用密钥登录,妙啊! 直接清空或者删除/root/.ssh/authorized_keys发现还没得权限,root没权限,果然又是那个把戏。 lsattr authorized_keys

—-i———– authorized_keys

chattr -i authorized_keys lsattr authorized_keys

—————- authorized_keys

>/root/.ssh/authorized_keys

然后直接删除这个受信任的文件。

  • 另一台服务器

前面分析到j用户首次的登录是从192.168.11.100这个ip地址登录的,我又尝试从这台服务器进行了分析。 使用last果然发现了问题。

j        pts/5        192.168.10.100   Wed Jul 14 16:19 - 16:20  (00:00)
j        pts/2        server1          Wed Jul 14 16:16 - 16:21  (00:05)

它也从server1也就是10.10.100.3进行了登录动作。

看看那个文件有没有出现。 ls /usr/games/ -la

drwxr-x— 2 root root 6 7月 14 16:16 …

文件夹有了也是昨天创建的,查看文件里面内容ls /usr/games/... -la发现为空。 这台服务器没有发生的原因,唯一解释就是这台服务器访问不到外网,救了它一命。

至此完全杜绝了j用户的登录,当然为了安全也可以删除j用户了,我打算还是先留着作为证据了。

  • j用户的逆天权限

前面说过j用户的uid和gid均为0,家目录为/root,这样登录j用户就等于直接登录了root,连sudo都不用输入直接提权。 那么这种权限是怎么实现的,其实非常的简单。 使用root权限执行useradd -o -u 0 -g 0 -d /root -s /bin/bash k 可以创建一个k的拥有root权限的用户。 拿掉他的权限可以使用vipw修改gid和uid即可。

  • 反向代理添加访问日志

这一块是可以优化的地方,端口转发这一块,之前是通过 stream { upstream xxx{ … } server { … } } 来实现的,没有添加日志,在stream内添加 log_format stream ‘$remote_addr [$time_local] $status $upstream_addr’; access_log /xxxx/xxxx/xxxx.log stream ; 可以记录到来源ip 时间 状态 反向代理服务信息。

故障总结

  • 密码泄露

定义此次攻击为密码泄露,肉鸡⛏挖矿,从/var/log/secure分析,来自192.168.11.100的未知用户登录失败次数达到了31096次(7月11日到16日)

使用root登录失败的次数也达5919次 外面在不断的尝试爆破服务器,但是判定用户j不是爆破的而是密码泄露的理由是它的登录轨迹 期间登录服务器只有两次失败的记录 Jul 13 23:19:22Jul 14 17:04:22,在故障前一天晚上晚上(也就是bilibili出问题的时间点?),它尝试登录了服务器但是失败了,后面是故障当天,解决了故障后再次登录失败。 而故障前一天它也是在Jul 13 15:09:25第一次登录,但是在绝对可信的last没有留下记录。 紧接着就是故障当天的登录,以及后续的我改完密码自己的尝试登录记录了。 因此判定j用户遭到了密码泄露的挖矿攻击。

  • j用户由来

供应商解释是当时用来做等保的账户

  • 攻击过程

使用泄露的j用户以及密码进行服务器登录,并连接外网下载挖矿程序并运行。 添加计划任务保持在线状态,添加密钥便于下次再次登录。 扫描服务器网卡,获取各个网段的主机,并进行登录,重复上面的步骤。 (由于备用的web服务器没有外网访问权限,只创建了/usr/games/...文件夹,幸免遇难) 病毒样本分析: https://www.joesandbox.com/analysis/438274/0/html https://hybrid-analysis.com/sample/efa9cf5ad8eb73556e34f2cbf4fb71df19e9956a4f0332a714bb6307395f3dcc/60d17df7e81ec670746de450 https://maldun.com/analysis/YXNkZmRzZmFkc2Y2MTY0NTRkc2Zhc2RmYXNkZg==/

  • 安全性改进

参见上方的 生产服务器不安全的点 ,逐一分析改进。

还有就是供应商给我们部署的防毒墙也没有任何反馈,让我看日志审计系统但是系统直接登录就是提示数据库异常,请联系管理员。 关键时刻硬件形同虚设。

问题分析到这里,真相已经逐渐明朗了。好在对方的手段显得比较拙劣,留下了这么多痕迹,不然我怎么死的都不知道。

最后要强调的是:

图方便和保安全是互斥的,这次故障很多地方都有图方便而忽略安全性的地方。

作为运维人员,如果你有绝对的保安全性的权利,绝对不要去图方便,最终受害的是自身,也会给业务造成无可挽回的损失。

Licensed under CC BY-NC-SA 4.0
最后更新于 Aug 10, 2021 10:14 UTC