应急响应实录:某金融公司Docker集群遭挖矿攻击,3小时溯源全过程

摘要: 一场突如其来的告警,往往是安全应急响应的开始。

下午两点,我们金融业务核心集群的一台 Docker 主机 CPU 使用率突然飙升至 99%。运维团队第一时间介入,初步判断为业务流量高峰,但数分钟后,告警仍未消除,这引起了我们的警觉。作为公司的安全团队,我们立刻接手,一场与时间赛跑的溯源排查就此展开。

应急响应实录:某金融公司Docker集群遭挖矿攻击,3小时溯源全过程

初步研判:告警背后的异常进程

T+5分钟

我们远程登录到告警主机,执行 top 命令,一个名为 kdevtmpfsi 的进程几乎吃满了所有 CPU 核心。

这个进程名很陌生,既不是已知的业务进程,也不属于系统常规服务。凭借经验,我们立刻意识到这极有可能是挖矿程序的典型伪装。

此时,最直接的做法是立即杀死进程,但我们没有这么做。在不清楚攻击者是否留有其他后门或权限维持手段的情况下,贸然“打草惊蛇”可能会导致溯源线索中断,甚至触发攻击者的反制措施。

我们的首要任务是:在不干扰恶意程序运行的前提下,快速定位其来源和影响范围。

深入溯源:抽丝剥茧定位入侵路径

整个溯源过程,我们需要回答三个核心问题:

  1. 这个进程从哪里来?(入侵点)
  2. 它做了什么?(攻击行为)
  3. 它是否扩散到了其他地方?(影响范围)

第一步:确认恶意进程与网络行为

T+15分钟

我们首先需要确认 kdevtmpfsi 的“身份”。

通过 lsof -p [PID] 命令,我们发现该进程与一个境外的 IP 地址建立了持续的 TCP 连接。在威胁情报平台查询该 IP,确认其为某知名挖矿团伙控制的矿池地址。

至此,挖矿行为基本可以定性。

接着,我们使用 ps -ef 查看进程的父子关系,发现它是由一个 shell 脚本启动的。这表明攻击者很可能通过某种方式在服务器上执行了一段恶意脚本。

第二步:从容器到镜像的逆向追踪

T+45分钟

我们的业务都运行在 Docker 容器中,因此下一个关键问题是:恶意进程究竟是在主机上,还是在某个容器里?

我们使用 docker ps 列出所有运行中的容器,再逐一通过 docker top [container_id] 查看容器内的进程。很快,我们在一个运行着核心交易应用的容器中找到了 kdevtmpfsi 的身影。

问题范围被迅速缩小。攻击者并非直接攻陷了宿主机,而是通过这个容器作为跳板。

我们立刻检查该容器所使用的镜像。docker inspect [container_id] 的结果显示,该镜像基于一个公网 Docker Hub 上的第三方基础镜像构建,且最近一次的构建时间就在几天前。这为我们提供了两个可能的怀疑方向:应用本身存在漏洞,或是基础镜像源头就“带毒”。

第三步:分析日志,锁定最初的失陷点

T+1 小时 30 分钟

日志是还原攻击现场最可靠的证据。我们兵分两路,同时排查应用日志和 Docker 守护进程日志。

在容器的应用日志中,我们发现了蛛丝马迹。大约在告警发生前的三小时,日志记录了数条针对某个 API 接口的异常请求。这些请求中包含了一段经过编码的攻击载荷,解码后,我们确认这是一次针对某开源组件远程代码执行(RCE)漏洞的成功利用。

攻击者正是通过这个 RCE 漏洞,获得了在容器内执行任意命令的权限,进而下载并运行了挖矿脚本。入侵点至此水落石出。

第四步:排查横向移动与权限维持痕迹

T+2 小时

找到入口不代表结束。更重要的是确认攻击者是否已经“站稳脚跟”,甚至实现了“容器逃逸”,将战火烧到宿主机或其他容器。

