起因

一直挺得意那台轻量服务器——2 核 4G,跑着博客、图床、一个文件管理,两年没出过事。

10 月 26 号晚上翻图床的时候发现不对劲:桶里多了几个从来没上传过的文件,名字是 shell.php、.htaccess,还有一个叫 ahk_probe 的东西。第一反应是自己手滑,第二反应是——我根本没开过 PHP。

往下挖

先看的不是网站,是进程。

ps auxf | grep -v '\[' 

排在最上面的几个进程看着很正常,名字是系统自带的那种。但路径不对:

/dev/shm/.collector/collector.d

/dev/shm 是内存盘,重启就清空,正常服务不会往这儿放东西。collector.d 这个名字起得很「正经」,伪装成日志收集器——这种命名习惯不是随手写的,是有人专门研究过怎么不被人一眼看出来。

再看 /root/.ssh/,authorized_keys 里多了一把不属于我的公钥。也就是说:对方不需要密码也能随时回来。

溯源:入口在哪

翻 nginx 和 MinIO 的日志,链条很清楚:

  1. 图床的 9000 端口直接对着公网开着
  2. MinIO 用的是默认凭据 minioadmin / minioadmin(建的时候图省事,一直没改)
  3. 对方扫到 9000,用默认口令直接进来了
  4. 通过 MinIO 的写入权限往桶里丢 web shell 和探测脚本
  5. 拿到执行权限后提权、装后门、留公钥

整个过程没有任何「高难度操作」。用的是出厂默认密码和不必要对外开放的端口。

顺带在 auth.log 里翻了 SSH 爆破记录,三个来源,都是同一批端口、同一套字典:

来源地址 归属 行为
51.222.47.156 境外(OVH 地址段) 单 IP 尝试登录 4466 次
106.53.117.97 中国·广东·广州(腾讯云) 扫描同一批端口
182.134.27.185 中国·四川·宜宾(电信) 扫描同一批端口

没什么好洗的,就是三个贱人:

  • 51.222.47.156(境外 OVH 段)—— 一个 IP 硬试了 4466 次
  • 106.53.117.97(广东广州,腾讯云)
  • 182.134.27.185(四川宜宾,电信)

租台云主机来扫端口是贱人,拿别人的机器当跳板更是贱人。这三个地址我记在这儿了,哪天想起来了就翻出来看一眼。

骂完还得防。真正让它们无从下手的是「密码登录关掉」和「端口不对外」。

止损

发现后没做「清理」这种操作,直接按事故处理:

  1. 先关机,切断对方的操作通道——清理是在跟对手赛跑,没必要
  2. 关机后打快照,把现场固定下来(这台机器上的一切都可能是证据)
  3. 重启挂个临时环境,只对自己的 IP 开放,把数据捞出来
  4. 数据核对无误后,整机重装

这里有个判断很关键:不要试图「删掉后门」然后继续用。一个拿到过 root 的人,可以在任何地方留东西——内核模块、cron、systemd、甚至固件。你不可能穷举。

唯一可靠的处置是重装。

数据是怎么保住的

图床数据在对象存储的桶里,站点是纯静态文件,都落在数据盘上。把这两个目录打包:

tar czf backup.tar.gz /数据目录/minio/data /var/www

打完校验 SHA256,传到本地再核一遍。中间出过一次传输损坏,第二次才拿到一致的哈希——这一步千万不能省,一个坏包等于没备份。

教训

三条,按严重程度排:

问题 后果
默认密码(minioadmin/minioadmin) 等于没设密码,扫描器字典第一条就是它
端口对公网敞开(12 个端口) 每个端口都是一个入口,图床根本不需要公网直连
root 密码复用且偏弱 一旦进来,横向到系统层毫无阻力

还有一个隐性的:我从来没看过那台机器的日志。4466 次爆破,失败了 4466 次,没有一次触发告警,因为压根没装 fail2ban。

最后

这次没人身损失,数据也都回来了。但那种「自己的机器上跑着别人的进程」的感觉,比丢数据更让人不舒服。

后面几篇会写重装之后做了什么——SSH 换密钥、端口砍到 3 个、fail2ban、图床收回内网、评论系统搬回自己机器。都是很基础的东西,基础到出事之前我一直觉得「没必要」。