问题标签: #DevOps #Docker #信息安全 #挖矿排查

问题描述: Linux 服务器 CPU 占用率长期维持在 100% 以上,存在无法彻底杀死的异常进程。


一、 异常现象 (Symptoms)

  1. CPU 报警: top 命令显示 CPU 使用率极高(如 700%+)。
  2. 顽固进程: 发现名为 javaekdevtmpfsi 或随机字符串的异常进程占用极高资源。
  3. 用户迷惑: 进程所有者可能显示为 mysqlwww 等常见服务用户,容易误导排查方向。
  4. 无限复活: 使用 kill -9 强杀进程后,进程立刻以新的 PID 重启,无法根除。
  5. 无定时任务: 检查宿主机对应用户的 crontab,通常为空。

二、 核心排查思路 (The Investigation)

面对“杀不死”的进程,核心思路是:不要盯着子进程打,要去找它的“守护进程”(父进程)。

1. 揪出父进程 (PPID)

首先找到病毒进程的 PID,然后查看其状态文件中的 PPid 字段。

# 假设病毒进程 PID 为 12345
cat /proc/12345/status | grep PPid

2. 分析父进程身份

拿到 PPID 后,查看父进程的具体启动命令。

# 假设 PPID 为 67890
ps -fp 67890

关键判断点:

  • 如果父进程命令包含 containerd-shimdocker-containerd/bin/sh ./entrypoint.sh 等字样。
  • 结论: 病毒并非运行在宿主机上,而是寄生在某个 Docker 容器内部
  • 现象解释: 之所以“杀不死”,是因为容器内的 1 号进程(或守护进程)监控到木马退出后,Docker 守护进程根据 Restart Policy 自动重启了容器。

3. 锁定带毒容器

执行以下命令,配合 top 中观察到的伴生进程或容器启动时间来锁定目标。

docker ps --format "table {{.ID}}\t{{.Image}}\t{{.Command}}\t{{.Status}}"
  • 特征 A: 容器启动命令 (COMMAND) 与上面查到的父进程命令一致。
  • 特征 B: 容器运行时间 (STATUS) 很短(因为刚才杀毒导致容器重启过),而其他正常容器运行时间较长。

三、 通用解决方案 (Solution)

1. 彻底清除 (Stop & Remove)

不要在宿主机尝试杀进程,必须直接处理容器。

# 1. 停止容器(CPU 将瞬间恢复正常)
docker stop <Container-ID>

# 2. 删除容器实例
docker rm <Container-ID>

# 3. 删除带毒镜像(必须执行,防止误操作重新启动)
docker rmi <Image-Name>:<Tag>

2. 根源修复 (Update & Patch)

容器被植入木马通常是因为:

  1. 应用漏洞: 使用了含有远程执行漏洞(RCE)的旧版本镜像(如旧版 Next.js, Redis, WebLogic 等)。
  2. 弱口令: 暴露在公网的服务使用了默认密码。

修复动作:

  • 备份数据: 备份 docker-compose.yaml 及持久化数据卷(Volumes)。
  • 升级版本: 修改配置文件,将镜像 Tag 升级到官方最新的安全版本。
  • 更新配置: 重新拉取镜像并启动。
# 拉取新版镜像
docker compose pull

# 重建并启动容器
docker compose up -d

四、 避坑指南 (Lessons Learned)

  1. 透过现象看本质: top 命令看到的 USER 列在 Docker 环境下具有欺骗性。容器内的 UID 往往直接映射到宿主机,显示为 mysql 并不代表宿主机的 MySQL 服务被黑。
  2. 关注 PPID: 排查挖矿木马时,父进程 ID (PPID) 是破局的关键。
  3. 最小权限原则: 尽量不要将 Docker 端口(如 2375)暴露在公网,Web 服务应及时更新补丁。