如果一台 Docker 主机把未经过身份验证的 API 暴露在互联网上,它提供的就不只是远程管理便利,而是一条通往运行这些容器的机器的路径。9 月 30 日公布的 CARBONATO 活动让这一点变得难以忽视:攻击者利用暴露的 Docker Remote API 创建特权容器、建立持久化、窃取凭据,并寻找更多 Docker 主机。

展示暴露 Docker 主机的编辑插图,表现从互联网通往服务器和容器控制平面的访问路径。

这起事件值得关注,并不是因为它本质上讲述了一个新的 Docker 漏洞,而是因为一个管理接口被放置在不受信任的网络上,却没有身份验证边界。恶意软件加入了现代化载荷,包括被重新利用的开源 AI 代理框架;但真正促成攻击的条件更早、更简单:任何能够连接到守护进程的人,都可以要求它以主机权限执行操作。

对于在云服务器、构建机器、开发主机、自托管服务或边缘系统上运行 Docker 的团队,正确的响应是进行暴露面与失陷评估。关闭未认证路径,判断主机是否被使用过,轮换它可能读取的所有凭据,然后检查相邻系统。如果底层主机或其凭据可能已经落入他人控制,仅仅重装一个容器或修改镜像标签并不够。

CARBONATO 报告实际说明了什么

新加坡网络安全局(Cyber Security Agency of Singapore)于 9 月 30 日发布的公告称,研究人员发现了一场针对 Docker 主机的僵尸网络活动。这些主机的未认证 Remote API 暴露在互联网上,通常使用 TCP 端口 2375。公告描述称,该活动利用 Docker 的合法功能创建特权容器,使其能够访问主机文件系统、进程和网络。

这一过程很关键。如果守护进程接受来自不受信任方的管理请求,攻击者就不需要利用 Docker Engine 中的内存安全漏洞。对于管理员来说,创建容器、挂载路径、启动进程或连接网络都是正常请求;但当请求者未经认证、守护进程又以高权限运行时,这些操作就可能变成对主机的控制。

新加坡公告称,这场活动可以建立持久化远程访问,窃取凭据和其他敏感信息,并扫描相连网络以寻找更多暴露的 Docker 主机。它并没有声称每一台暴露主机都已被攻陷,也没有提供一个单独就能证明或排除事件的通用指标。这些限制很重要:公告是调查暴露面和日志的理由,而不是给每个 Docker 安装贴上“已感染”标签的依据。

另一份云安全联盟研究说明补充了载荷背景。该说明将 CARBONATO 描述为一种会自我传播的僵尸网络:它安装未经修改的开源 AI 代理框架 Hermes Agent,并修改其 persona 配置,使框架服务于运营者的目标。研究说明称,受感染主机会扫描相邻网络范围,寻找更多 Docker 守护进程。

不寻常之处在于它选择的载荷。对防守方而言,真正重要的仍然是访问路径。AI 框架的存在可能吸引注意,但攻击者并不需要 AI 代理,就能把暴露的 Docker 守护进程变成严重事件。同样的管理暴露也可以用于窃取凭据、挖矿、破坏性操作、代理转发、横向移动,或部署传统后门。

为什么必须准确看待 2375 端口

Docker 官方文档区分了通常的本地套接字与远程网络连接。在 Linux 和 macOS 上,Docker 默认使用不经网络传输的 Unix 套接字。远程管理则可以通过 SSH,或者通过启用 TLS 与客户端身份验证保护的 TCP 套接字实现。

Docker 文档还说明了常见端口划分:TCP 2375 通常用于不安全、未启用 TLS 的连接,TCP 2376 通常与 TLS 相关。端口号本身不能证明发生了失陷,换用其他端口也不会让未认证 API 变得安全。2375 只是一个有用的发现信号,因为它经常表示某个 Docker 守护进程被配置为提供明文远程访问。

