事情是这样的,昨天晚上我收到了腾讯云的异地登录告警,一开始我并不是太在意。腾讯云经常会有一些误报告警,不怪腾讯云,有时候我带着笔记本回老家,笔记本竟然没睡死,在合上的状态连上了我的服务器(目测是 VSCode 远程开发),而老家的电信宽带竟然有时候 ip 是其他城市的,就会引起异地登录报警。
然而这次的告警收到的时候我正在深圳家里电脑前,没有移动设备,而且 IP 也十分诡异,查询为拉脱维亚的 IP。以为是密码泄露,登上去草草改了密码就睡觉了。
第二天起来看 log,发现第一次登录只有一个 disconnect 的 log,我就在想这个异常 IP 到底是不是真的有成功登录我的机器呢,找了腾讯云安全的大佬们协助排查。后来发现第二次的登录有完整的 log,可以明显的看到 Accept 了来自公钥的登录。使用的公钥来自我另一个机器上(后称为 B 机器)的用户密钥对。
告警的机器我们把他叫做 A,A 机器是最近新购的,腾讯云最近 SA2有优惠啊,于是买了一台,准备把老机器 B 停止续费,迁移数据和服务换到价格更便宜配置更高的 A 机器。迁移过程完全是手工操作,没有粗暴的对拷数据,认真的整理了哪些服务已经不需要了,也重新规划了目录结构和权限。为了方便迁移数据(我使用 scp 拷贝),我把 B 机器的公钥添加到了 A 机器的authorized_keys 中,因此 B 机器是可以直接免密 ssh 到 A 机器的。
安全的同学相当的给力,很快的从情报上发现了入侵 IP 相关的一个文章,这个病毒叫 Ebury,感染后会替换掉ssh 依赖的 libkeyutils.so,使得 ssh 会加载一个病毒载体 libxxx.so(文件名不定,我这里见过 libtsr.so/libpw5.so/libhdx.so 等),他会记录你 ssh 到别的机器的时候用到的密码或密钥,通过 DNS 请求把数据发回去黑客的服务器。相关的日志信息可能会被抹除而无法查询,文件的修改时间也会被改到一个以前的时间来迷惑你(stat 看 change 时间可以发现问题),还把 rpm 相关签名信息改掉,你通过 rpm 检查包签名也是查不出来的。我遇到的变种基本可以通过 objdump 查看 libkeyutils.so 有奇怪的 libxxx.so 依赖来判断受感染,这个 libxxx.so 上传到 virustotal 站点是可以识别出来 ebury 病毒的。
除了腾讯云国内的机器,国外我还有其他供应商的机器,这些机器很多时候(主要是晚上)SSH 卡顿困难,所以我时常会有借国内机器 SSH 管理国外机器,果不其然,国外的几个机器查了下全都被感染了!!!病毒样本最早的时间在2017年,所以其实在我的机器上已经潜伏了很久,随着机器之间互相 ssh 登录互相传染病毒。
国外廉价 VPS 大多属于 Unmanaged VPS,基本是没有什么技术支持,更别说像腾讯云这种入侵检测告警之类的,所以问题其实早已存在,只是没什么症状,没什么明显影响,没有被发现而已。
在善后问题的处理上面,我发现 clamav 有奇效,可以扫描出受感染的文件来。由于重装比较麻烦,尤其是感染到我一台用于存储数据备份的机器(没错,国外的,还不像云服务简单的做定时快照之类的就能实现备份目的),所以我决定暂时清除相关感染文件(重新安装正规来源的 keyutils-libs,删除 libxxx.so),撤换受感染机器的 ssh keys,撤换互相登录过的机器 root 密码,禁止 root 密码登录,后续也不准备允许长期的跨机器互登公钥信任。
======
Update:某些比较老的机器上 clamav会超内存无法扫描,还有的机器clamav通过包管理安装,病毒库更新到最新,但扫样本so的时候竟然报没被感染,因此并不是很靠谱。
我的处理方法:
- objdump -x /lib64/libkeyutils.so.XXX | grep NEEDED 确认入侵痕迹,会依赖一个不知名libxxx.so
- yum reinstall keyutils-libs 重新安装正常版本的libkeyutils.so,再次使用1中命令确认已经不再依赖不知名libxxx.so
- reboot重启机器,让内存里面已经加载的不知名libxxx.so自然消散
- 重启后 lsof | grep /lib64/libxxx.so 确认内存中已经没有该文件,再次使用1中命令确认已经不再依赖不知名libxxx.so
- 删除libxxx.so
- 重新生成机器的公私钥 ssh-keygen