无法控制:Kubernetes 中存在命令注入漏洞
编辑和评论补充:Tricia Howard
执行摘要
Akamai 安全研究人员 Tomer Peled 最近在 Kubernetes 中发现了一个 高严重性漏洞 ,该漏洞编号为 CVE-2023-3676,CVSS 评分为 8.8。
本次发现还识别出另外两个漏洞,因为它们具有相同的根本原因:不安全的函数调用并且缺少用户输入清理。
简介
YAML(表示 YAML 不是标记语言)是类似于 JSON 的一种数据序列化语言,主要用在配置文件中。因此,它在 Kubernetes 中发挥着重要作用。Kubernetes 是无处不在的新型容器编排系统,可有助于企业自动完成容器化应用程序的部署、扩展和管理。Kubernetes 框架几乎将 YAML 文件用于各个方面,从配置容器网络接口到 Pod 管理,甚至是密钥处理都会用到该文件。
近年来,Kubernetes 中的 YAML 文件已成为人们研究的主题。考虑到 Kubernetes 依赖 YAML 进行集群配置,因此这个研究课题特别值得深入研究。
先前 YAML 和 Kubernetes 是如何被利用的?
2022 年, CVE-2022-1471 在知名的 YAML 文件解析器 SnakeYAML 的构造函数中被发现。利用该漏洞,攻击者能够创建不安全的对象。这样,当易受攻击的应用程序使用这些对象时,攻击者便能够在这些应用程序上执行代码。另一个示例也说明了 YAML 文件可能的影响,您可以在 Kubernetes 安全团队所编写的关于 CVE-2021-25749 的 CVE 公告 中查看此示例。利用该漏洞,攻击者只需在 YAML 文件中将其名称拼写错误便能够绕过相关验证,从而实现以 root 用户身份运行。
在对 Kubernetes 的研究过程中,我们发现了 CVE-2017-1002101 和 CVE-2021-25741。这两个漏洞揭示了攻击者如何将争用条件和符号链接与 YAML 文件中的 subPath 子属性结合使用,从而在容器外获取对特权数据的访问权限。
受到这两个漏洞的启发,我们沿着 Kubernetes 代码库中的路径处理方向继续深入研究,最终发现了现在所讨论的这个漏洞。
在本博文中,我们会演示拥有“apply”特权(即,与 Kubernetes API 进行交互所需的特权)的攻击者如何注入将使用 SYSTEM 特权在远程 Windows 机器上执行的代码。
漏洞详情
在某个 Pod 被创建后,用户可以选择在该 Pod 与主机之间创建一个共享目录。称为 卷 的这项功能非常有用,例如,它可用于通过 Pod 中的容器为网站提供服务。我们可能需要共享与主机所共享的某个目录中的站点文件;这样,我们便能够根据自己的需要更改站点布局,以便每次重新编译包含该站点的映像。
通过在 Pod 的 YAML 文件中包含 volume 参数 即可启用卷。 mountPath (容器中的位置)和 hostPath (主机上的位置)中列出了装载卷的位置。
对于我们来说,最重要的是,我们可以使用 subPath 子属性在所选位置装载共享目录或文件。图 1 显示的是卷的所有相关属性。
YAML 文件的解析由 kubelet 执行,kubelet 是 Kubernetes 中的核心服务,负责在节点上运行容器化应用程序。作为 CVE-2021-25741 修补方法的一部分,kubelet 会验证 YAML 文件中的每个参数,并且还会调用内部函数“isLinkPath”来确保使用 subPath 参数不会导致创建任何符号链接。图 2 中显示的函数。
该函数可作为用户在 YAML 文件中提供的 subPath 的参数。然后,它会使用此路径创建用于确定路径类型(即,它是否为符号链接)的 PowerShell 命令。“exec.Command”函数调用随后会直接调用带格式的 PowerShell 命令。
“exec.Command”与未清理的用户输入内容同时存在,强烈暗示攻击者有机会进行命令注入。
利用 PowerShell,用户能够在字符串内的值被使用之前对这些值进行计算。例如,可以通过向您的字符串中添加 $(<experssion_to_be_evaluated>) 来完成此操作(图 3)。
PS> echo “the value of 1+1 is $(1+1)
Output:
the value of 1+1 is 2
图 3:对字符串内的表达式求值的 PowerShell 的示例
此示例非常简单,但实际上可以在括号中插入 任何 PowerShell 命令并对其进行求值,例如 $(Start-Process cmd)、$(Invoke-Expression exp) 以及其他 PowerShell 处理。
攻击者可以滥用此 subPath 求值以访问易受攻击的代码,并使用 SYSTEM 特权 从远程节点 执行任何所需的命令(kubelet 自己的上下文),从而获得对集群中所有 Windows 节点的控制。图 4 显示了一个恶意的 subPath 值。
修补分析
Kubernetes 团队选择传递来自环境变量而不是用户输入的参数,以此修补此类漏洞(图 5)。通过以此方式向下传递值,这些参数会被视为字符串,因此 PowerShell 不会将它们作为表达式进行求值。
我是否容易受到攻击?
正如我们先前所提到的,所有低于 1.28 版本的 Kubernetes 都因存在此 CVE 而容易受到攻击。有几种方法可以确定您的集群中是否有某个节点为 Windows 节点。其中一种方法是执行图 6 中的命令。
kubectl get nodes -o wide --show-labels | grep “os=windows” 输出: akswin000000 Ready agent 4d17h v1.26.6 agentpool=win,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=windows… akswin000001 Ready agent 4d17h v1.26.6 agentpool=win,beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=windows… |
图 6:用于确定您的集群中是否有某个节点为 Windows 节点的 kubectl 命令
抵御措施
安装补丁是保护自己免受此漏洞威胁的最可靠方法。如果无法安装该补丁,我们还给出了一些能够抵御此漏洞的方法,您可以从中选择适合您环境的方法。
先前的解决方案
对于 CVE-2023-3676,Kubernetes 管理员可以禁用 Volume.Subpath。这将确保您的集群能够抵御此漏洞,但会禁用有时在生产中对集群来说很重要的一项机制。
package kubernetes.admission
deny[msg] {
input.request.kind.kind == "Pod"
path := input.request.object.spec.containers.volumeMounts.subPath
not startswith(path, "$(")
msg := sprintf("malicious path: %v was found", [path])
}
图 7:将阻止使用恶意 subPath 创建 Pod 的规则
RBAC
基于角色的访问控制 (RBAC) 是一种根据用户角色划分用户操作的方法。例如,每个用户只能在自己的命名空间中创建 Pod,或者只能查看允许访问的命名空间的信息。这可能有助于限制能对集群执行操作的用户的数量,并且有助于将注意力集中在拥有漏洞利用相关特权的用户身上。
结论
CVE-2023-3676 需要较低特权,因此对攻击者来说,其利用门槛较低:他们只需要拥有对某个节点的访问权限以及 应用 特权即可利用该漏洞。正如我们在本博文中讨论的那样,成功利用此漏洞会让攻击者可以在机器上的任何 Windows 节点中使用 SYSTEM 特权实现远程代码执行。
影响重大且易于利用通常意味着各企业遭遇此攻击(及类似攻击)的可能性更高。实际上,对于此漏洞,唯一的局限性是其作用范围,即它只对如今不太流行的 Windows 节点起作用。
管理员应为他们的 Kubernetes 集群安装补丁以升级到可用的最新版本,从而避免这些漏洞被利用,这一点很重要。如果您无法立即安装补丁,我们建议您采用上述方法之一来抵御此漏洞。
对于做出快速响应并与我们进行了顺畅沟通的 Kubernetes 团队,我们在此深表感谢。
披露时间表
2023 年 7 月 13 日,我们将漏洞披露给 Kubernetes 团队。
2023 年 7 月 19 日,Kubernetes 团队分配了 CVE 编号
2023 年 8 月 23 日,Kubernetes 发布了 CVE 修复方法
2023 年 9 月 13 日,博文发布