# Remote Code Execution in Google Cloud Dataflow

Unauthenticated Java JMX on Dataflow worker nodes exposed to the internet via permissive VPC firewalls allowed root RCE in an unprivileged container and metadata service account theft.

- Payout: $3,134
- Severity: high
- Program: Google
- Credited: Mike Brancato
- Disclosed: 2021-12-28
- Write-up quality: 7/10
- Original: https://mbrancato.github.io/2021/12/28/rce-dataflow.html
- Library page: https://bugbountylibrary.com/r/blog%3Ambrancato-github-io-2021-12-28-rce-dataflow-html
- Tags: domain:cloud impact:internal-access impact:privesc impact:rce kind:bounty platform:blog sev:high tech:gcp tech:java technique:recon technique:source-review vuln:misconfiguration vuln:rce

**Target:** Dataflow worker node Java JMX port 5555
**Root cause:** Dataflow worker Java process runs with jmxremote.authenticate=false and ssl=false on port 5555, and the node's external IP is reachable when customer VPC firewall rules are permissive.
**Steps:**
1. Launch a Dataflow streaming job (Pub/Sub to Pub/Sub) in a GCP project with a permissive firewall rule allowing TCP 80-8080 from all hosts
2. Identify worker node external IP from Compute Engine console
3. `nmap -p 5555 -Pn <worker-ip>` confirms JMX port open
4. `use exploit/multi/misc/java_jmx_server`, set RHOST/RPORT 5555, run to get meterpreter as root in container
5. `curl -s "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/email" -H "Metadata-Flavor: Google"` to retrieve service account
**How found:** While debugging a Dataflow error via SSH, noticed a kubelet process and undocumented Kubernetes usage; investigated kubelet (no auth but local-only firewall), then enumerated listening ports and firewall rules, spotting port 5555 open and cross-referencing with the Java process command line showing JMX with auth and SSL disabled.
**Exploitation:** Attacker scans GCP IP ranges for port 5555, exploits unauthenticated JMX via Metasploit mlet payload to execute code as root inside the unprivileged container, then queries the metadata service (reachable due to host networking) to obtain the node's service account token, defaulting to the Compute Engine default SA with Editor role on the project.
**Escalation:** Container uses host networking so metadata service is reachable; default compute SA has Editor role, enabling lateral movement across the GCP project. Internal VPC hosts can also reach port 5555 via default-allow-internal rule.
**Insight:** Undocumented managed-service internals (kubelet, host networking, JMX flags) are visible from inside worker nodes; enumerate listening ports and match them to process command lines to find services the vendor forgot to secure, then check whether default VPC firewall rules expose them.
