Thursday, March 30, 2023

CVE-2022-4696 mitigation on GKE

There's a CVE on GCP that could lead to a privilege escalation (see security bulletin GCP-2023-001). This can be mitigated by blocking the affect syscall with a seccomp profile. Unfortunately Kubernetes doesn't make it easy to deploy a profile, you can only reference a file under the kubelet's root directory, and GKE doesn't provide an easy facility to deploy those files to all the nodes in the cluster. So here's a quick workaround to mitigate the CVE if you need to mitigate it quickly for specific workloads that are at risk (of course the recommended course of action is to upgrade GKE instead).
apiVersion: v1
kind: ServiceAccount
metadata:
  labels:
    app.kubernetes.io/name: seccomp-config
    app.kubernetes.io/part-of: seccomp
  name: seccomp-config

---

apiVersion: v1
kind: ConfigMap
metadata:
  name: seccomp-profiles
  labels:
    app.kubernetes.io/name: seccomp-config
    app.kubernetes.io/part-of: seccomp
data:
  CVE-2022-4696.json: |
    {
      "defaultAction": "SCMP_ACT_ALLOW",
      "architectures": [
        "SCMP_ARCH_X86_64",
        "SCMP_ARCH_X86",
        "SCMP_ARCH_X32"
      ],
      "syscalls": [
        {
          "names": [
            "io_uring_enter",
            "io_uring_register",
            "io_uring_setup"
          ],
          "action": "SCMP_ACT_ERRNO"
        }
      ]
    }

---

apiVersion: apps/v1
kind: DaemonSet                     
metadata:
  name: seccomp-config
  labels:
    app: seccomp-config
    app.kubernetes.io/name: seccomp-config
    app.kubernetes.io/part-of: seccomp
spec:
  selector:
    matchLabels:
      app: seccomp-config
  template:
    metadata:
      labels:
        app: seccomp-config
        name: seccomp-config
        app.kubernetes.io/name: seccomp-config
        app.kubernetes.io/part-of: seccomp
    spec:
      containers:
      - name: seccomp-config
        image: busybox
        command:
        - "sh"
        - "-c"
        - "ls -lR /host && cp -v /config/*.json /host/ && sleep infinity"
        volumeMounts:
        - name: hostdir
          mountPath: /host
        - name: seccomp-profiles
          mountPath: /config
        resources:
          requests:
            cpu: 1m
            memory: 1Mi
          limits:
            cpu: 25m
            memory: 25Mi
        livenessProbe:
          exec:
            command:
            - "true"
          periodSeconds: 600
        securityContext:
          privileged: true
      volumes:
      - name: seccomp-profiles
        configMap:
          defaultMode: 420
          name: seccomp-profiles
      - name: hostdir
        hostPath:
          path: /var/lib/kubelet/seccomp
          type: DirectoryOrCreate
      serviceAccountName: seccomp-config
This deploys the seccomp profile on all the nodes with a daemon set (alternatively consider using the security profiles operator). You may need to deploy this in a namespace where privileged pods are allowed. Then any pod where you want to plug this hole you need to add this to the securityContext of the container:
          seccompProfile:
            localhostProfile: CVE-2022-4696.json
            type: Localhost