gcp-dataproc-exposes-cluster-sa-cred
A Dataproc cluster exposes its service account's OAuth token to any code running in submitted jobs via the GCE metadata server.
match
A conjunctive graph pattern. Variables (?x) bind node ids; every clause must hold.
where
node_type(?cluster) ==
AnalyticsService # Dataproc Cluster
emit
| source type | AnalyticsService |
|---|---|
| target type | ServiceAccount |
| source | ?cluster |
| target | ?sa |
Narrative
{cluster.name} exposes the OAuth token of {sa.name} to any code running in a submitted job via the GCE metadata endpoint (http://metadata.google.internal/ computeMetadata/v1/instance/service-accounts/default/token). Any attacker code in a job obtains a usable access token for {sa.name}.
Raw rule rules/derived/gcp/dataproc.yaml
id: gcp-dataproc-exposes-cluster-sa-cred
emits: ExposesCredential
description: A Dataproc cluster exposes its service account's OAuth token to any code running in submitted
jobs via the GCE metadata server.
match:
- - cluster: null
- ExecutesAs
- sa: null
where:
- 'node_type(?cluster) == AnalyticsService # Dataproc Cluster'
emit:
source_type: AnalyticsService
target_type: ServiceAccount
source: ?cluster
target: ?sa
permissions: []
derived_from:
- ?cluster ExecutesAs ?sa (gcp-dataproc-explicit-executes-as)
false_positive_note: "Not an escalation by itself; becomes an attack step only when combined with CanExecuteCommand\
\ (job submission). The exposed credential is a short-lived OAuth 2.0 access token (1-hour TTL), not\
\ a long-lived key. The credential is only accessible from code running inside a job on the cluster\
\ \u2014 it is NOT accessible from the Dataproc control plane or the jobs.get API."
narrative: '{cluster.name} exposes the OAuth token of {sa.name} to any code running in a submitted job
via the GCE metadata endpoint (http://metadata.google.internal/ computeMetadata/v1/instance/service-accounts/default/token).
Any attacker code in a job obtains a usable access token for {sa.name}.'