我们重点排查了以下几个方面:

  • 容器逃逸:在宿主机上全面搜索挖矿程序的文件名,未发现踪迹。同时检查了 dmesg 和系统日志,没有发现内核漏洞利用或容器逃逸的典型痕迹。
  • 权限维持:检查了容器内部和宿主机的定时任务(crontab),发现在受害容器内,攻击者添加了一个定时任务,每分钟检查一次挖矿进程是否存在,如果不存在就重新启动。这是非常典型的权限维持手段。
  • 横向移动:我们排查了该主机上其他所有容器的进程和网络连接,并检查了堡垒机的登录日志,均未发现异常。攻击似乎被局限在了这一个容器内。

阶段性结论:攻击链已基本清晰

经过近两小时的紧张排查,我们已经可以完整地勾勒出此次攻击的全貌:

  • 入侵点:攻击者利用金融应用中一个未及时修复的 RCE 漏洞,获得了容器的控制权。
  • 攻击载荷:在容器内部下载并执行了挖矿脚本。
  • 权限维持:通过在容器内写入定时任务,确保挖矿程序持续运行。
  • 影响范围:攻击被成功限制在单个容器内,未发生横向移动或容器逃逸,也未发现数据泄露的迹象。

清理与处置:快速遏制与恢复业务

T+2 小时 30 分钟

在掌握了足够的信息后,我们开始执行清理和恢复操作。整个过程遵循“隔离、取证、清除、恢复”的原则。

  1. 隔离:首先,我们通过配置宿主机防火墙规则,切断了受害容器与外部矿池地址的通信,使其无法继续“工作”。
  2. 取证:我们使用 docker commit 命令,将当前受害容器的状态固化为一个新镜像。这个镜像将作为后续深入分析和追责的数字证据。
  3. 清除:停止并彻底删除了被污染的容器实例。同时,清除了其在容器内设置的定时任务。
  4. 恢复:开发团队紧急提供了修复了 RCE 漏洞的新版应用镜像。我们使用这个来自可信内部仓库的干净镜像,重新部署了服务。
  5. 验证:服务上线后,我们持续监控新容器的 CPU、内存和网络连接,确认无任何异常行为后,才将事件的响应级别降级。

至此,应急响应的主要工作在三小时内宣告完成,业务恢复正常。

复盘与加固:从事件中学习,构建纵深防御

一次成功的应急响应不仅在于扑灭“火情”,更在于找到起火原因,并加固防火墙。事件结束后,我们立即组织了复盘,并推动了以下几项安全加固措施的落地。

漏洞管理与镜像安全

此次事件的根源在于一个已知的 RCE 漏洞。我们以此为契机,推动了更严格的漏洞管理流程,要求所有上线镜像必须经过自动化漏洞扫描(SAST/DAST),禁止存在高危漏洞的镜像部署到生产环境。同时,规范了基础镜像的使用,统一收敛到经过安全基线加固的官方或内部镜像源。

运行时安全监控

告警是发现问题的最后一道防线,但我们不能总依赖它。部署容器运行时安全工具,可以更早地发现异常。例如,一个正常的业务容器不应该执行 curl 或 wget 等命令去下载未知脚本,也不应该启动 shell 进程。这些行为都可以在运行时被实时检测和阻断。

最小权限原则

虽然此次攻击未造成容器逃逸,但风险依然存在。我们重新审视了容器的安全配置,强制要求所有容器以非 root 用户运行,并配置了更严格的 Seccomp 和 AppArmor 安全策略,限制容器内进程可以使用的系统调用,最大限度地收缩攻击面。

这次应急响应是一次实战考验。它再次证明,在容器化时代,安全防护必须贯穿应用的整个生命周期,从编码、构建到部署、运行,任何一个环节的疏忽都可能成为防线上的缺口。建立快速的检测、响应和恢复能力,是保障业务连续性的核心。