Kubernetes 竞争条件漏洞的发现过程简述
聚焦源代码安全,网罗国内外最新资讯!
编译:奇安信代码卫士团队
去年,Checkmarx 公司的安全研究团队在研究 Kubernetes 时发现了一个竞争条件漏洞。如下是漏洞挖掘过程简述。
Kubernetes 是一款最初由谷歌用 Go 语言编写的开源框架,旨在自动化部署、扩展并管理容器化应用程序。
要了解该漏洞,首先需要了解一些Kubernetes 基础知识。Kubernetes 的目的是编排服务器集群即节点,而每个节点都能够托管 Pod。Pod 是在节点上运行的用于封装应用程序的进程。一个应用程序可以包含一个或多个容器。通过创建/删除同一款应用程序的更多 pod,可使Kubernetes 根据应用程序的需要自动增加资源。
集群由一个 Master 节点和多个 Worker 节点组成。Master 节点运行的是 kube-apiserver 进程,可使Master 监控并控制 Workers。在 Workers 节点上,和 Master 的通信由 kubelet 进程完成,而 kube-proxy 进程映射的是 Pod 网络服务,供用户与应用程序交互。下图表说明了 Kubernetes 的主要组件及其交互方式。
要查找 Kubernetes 中的漏洞,我们需要具备多个服务器的实验环境。为此,我们决定使用虚拟机而非物理机。为了自动化实验室创建和重建进程,我们使用了 Terraform、Packer 和 Ansible。本文所述漏洞是由该自动化进程发现的。
在创建实验时,我们重用了 Packer 镜像,但错误地未更改服务器的主机名,当我们将服务器提升为 Kubernetes 集群成员时,意识到该集群并不稳定。Master 节点上的 CPU 负载非常高而且最终导致集群崩溃!
我们无法理解引发这种行为的原因。尽管我们错误地用同样的主机名配置了集群中的服务器,但在 DevOps 进程中这种情况很常见。另外攻击向量即用户在 Worker 中具有足够权限能够导致整个集群崩溃。
当通过命令 kubectl get nodes 在 Master 中列出集群节点时,我们只有一个成员,而它就是原始的 Master,尽管其它节点正确地被添加到了该集群中。
被重新引导到 Master 节点后,集群仍然处于稳定状态。当使用具有相同的主机名和不同 Master 主机名的两个 Worker 进行测试时,集群中也存在不稳定状态,而且 kubectl get nodes 命令的输出中仅显示集群中将要添加的第一个 Worker。
更深入地研究后,我们理解了引发该不稳定性的原因。Etcd **的更新中存在竞争条件。Kubernetes Master 使用 etcd 来存储所有的集群配置和状态数据。集群节点的主机名用于命名 etcd 中的**,格式如下:/registry/minions/HOSTNAME,其中 HOSTNAME 是该节点的实际主机名。
当两个节点共享相同的主机名时,它们每次将状态传达给和 Master 节点时,etcd 就会更新所引用的**。当定期检查该**的值时,我们就证实了该竞争条件的存在,因为两个节点的值会随着时间而随机显示,如图1 所示:
除了更新次数增加外,在每次更新时,多个其它**(事件)也会被创建而且应该由 Kubernetes 组件调度。这就是因 Master 节点上高 CPU 负载而引发集群不稳定的原因所在。
除了在 Worker 节点上增加已经存在的主机名时,还可以在向集群增加节点时使用 hostname-override 的方式利用该漏洞。
我们在公开的 Kubernetes 服务提供商 Azure Kubernetes Service(AKS) 时验证了该行为,并注意到在节点的主机名上增加了一个前缀,足以缓解该漏洞。
Kubernetes GitHub 官方推荐了两种解决方案:一是阻止具有重复主机名或 –hostname-override 值的节点加入集群,二是在 etcd **名称中增加前缀/后缀。
目前该漏洞已修复,方法是阻止具有相同主机名的节点加入集群。
推荐阅读
开源系统Kubernetes 推出公开漏洞奖励计划,最高奖赏1万美元
Kubernetes CLI 工具被曝严重漏洞,谷歌K8S也受影响
原文链接
https://www.checkmarx.com/blog/checkmarx-research-race-condition-in-kubernetes#
题图:Pixabay License
转载请注明“转自奇安信代码卫士 www.codesafe.cn”。
奇安信代码卫士 (codesafe)
国内首个专注于软件开发安全的产品线。
点个“在看”,bounty 不停~