关键问题不是孤立地问“2375 端口是否开放”,而是:

  • 哪个进程正在监听?
  • 监听器是能从公网访问,能从广泛的企业网络访问,还是只能从受限的管理网段访问?
  • 它是否要求身份验证,并且能否正确授权客户端?
  • 后面对应的是哪个 Docker 守护进程、账户、主机和工作负载?
  • 是否存在主机所有者没有发起的请求记录?

一个面向互联网的服务即使并非对全球所有地址开放,也可能很危险。暴露给扁平内部网络的守护进程,仍可能被被攻陷的工作站、承包商设备、开发账户,或本不应拥有主机管理权限的其他工作负载访问。“它只在 VPC 内开放”描述的是网络范围,不是授权模型。

根本问题:Docker 访问权就是主机访问权

容器提供了有用的隔离边界,但访问 Docker 守护进程是一种管理权限。Docker 警告称,把守护进程绑定到 TCP 套接字,或者通过 docker 组授予 Unix 套接字访问权,都可能让用户获得主机级 root 权限。在排查构建系统问题,或试图让远程开发更方便时,这一警告很容易被忽略。

使用提升权限创建的容器可能能够查看或修改主机资源。即使不复现攻击步骤,防守上的结论也很直接:应像保护 root 凭据一样保护 Docker 守护进程凭据和套接字访问权。它们属于与云管理员密钥、虚拟机管理接口、Kubernetes 控制平面访问权相同的风险类别。

这也是为什么单独删除可疑容器是一种薄弱的遏制措施。如果攻击者曾获得守护进程级访问权,他们可能已经读取环境变量,挂载主机目录,检查其他容器,复制配置文件,修改启动机制,创建额外账户,或从主机收集凭据。眼前这个容器可能只是更大范围失陷中的一个痕迹。

同一原则适用于 CI 运行器。一个能够访问特权 Docker 套接字的构建运行器,可能暴露源代码、签名材料、软件包凭据、云令牌和部署权限。挂载了 Docker 套接字的开发者笔记本,也可能暴露本地文件和主机环境。因此,为方便而引入的远程 API,可能把容器工作流连接到周围的身份系统和基础设施。

管理员首先应该做什么

第一步响应应当在不破坏证据的前提下减少攻击者可达范围。

1. 找出所有存在网络暴露的 Docker 守护进程

先建立权威资产清单,不要依赖记忆。检查云安全组、主机防火墙、负载均衡器、VPN 路由、服务发现记录、容器主机配置、systemd 单元文件、守护进程配置文件、编排模板以及基础设施即代码仓库。

查找 TCP 2375 和 2376 上的 Docker 守护进程监听,也要查找自定义端口,以及监听所有网络接口等绑定方式。生产和非生产环境都要检查。开发主机往往暴露更多、监控更少,而且可能连接到包含高价值凭据的网络。

CISA 的互联网暴露面缩减指南建议建立面向互联网资产的可见性,并减少不必要的暴露。相同方法也适用于内部暴露:弄清哪些服务可达、从哪里可达,以及存在这种可达性的业务理由。资产如果不在清单中,就无法可靠地打补丁、监控或调查。

如果未认证守护进程已经暴露,立即在网络层限制访问,同时保留日志和变更记录。紧急目标是阻止新的未认证连接。不要认为防火墙变更证明主机已经干净;它只是改变了谁能够触达主机。

2. 移除明文远程访问

Docker 关于保护守护进程套接字的官方指南建议使用 SSH 或 TLS 保护远程访问。对于运维工作流,SSH 往往很实用,因为它可以把请求转发到远程 Unix 套接字,同时沿用主机现有的身份验证和授权模型。

如果确实需要 TCP 访问,应使用双向认证 TLS,配备受控的证书颁发机构,保护私钥,限制来源网络,并记录管理活动。使用 TLS 加密但不进行身份验证的服务,仍然存在授权问题。加密可以防止流量被观察和篡改,却不能决定某个客户端是否应该被允许创建特权容器。

