
PoC funzionale di CVE-2026-17106 (CopyEscape): corsa TOCTOU in docker cp che consente scrittura arbitraria sull'host Docker. Laboratorio Docker + monitor inotify + LD_PRELOAD. Variante macOS innocua e Linux distruttiva.
Proof of Concept educativa di CopyEscape (CVE-2026-17106), vulnerabilità di race condition TOCTOU in
docker cpche consente a un container dannoso di scrivere file arbitrari sull'host Docker. Ispirata al lavoro originale di masasron, che ha scoperto e documentato la vulnerabilità nel blog "CopyEscape: Taking Over Docker Hosts with docker cp".
CVE-2026-17106 è una vulnerabilità di race condition (TOCTOU) nell'estrazione del file tar che il daemon Docker produce durante docker cp <contenedor>:<ruta> <destino>. Interessa Docker CLI 29.6.1 e versioni precedenti; corretta a partire dalla 29.7.0. Il bug risiede nella CLI (estrazione del tar sull'host), non nel daemon.
La catena battezzata CopyEscape dimostra come, partendo unicamente da un container in esecuzione senza capacità extra, un attaccante può:
/watched/file.txt/ come un file regolare davanti a qualsiasi processo che lo apra dentro il container, tramite una libreria LD_PRELOAD che intercetta open, openat, openat2, fopen, stat, lstat, fstatat, statx e le varianti 64.aaa.txt da 16 MiB che costringe il daemon a impiegare abbastanza tempo a produrre il tar affinché il monitor vinca la corsa.inotify gli accessi del daemon e, nella finestra di corsa, sostituire una sottodirectory escape/ con un symlink assoluto verso il target dell'host (/Users/<usuario> su macOS o /usr/bin su Linux) tramite due rename(2) atomici con rollback.escape seguito da una voce figlia escape/<basename>; la CLI vulnerabile crea il symlink sul client ed estrae la voce figlia attraverso di esso, scrivendo fuori dalla destinazione scelta dall'utente.Il risultato è scrittura arbitraria di file sull'host con i permessi del processo che esegue docker cp. La variante Linux sovrascrive /usr/bin/runc e ottiene esecuzione di codice come root sull'host al successivo docker run / exec.
Questo repository contiene materiale strettamente educativo e difensivo.
runc dell'host: usala solo in una VM monouso con backup verificato.La PoC viene fornita con una variante macOS innocua (scrive ~/pwnd come marcatore) il cui unico scopo è servire come dimostrazione riproducibile.
┌─────────────────────────────────────────────────────────────────────┐
│ 1. LD_PRELOAD camufla /watched/file.txt como archivo regular │
│ open/openat/openat2/fopen/stat/lstat/fstatat/statx → decoy │
│ docker exec ... cat /watched/file.txt → "top-level file" │
└──────────────────────────────────────────┬──────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 2. Layout real dentro del contenedor │
│ /watched/file.txt/ │
│ ├── aaa.txt (16 MiB de 'B', cebo lento) │
│ ├── escape/ (directorio real inicial) │
│ ├── escape/<basename> (payload: runc o pwnd) │
│ └── .swap-escape (symlink → /Users/<usr> o /usr/bin) │
└──────────────────────────────────────────┬──────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 3. docker cp pide tar al daemon │
│ daemon recorre /watched/file.txt/ y abre aaa.txt │
│ inotify detecta IN_OPEN sobre aaa.txt │
└──────────────────────────────────────────┬──────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 4. Monitor pivot: dos rename(2) atomicos con rollback │
│ escape/ → .old-escape/ (backup) │
│ .swap-escape → escape/ (symlink al target del host) │
└──────────────────────────────────────────┬──────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 5. Tar resultante contiene: │
│ escape → /Users/<usr> (symlink absoluto) │
│ escape/<basename> (entrada hija que atraviesa el symlink) │
└──────────────────────────────────────────┬──────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ 6. CLI vulnerable extrae symlink + hija │
│ crea escape → /Users/<usr> en el destino local │
│ extrae escape/<basename> A TRAVES del symlink │
│ escribe /Users/<usr>/<basename> en el host │
└──────────────────────────────────────────┬──────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────┐
│ macOS: ~/pwnd con "COPYESCAPE_MACOS_DEMO" (demo inocua) │
│ Linux: /usr/bin/runc sobrescrito (RCE como root) │
└─────────────────────────────────────────────────────────────────────┘
La PoC è pensata per essere eseguita su macOS con:
curl, tar, git e docker nel PATH.alpine:3.21.HOME nella forma /Users/<usuario>.Non serve root per la variante macOS. La variante Linux richiede root e una VM monouso.
Il runner run-poc.sh scarica automaticamente il binario della CLI vulnerabile 29.6.1 dal sito ufficiale Docker (download.docker.com). Non modifica l'installazione di Docker Desktop del sistema: usa il daemon attuale ma invoca il binario scaricato per l'operazione docker cp.