名词介绍

容器

援引T Wiki

Docker 容器与虚拟机类似,但二者在原理上不同,容器是将操作系统层虚拟化,虚拟机则是虚拟化硬件,因此容器更具有便携性、高效地利用服务器。

架构图如下,里面包括了 Docker 客户端、Docker 容器所在的宿主机和 Docker 镜像仓库三个部分。

其中**宿主机包括了 Docker 守护进程、本地容器和本地镜像,**Docker 守护进程(dockerd)的作用是侦听 Docker API 请求和管理 Docker 对象

img

容器编排

容器编排是指自动化容器的部署、管理、扩展和联网,容器编排可以为需要部署和管理成百上千个 Linux 容器和主机的企业提供便利。

常见的容器编排工具方案有 Kubernetes、Docker Swarm 和 Apache Mesos 等

简明讲解二者关系docker是什么?和kubernetes(k8s)是什么关系?

无服务

无服务(Serverless)是一种云原生开发模型,可使开发人员专注构建和运行应用,这并不是说没有服务器,而是说开发者不用去管服务器只负责开发就行。省去了运维的工作

通常被分为两类,分别是后端即服务(BaaS)和函数即服务(FaaS)

微服务

微服务(Microservices)是一种软件架构风格,它是以专注于单一责任与功能的小型功能区块为基础,利用模块化的方式组合出复杂的大型应用程序,各功能区块使用与语言无关的API集相互通信。

服务网格

服务网格(Service Mesh)用于控制应用的不同部分之间如何共享数据,服务网格内置于应用程序中的专用基础架构层,这个可见的基础架构层可以记录应用的不同部分是否能正常交互。

img

Docker的攻击面

容器镜像风险

  1. 开发者引入了存在漏洞版本的第三方依赖/组件
  2. 攻击者在公共镜像仓库投毒的恶意镜像
  3. 开发者调试过程中遗留的数据库密码/API密钥

活动中容器本身风险

  1. 容器在使用中映射出的敏感服务端口未授权访问

  2. 容器运行本质是基于宿主机操作系统内核,可导致CPU资源耗尽

  3. 不安全的配置与挂载

    • Docker 通过三种主要机制实现容器隔离:

      1. Linux 命名空间(Namespaces)
        • 作用:隔离容器的“视图”,让每个容器觉得自己拥有独立的文件系统、网络、进程列表、主机名等。
        • 实现方式:Linux 内核功能,为每个容器创建独立的“命名空间”。例如,PID 命名空间让容器有自己的进程 ID 1,网络命名空间让容器有自己的 IP 地址和端口。
      2. Linux 控制组(cgroups)
        • 作用:限制和管理容器可以使用的系统资源,如 CPU、内存、硬盘 I/O。
        • 实现方式:Linux 内核功能,为每个容器分配并限制其可以使用的资源配额,防止单个容器耗尽系统资源。
      3. RootFS (根文件系统)
        • 作用:为每个容器提供一个独立的、隔离的文件系统。容器内的文件操作不会影响主机或其他容器。
        • 实现方式:Docker 使用**联合文件系统(Union File System)**技术(如 OverlayFS)来构建容器镜像,它由多个只读层和一个可写层组成,高效且隔离。

      简而言之,命名空间让容器“看不见”彼此和主机,cgroups限制它们能“用多少”资源,而RootFS则提供了独立的“存储空间”。

    • 如果设定了以下配置就会导致相应的隔离机制失效:

      • –privileged:特权运行使容器内的 root 权限和宿主机上的 root 权限一致,权限隔离被打破
      • –net=host:通网挂载使容器与宿主机处于同一网络命名空间,网络隔离被打破
      • –pid=host:进程映射使容器与宿主机处于同一进程命令空间,进程隔离被打破
      • –volume /:/host:文件映射使宿主机根目录被挂载到容器内部,文件系统隔离被打破

容器管理程序接口的风险

Docker 守护进程主要监听 UNIX socket 和 TCP socket,默认情况下,Docker 只会监听 UNIX socket

UNIX socket

UNIX socket 的风险主要在于 Docker 守护进程默认以宿主机的 root 权限运行,因此就可以借助这点进行提权或者容器逃逸

这类风险主要有两个利用场景

  • 普通用户被加到 Docker 用户组内提权

如果普通用户被加入到 Docker 用户组内,那么普通用户也将有权限访问 Docker UNIX socket,如果攻击者获得了这个普通用户权限,就可以借助 Docker 提权到 root 用户权限。

具体的做法可以简单描述为:使用普通用户创建一个 privileged 为 true 的容器,在该容器内挂载宿主机硬盘并**写入定时任务,然后将宿主机的 root 权限反弹回来,**后期将详细介绍这种方法的使用。

  • UNIX socket 挂载到容器内部 用于逃逸

有时为了实现容器内部管理容器,可能会将 Docker UNIX socket 挂载到容器内部,那么如果该容器被入侵,RT 就可以借助这个 socket 进行容器逃逸获得宿主机 root 权限。

TCP socket

现在 Docker 守护进程默认不会监听 TCP socket,不过有时可能用户会因为方便开启 TCP socket 的监听,一般默认监听端口是 2375

默认情况下,Docker 守护进程 TCP socket 是无加密无认证的,因此如果发现宿主机 Docker 开放了 TCP socket,就可以直接使用 docker -H 接管目标的容器

其他风险

容器网络风险

虽然默认情况下,容器内部的网络与宿主机是隔离的,但是每个容器之间是彼此互相连通的,理论上在容器之间是存在内网横向的风险的。

宿主机操作系统风险宿主机操作系统风险

容器通常与宿主机共享内核,也就是说如果宿主机内核存在漏洞,意味着容器可能也会存在相同的漏洞。

例如如果宿主机存在脏牛漏洞,那么拿到容器权限后,使用脏牛漏洞就可以获得宿主机权限,实现容器逃逸。

软件自身的漏洞

Docker 自身存在的一些漏洞,比如 CVE-2019-14271、CVE-2019-5736 等都可以导致容器逃逸,这些也都是风险点,后面会对这些漏洞进行尝试复现。


本站由 Satoru 使用 Stellar 主题创建。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。