优先使用私有管理路径,而不是公开监听器。对能够管理守护进程的身份实施最小权限,将人工管理与自动化分开,并避免把可广泛复用的客户端证书分发给构建任务或多个团队。授予无限制 Docker 访问权的客户端证书,应当视为主机 root 凭据。

不要只改端口号来解决暴露问题。安全组、主机防火墙、路由、身份验证和授权,都必须共同构成预期的管理边界。

3. 保留并检查证据

对于可能暴露的主机,在轮换凭据或重建主机之前,保留相关的系统、防火墙、云平台、Docker、编排和身份日志。确定守护进程可达的时间窗口,再与活动报告及自身遥测数据进行比对。

可以提出以下检查问题:

  • 是否有针对 Docker API 端点的异常请求?
  • 是否在正常部署窗口之外创建、启动、停止或删除了容器?
  • 是否出现新的镜像、仓库、网络、卷或机密?
  • 是否有容器异常挂载了主机路径?
  • 是否有容器以提升权限运行,使用主机网络,或访问敏感目录?
  • 主机上是否创建了新进程、用户、计划任务、服务、SSH 密钥或启动项?
  • 主机是否建立了异常出站连接,尤其是连接命令与控制基础设施或陌生镜像仓库?
  • 同一网络中的其他主机是否很快出现 Docker 相关连接尝试?

目标不是寻找某一个神奇文件名。攻击者可以删除容器、重命名进程、使用合法工具,或部署完全不同的载荷。应把 API 活动与进程执行、网络流量、仓库访问、云审计事件和身份提供商日志关联起来。

如果主机包含敏感工作负载,或者日志不足以确定发生了什么,应将其隔离并遵循组织的事件响应流程。当主机完整性存疑时,应使用可信镜像重建。只有在同时审查凭据、配置和部署制品,而不是把它们从可能已被攻陷的系统中整体复制过来时,重建才更有可信度。

4. 按照权限范围轮换暴露的机密

应假设 Docker 守护进程、主机、挂载卷、环境变量、镜像层或运行中进程能够读取的机密都可能已经暴露。应根据凭据能够执行的操作确定优先级,而不是根据它们存放的位置排序。

这可能包括云访问密钥、CI 令牌、代码托管令牌、镜像仓库凭据、数据库密码、SSH 密钥、签名密钥、Webhook 机密、服务账户令牌,以及部署文件中嵌入的凭据。应从可信的管理路径撤销或轮换这些凭据,并检查新凭据签发后是否出现异常使用。

如果旧凭据仍然有效,只轮换而不撤销是不完整的。如果不检查日志,就会错过攻击者已经使用该机密访问其他服务的可能性。如果不梳理依赖关系,轮换可能导致生产中断,因此需要协调;但在存在可信暴露的情况下,运维不便不是继续保持高价值凭据有效的理由。

还要检查那些并未直接存储在主机上、却可以通过主机身份访问的机密。被攻陷的云实例角色、工作负载身份或 CI 服务账户,可能让事件范围远超一台 Docker 服务器。

安全架构应当是什么样

一个可防御的 Docker 部署通常拥有狭窄的管理路径,并且每个例外都有明确理由。

进行本地管理时,应保留受主机访问控制保护的默认 Unix 套接字,并限制 docker 组成员资格。组成员资格不是无害的便利设置;它可能赋予用户对守护进程乃至主机的广泛控制。

进行远程管理时,使用 SSH 或双向认证 TLS,限制来源地址,并在适当情况下将服务放置在管理网络或 VPN 后面。把日志保存在主机之外,避免攻击者抹掉唯一副本。监控证书签发、密钥使用以及守护进程配置变化。

对于 CI,不要把特权主机套接字交给不受信任的构建任务。可以考虑 rootless 模式、隔离运行器、短生命周期工作节点、分离的构建与部署身份,以及范围受限的 API。如果构建确实需要特权操作,就应把运行器视为高风险管理系统,并相应隔离。

在云环境中,应把 Docker 监听器纳入攻击面管理和配置漂移检测。安全模板可能被后续启动脚本、预置在镜像中的守护进程配置、排障命令,或最终永久保留的临时防火墙例外所破坏。

