作者:StackRox
译者:冬哥
原文:https://www.stackrox.io/blog/docker-security-101/
容器以及例如Kubernetes等编排器开启了应用程序开发方法的新时代,支持微服务架构以及持续开发和交付。根据我们最新的容器状态和 Kubernetes 安全报告,Docker 是迄今为止最主要的容器运行时引擎,渗透率为 91% 。
容器化有诸多的好处,因此得到了广泛的采用。据 Gartner 称,到 2020 年,超过 50% 的全球组织将在生产环境中运行容器化应用程序。然而,使用 Docker 容器构建应用程序也带来了新的安全挑战和风险。单个受损的 Docker 容器就可能会威胁到所有其他容器以及底层主机,这凸显了Docker安全防护的重要性。
Docker安全防护大致可以分为两个方面:防护和加固主机,使容器泄露不会导致主机泄露,以及防护Docker 容器。本文重点关注容器安全,重点介绍 Docker 容器安全风险和挑战,并提供在构建和部署阶段强化环境以及在运行时保护 Docker 容器的最佳实践。
鉴于 Kubernetes 的广泛采用和在编排容器中的关键作用,我们还分享了保护 Kubernetes 的最佳实践。最后,我们提供了容器安全平台应该能够回答的 11 个关键安全问题,为你提供在生产环境中安全运行容器和 Kubernetes 所需的洞察力和保护。
Docker 必须解决的 8 个容器安全挑战
企业长期以来一直在虚机 (VM) 或裸机服务器上部署应用程序。此类基础设施的安全性涉及保护你的应用程序及其运行的主机,然后在应用程序运行时加以保护。容器化引入了新的挑战,亟需解决。
容器支持微服务,这增加了数据流量以及网络和访问控制的复杂性。
容器依赖于基础镜像,想要了解镜像的来源安全与否可能具有挑战性。镜像还可能包含漏洞,这些漏洞可以传播到所有使用到此镜像的所有容器。
容器的生命周期很短,因此监控它们,尤其是在运行时,可能非常困难。另一个安全风险来自对不断变化的容器环境缺乏可见性。
与 VM 不同,容器不一定彼此隔离。一个不达标的容器可能导致其他容器受损。
与传统 VM 相比,容器化环境具有更多组件,包括 Kubernetes,它本身就存在一系列安全挑战。你能分辨出哪些部署或集群受到高严重性漏洞的影响吗?有没有暴露到互联网?如果利用给定的漏洞,爆炸半径是多少?容器是在生产环境还是开发/测试环境中运行?
容器配置是另一个带来安全风险的领域。容器是否在不应该的更高权限运行?图像是否启动了增加攻击面的不必要服务?图像中是否存储有秘密?
作为最大的安全驱动因素之一,鉴于容器环境的快速发展,合规性可能是一项特殊挑战。许多有助于证明合规性的传统组件(例如防火墙规则)在 Docker 环境中采用的形式非常不同。
最后,现有的服务器工作负载安全解决方案不足以应对容器安全挑战和风险。
26 个 Docker 安全最佳实践
以下是来自行业标准和 StackRox 客户的最佳实践列表,用于安全地配置你的 Docker 容器和镜像。
始终使用最新版本的 Docker。例如,今年早些时候的runC漏洞在 Docker 版本18.09.2发布后很快就被修补了。
确保只有受信任的用户加入到Docker 组成员,以便于只允许受信任的用户控制 Docker 守护程序。查看这篇文章,了解有关减少 Docker 守护程序攻击面的更多信息。
确保适当的规则,可以提供审计跟踪:
Docker 守护进程
Docker 文件和目录:
/var/lib/docker
/etc/docker
Docker.service
Docker.socket
/etc/default/docker
/etc/docker/daemon.json
/etc/sysconfig/docker
/usr/bin/containerd
/usr/sbin/runc
确保所有 Docker 文件和目录由适当的用户(通常是 root 用户)拥有,并且它们的文件权限设置为限制性值(参见Docker 守护程序配置文件的CIS 基准部分),从而保护所有 Docker 文件和目录。
使用具有有效注册表证书的注册表或使用 TLS 的注册表,以最大程度地降低流量拦截的风险。
如果使用的容器没有在镜像中定义明确的容器用户,你应该启用用户命名空间支持,这将允许你将容器用户重新映射到主机用户。
禁止容器获取新权限,(默认情况下,容器允许获取新权限),因此必须明确设置此配置。可以采取的另一个减少权限提升攻击的步骤是删除镜像中的 setuid 和 setgid 权限。
作为最佳实践,应该以非 root 用户身份运行容器(UID 不是 0)。(默认情况是,容器以root 用户身份在容器内以 root 用户身份运行。)
构建容器时仅使用受信任的基础镜像。这个提示可能看起来显而易见,但第三方注册中心通常没有针对存储在其中的镜像做任何治理策略。了解哪些镜像可在 Docker 主机上使用、了解它们的出处、并查看其中的内容非常重要。你还应该为Docker 启用内容信任以进行镜像验证,并仅将经过验证的包安装到镜像中。
使用不包含可能导致更大攻击面的不必要软件包的最小基础镜像。容器中的组件越少,可用攻击向量的数量就越少,而且最小的镜像也会产生更好的性能,因为磁盘上的字节更少,复制镜像的网络流量也更少。BusyBox 和 Apline 是构建最小基础镜像的两个选项。
实施强有力的治理策略,强制执行频繁的镜像扫描。在进入构建阶段之前,应拒绝陈旧镜像,或重新扫描最近未扫描的镜像。
构建一个工作流,定期识别并从主机中删除陈旧或未使用的镜像和容器。
不要将机密存储在镜像/Dockerfile 中。默认情况下,你可以将机密存储在 Dockerfile 中,但将机密存储在镜像中会使该镜像的任何用户都可以访问机密。需要密文时,请使用密文管理工具。
运行容器时,删除容器运行所需的所有功能。可以使用 Docker 的 CAP DROP 功能删除特定容器的功能(也称为 Linux 功能),并使用 CAP ADD 仅添加容器正常运行所需的那些功能。
不要运行带有--privileged标志的容器,因为这种类型的容器将具有底层主机可用的大部分功能。此标志还会覆盖你使用 CAP DROP 或 CAP ADD 设置的任何规则。
不要在容器上挂载敏感的主机系统目录,尤其是在可写模式下,这可能会使它们暴露在被恶意更改的情况下,从而可能导致主机受损。
不要在容器中运行 sshd。默认情况下,ssh 守护进程不会在容器中运行,不应该安装 ssh 守护进程以简化 SSH 服务器的安全管理。
不要在容器内映射任何低于 1024 的端口,因为它们被认为是特权端口,会传输敏感数据。默认情况下,Docker 将容器端口映射到 49153–65525 范围内的端口,但它允许将容器映射到特权端口。作为一般经验法则,确保容器上只打开需要的端口。
除非必要,否则不要共享主机的网络命名空间、进程命名空间、IPC 命名空间、用户命名空间或 UTS 命名空间,以确保 Docker 容器和底层主机之间的适当隔离。
指定容器按设计运行所需的内存和 CPU 数量,而不是依赖于任意数量。默认情况下,Docker 容器无限制地平等共享其资源。
将容器的根文件系统设置为只读。一旦运行,容器不需要更改根文件系统。对根文件系统所做的任何更改都可能是出于恶意目的。为了保持容器的不可变特性——新容器不会被打补丁而是从新镜像中重新创建——你不应该使根文件系统可写。
施加 PID 限制。容器的优点之一是严格的进程标识符 (PID) 控制。内核中的每个进程都有一个唯一的 PID,容器利用 Linux PID 命名空间为每个容器提供一个单独的 PID 层次结构视图。对 PID 进行限制有效地限制了每个容器中运行的进程数量。限制容器中的进程数量可以防止过度产生新进程和潜在的恶意横向移动。施加 PID 限制还可以防止分叉炸弹(不断自我复制的进程)和异常进程。大多数情况下,如果你的服务始终运行特定数量的进程,那么将PID 限制设置为该确切数量可以减轻许多恶意行为,包括反向 shell 和远程代码注入。
不要将挂载传播规则配置为共享。共享挂载传播意味着对挂载所做的任何更改都将传播到该挂载的所有实例。应该将挂载传播设置为从属或私有模式,以便对卷所做的必要更改不会与不需要该更改的容器共享(或传播到)。
不要使用带有特权或 user=root 选项的 docker exec 命令,因为此设置可以为容器提供扩展的 Linux 功能。
不要使用默认网桥“docker0”。使用默认网桥会使你面临 ARP 欺骗和 MAC 泛洪攻击。相反,容器应该在用户定义的网络上,而不是默认的“docker0”网桥。
不要在容器内挂载 Docker 套接字,因为这种方法将允许容器内的进程执行命令,使其完全控制主机。
Kubernetes 安全的7个最佳实践
作为容器编排的事实标准,Kubernetes 在确保应用程序安全方面发挥着关键作用。为了有效保护容器化应用程序,你必须利用来自 Kubernetes 的上下文信息及其原生策略执行功能。例如,Kubernetes 有几个内置的安全功能,可以更轻松地操作整个生命周期的容器安全性,包括 Kubernetes RBAC、网络策略和准入控制器。利用 Kubernetes 中这些固有控制功能的强大功能来保护你的容器化环境。
以下是一些 Kubernetes 安全最佳实践,可帮助实现整个生命周期的容器安全性。
对于 RBAC,将角色和 ClusterRoles 指定给特定用户或用户组,而不是向任何用户或用户组授予集群管理员权限。
使用 Kubernetes RBAC 时避免重复权限,因为这样做可能会产生操作问题。
删除未使用或非活动的 RBAC 角色,以便在故障排除或调查安全事件时将注意力集中在活动角色上。
使用 Kubernetes 网络策略来隔离Pod,并明确地只允许应用程序运行所需的通信路径。否则,将面临横向和南北威胁。
如果pod 需要Internet 访问(入口或出口),请创建适当的网络策略来强制执行正确的网络分段/防火墙规则,然后创建所述网络策略所针对的标签,最后将pod 与该标签相关联。
使用 PodSecurityPolicy 准入控制器来确保执行适当的治理策略。PodSecurityPolicy 控制器可以阻止容器以 root 身份运行或确保容器的根文件系统以只读方式挂载(这些建议听起来应该很熟悉,因为它们都在前面的 Docker 措施列表中)。
使用 Kubernetes 准入控制器强制执行镜像注册表治理策略,以便自动拒绝从不受信任的注册表中获取的所有镜像。
最后的想法——确保你能回答这 11 个关于 Docker 容器环境的安全问题
为了帮助快速评估你的安全状况,如果你的云原生堆栈已采用适当的安全措施构建,我们编制了安全、DevSecOps 或 DevOps 团队应该能够轻松回答的问题列表。
上次扫描日期超过 60 天的主机上有多少个镜像?
有多少镜像/容器具有高严重性漏洞?
这些高严重性易受攻击的容器会影响哪些部署?
受影响的部署中是否有任何容器存储了机密?
是否有任何易受攻击的容器以 root 或特权标志运行?
Pod 中是否有任何易受攻击的容器没有与之关联的网络策略(意味着它允许所有通信)?
生产中运行的任何容器是否受此漏洞影响?
我们使用的镜像来自哪里?
我们如何阻止从不受信任的注册表中提取的镜像?
我们是否能够在容器运行时看到哪些进程正在执行?
哪些集群、命名空间和节点不符合 Docker 和 Kubernetes 的 CIS 基准?
遵循列表中汇编的这些最佳实践,你将可以采取最重要的步骤来成功强化Docker 和 Kubernetes 环境并保护你的关键业务应用程序。