对于开发者,应记录获批准的远程工作流。团队经常因为安全路径不清晰或不方便,才创建不安全的监听器。受支持的 SSH context、托管开发环境或设计良好的构建服务,可以减少直接暴露守护进程的压力。

如何区分暴露与已确认失陷

公开监听或面向广泛内部网络的 Docker 服务是严重发现,但它并不自动证明攻击者曾经使用过。应在事件记录中保持以下三种状态的区分:

  1. 已确认暴露: 守护进程接受过,或本来可以接受来自不受信任网络的连接。
  2. 发现可疑活动: 日志或主机遥测显示存在无法由授权工作解释的请求、进程、网络活动或配置变化。
  3. 已确认失陷: 调查人员拥有足够证据,证明未授权方取得了控制权或访问了数据。

这种区分能改善决策。确认暴露后,应立即关闭暴露并开展基于风险的审查。发现可疑活动后,应启动遏制和事件响应。确认失陷后,则应全面确定范围、撤销凭据、恢复系统、评估通知义务,并总结经验。

它也能避免两种常见错误。第一种是自满:“我们没有看到恶意容器,所以这次暴露没有危害。”第二种是夸大:“2375 端口开放,所以整个环境肯定已经被攻破。”良好的安全报告可以保持紧迫性,同时不假装掌握证据并未支持的结论。

AI 角度居于次要位置,但仍有参考价值

CARBONATO 使用 AI 代理框架,说明攻击者可能如何打包自动化能力,但这不是把所有 AI 组件都视为天然恶意的理由。云安全联盟所描述的框架是开源软件,本身可以有合法用途。它被重新用于僵尸网络,体现的是一个熟悉的安全模式:当对手控制周围的执行环境和配置时,合法软件也会成为攻击的一部分。

因此,防守方应把已安装的软件、配置文件、计划活动、出站目的地以及被访问的凭据纳入调查。只搜索某个产品名称,可能会漏掉经过修改的部署,或完全不同的载荷。反过来,只因为出现某个合法框架名称就进行阻断,而不修复 Docker 暴露,也会让原来的访问路径继续存在。

更大的教训在于自动化边界。运行在被攻陷主机上的 AI 框架可能让任务执行更加灵活,但它并没有创造最初的权限。最初的权限来自 Docker 守护进程。强身份验证、网络分段、主机完整性、凭据卫生和有用的日志,仍然是最关键的控制措施。

下一次审查可直接使用的清单

团队可以把这起事件转化为一项可重复的控制审查:

  • 清点所有 Docker 守护进程,以及能够访问它们的网络。
  • 确认没有未认证 Docker API 暴露在互联网或不受信任的内部网络中。
  • 搜索 TCP 2375 和自定义守护进程监听,而不只是搜索预期的服务名称。
  • 用 SSH 或正确配置的双向认证 TLS,替代临时的 TCP 管理方式。
  • 限制 Docker 套接字访问,并审查 docker 组成员资格。
  • 将 CI 运行器与敏感生产网络和凭据隔离。
  • 集中保存 Docker、主机、防火墙、云平台、身份系统和镜像仓库日志。
  • 检查异常容器创建、特权设置、主机挂载、新镜像和出站连接。
  • 轮换可能被受影响主机或工作负载读取的凭据。
  • 当无法从可信介质确定主机完整性时,重建主机。
  • 把守护进程暴露和配置漂移加入定期安全检查。
  • 记录获批准的远程管理流程,避免工程师创建紧急监听器。

CARBONATO 及时提醒我们:容器平台的控制平面本身就是关键资产。决定防守质量的,不是猜测载荷有多新奇,而是确认谁能够触达守护进程、守护进程能够做什么、它最近做过什么,以及主机失陷后哪些身份会被暴露。当这些问题成为例行检查的一部分,团队就能在不恐慌也不抱侥幸的情况下,更容易管理风险。

来源