Cloud Pentest Checklist

The cloud-config checklist turned into a how-to-test field guide for AWS, GCP, Azure and OCI: recon, IAM, compute and instance-metadata, storage, networking, serverless and containers, secrets/KMS, logging, data, and privilege-escalation chains — plus provider-specific primitives — each with the scenario, the real command (prowler, ScoutSuite, Pacu, aws/gcloud/az CLI, kube-hunter), the steps, the finding, and the fix.

LazyHackers.in — Checklist

☁️ Cloud Pentest Checklist

AWS / GCP / Azure / OCI, item by item: scenario · command · steps · the finding · the fix

☰   How to use this guide

Cloud compromise is rarely one exploit — it's a chain: a leaked key or metadata-reachable credential, an over-permissive IAM policy, and over-shared storage, walked into privilege escalation and lateral movement. Identity is the perimeter. This guide turns every line of the cloud checklist into how-to-test, provider-agnostic first, then AWS/GCP/Azure/OCI primitives. Pair with the web/API checklists for the app layer.

Assumes an authorised assessment (config review + credentialed + external). Chase privesc + lateral-movement chains (§9 + provider primitives), not just isolated public-bucket findings. Each section ends with a coverage table covering every line.
Run automated scanners read-only first; treat any write/exploit action as in-scope only. Never touch another tenant/account you aren't authorised for.
# Read-only posture scanners (run these first, then verify by hand)
prowler aws            # or: prowler gcp / azure / oci
scoutsuite aws         # multi-cloud config audit -> HTML report
# Credentialed enum / privesc mapping
pacu                   # AWS exploitation framework (enum + privesc modules)
cloudsplaining scan --input-file account-authz.json   # IAM least-privilege gaps
# Secrets in repos/images/CI
trufflehog filesystem ./repo ; trufflehog docker --image registry/img:tag

0   Recon & external attack surface

Map the external footprint across all accounts/projects/subscriptions, and hunt for leaked credentials — the fastest path in.

External surface & leaked secrets

# Public buckets / blobs
cloud_enum -k target                    # AWS S3 + GCP + Azure blob brute
# Dangling DNS -> takeover of deleted cloud resources
subfinder -d target.tld | nuclei -t http/takeovers/
# Secrets in public Git / CI logs / IaC state
trufflehog github --org target ; gitleaks detect
# Terraform state / CloudFormation publicly readable -> secrets
curl -s https://bucket.s3.amazonaws.com/terraform.tfstate | jq '.. | .secret? // empty'
⚑ Report as: “Public cloud storage bucket / secrets leaked in public repo or IaC state”
🛡 Fix: Block public access at the org level; remove DNS records when resources are deleted; keep IaC state in a private encrypted backend; scan repos/CI for secrets pre-commit; rotate any exposed key immediately.

Recon & external surface — full coverage

Checklist itemHow to testReport as
Public IP/asset enumerationcloud provider CLI + amassExternal asset exposure
DNS → dev/staging endpointssubfinder/dnsxExposed non-prod endpoint
Dangling DNS → takeovernuclei takeoversSubdomain takeover
Public buckets/blobscloud_enumPublic storage
Exposed management consoleshttpx on known panelsManagement console exposed
Cloud metadata in leaked codetrufflehog/grepCredential/account-ID leak
Secrets in Git/paste/CI/imagestrufflehog, gitleaksSecret leak
Exposed CI/CD endpointsprobe Jenkins/GitLabCI/CD endpoint exposed
Public IaC state leaking secretsfetch tfstateIaC state exposure
Org/account ID enumerationenumerate IDsAccount ID disclosure

1   Identity & access management

The core of cloud security. Look for wildcard policies, self-escalation, long-lived keys, missing MFA, and over-broad trust.

# AWS: who am I, what can I do, where can I escalate
aws sts get-caller-identity
aws iam get-account-authorization-details > authz.json
cloudsplaining scan --input-file authz.json     # flags *:* , privesc, data-exfil perms
# Wildcards in any attached policy:
aws iam list-attached-user-policies --user-name X
# GCP: roles on the project
gcloud projects get-iam-policy PROJECT --format=json | jq '.bindings[]'
# Azure: role assignments
az role assignment list --all -o table
⚑ Report as: “Overly permissive IAM policy (wildcard actions/resources) / identity can self-escalate”
🛡 Fix: Least privilege: no *:*; deny identities the ability to modify their own policies; rotate/disable static keys; enforce MFA (especially privileged/root); apply permission boundaries / SCPs / org policies; restrict cross-account trust with external IDs/conditions.

IAM — full coverage

Checklist itemHow to testReport as
Overly permissive policy (*:*)cloudsplaining / policy reviewWildcard IAM policy
Privesc path via IAMpacu / cloudsplaining privescIAM privilege-escalation path
Long-lived static credentialscheck key ageUnrotated access keys
Stale identities/keys not disabledaudit last-usedStale credentials
MFA not enforcedcheck MFA on users/rootMFA not enforced
Root/global-admin daily usereview root activityRoot account in daily use
Service account over-privilegedreview SA rolesOver-privileged service account
Cross-account trust too broadreview trust policyPermissive cross-account trust
Confused-deputy (no external ID)check AssumeRole conditionConfused-deputy risk
Weak password policy / no rotationreview policyWeak password policy
Federation/SSO trust too broadreview SAML/OIDC trustOver-broad federation trust
No permission boundary / SCPcheck org guardrailsMissing IAM guardrails
No conditional access/IP restrictioncheck console conditionsMissing conditional access
Inline policy hiding grantsenumerate inline policiesExcessive inline policy
Identity self-escalationcheck policy-edit permsSelf-escalation capability

2   Compute / instances

The instance metadata service (IMDS) is the cloud's crown-jewel pivot: an SSRF or shell on an instance reaches metadata and steals the attached role's credentials.

Instance metadata & credential theft

# AWS IMDSv1 (no token) -> role creds directly. From the instance (or via app SSRF):
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/<ROLE>
# IMDSv2 requires a token first (good); if v1 still works it's a finding:
TOKEN=$(curl -s -X PUT http://169.254.169.254/latest/api/token \
  -H 'X-aws-ec2-metadata-token-ttl-seconds: 60')
# GCP / Azure metadata (need the Metadata header):
curl -H 'Metadata-Flavor: Google' http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token
curl -H 'Metadata: true' 'http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/'
⚑ Report as: “IMDSv1 enabled / SSRF to instance metadata yields role credentials”
🛡 Fix: Enforce IMDSv2 (token + hop-limit 1) and disable v1; least-privilege instance roles; restrict SSH/RDP source ranges; patch instances; keep secrets out of user-data; encrypt disks; don't over-share snapshots/images.

Compute / instances — full coverage

Checklist itemHow to testReport as
IMDS reachable & abusablecurl metadata (above)Instance metadata credential theft
IMDSv1 still enabled (AWS)curl without token worksIMDSv1 enabled
SSRF in app → metadataapp SSRF to 169.254.169.254SSRF to cloud metadata
SSH/RDP open to 0.0.0.0/0check SG/firewallManagement port exposed
Default/weak instance credstry defaultsDefault credentials
Instance role over-privilegedreview role permsOver-privileged instance role
Unpatched OS/packagesversion checkOutdated software
User-data leaks secretsread user-dataSecrets in user-data
Public/over-shared snapshot/imagecheck share settingsPublic snapshot/image
Disk/volume unencryptedcheck encryptionUnencrypted volume
Launch template embeds secretsinspect templateSecrets in launch template

3   Storage

Public or over-permissive object storage is the classic cloud breach. Test read, write, listing and pre-signed URL scope.

# AWS S3
aws s3 ls s3://bucket --no-sign-request           # anonymous list?
aws s3 cp test.txt s3://bucket/ --no-sign-request  # anonymous write?
# GCP / Azure
gsutil ls gs://bucket ; az storage blob list --container-name c --account-name a --auth-mode login
⚑ Report as: “Publicly readable/writable storage bucket”
🛡 Fix: Enable Block Public Access / uniform access; encrypt at rest; enable versioning + logging; scope pre-signed/SAS URLs tightly and short; deny anonymous listing; restrict cross-account bucket policies.

Storage — full coverage

Checklist itemHow to testReport as
Publicly readableanonymous list/getPublic read storage
Publicly writableanonymous putPublic write storage
Authenticated-users ACL grantcheck ACLAny-cloud-user access
Unencrypted at restcheck encryptionUnencrypted storage
No versioningcheck versioningNo versioning (ransomware risk)
Over-permissive/long-lived presigned/SASinspect URL TTL/scopeOver-permissive signed URL
Logging disabledcheck access loggingStorage logging disabled
Anonymous listing enabledlist without credsAnonymous object listing
Cross-account policy too broadreview bucket policyBroad cross-account policy
Backups/snapshots unencrypted/publiccheck backupsExposed/unencrypted backup

4   Networking

Find sensitive ports open to the world, flat networks, and missing egress filtering.

# AWS: security groups open to the world on sensitive ports
aws ec2 describe-security-groups --query \
 "SecurityGroups[?IpPermissions[?contains(IpRanges[].CidrIp,'0.0.0.0/0')]].GroupId"
# Then confirm reachability:
nmap -Pn -p 22,3389,3306,5432,6379,9200,27017 <public-ip>
⚑ Report as: “Security group allows 0.0.0.0/0 on a sensitive port”
🛡 Fix: Restrict ingress to required sources; keep DB/cache/admin private; segment VPCs/VNets; remove default permissive rules; add egress filtering; enable flow logs.

Networking — full coverage

Checklist itemHow to testReport as
0.0.0.0/0 on sensitive portsSG/firewall review + nmapOpen sensitive port
Internal services exposedprobe DB/cache/adminInternal service exposed
No segmentation (flat)review topologyNo network segmentation
Default VPC/VNet permissivecheck default networkPermissive default network
Peering/transit trust too broadreview peeringBroad peering trust
No egress filteringtest outboundNo egress filtering
LB/gateway weak TLS or opentestssl.shWeak edge TLS
Public DB endpointcheck DB exposurePublic database endpoint
VPN/bastion bypassabletest bypassBastion/VPN bypass
Flow logs disabledcheck flow logsFlow logging disabled

5   Serverless & containers

Functions and Kubernetes inherit cloud credentials — over-privileged execution roles, public invocation, and exposed K8s APIs are the pivots.

# Kubernetes exposure
kube-hunter --remote <k8s-ip>          # or run in-cluster
kubectl auth can-i --list              # what the default/pod SA can do
# Function env secrets (AWS Lambda)
aws lambda get-function-configuration --function-name F --query Environment
⚑ Report as: “Over-privileged function role / exposed Kubernetes API / public function”
🛡 Fix: Least-privilege execution roles; no plaintext secrets in env (use a secrets manager); require auth on functions; lock down K8s API + RBAC; don't mount default SA tokens; add pod security + network policies; private registries.

Serverless & containers — full coverage

Checklist itemHow to testReport as
Over-privileged function rolereview roleOver-privileged function
Plaintext secrets in env varsread env configSecrets in function env
Publicly invokable functioninvoke unauthenticatedPublic function
Event-source injectionpoison trigger sourceFunction event injection
Public registry / image secretspull & scan imageRegistry/image secret leak
Container as root/privilegedinspect securityContextPrivileged container
K8s API server exposedkube-hunterExposed Kubernetes API
RBAC over-permissive / default SAkubectl auth can-iOver-permissive RBAC
K8s secrets unencrypted/accessiblecheck secret encryptionExposed K8s secrets
No pod security/network policycheck policiesMissing pod/network policy
Kubelet/dashboard exposedprobe 10250 / dashboardKubelet/dashboard exposed
Workload identity over-scopedreview pod→cloud credsOver-scoped workload identity

6   Secrets & key management

Where keys and secrets live and who can use them. Over-permissive KMS policies let anyone decrypt.

⚑ Report as: “Over-permissive KMS key policy / secrets in plaintext config”
🛡 Fix: Tight KMS key policies (only intended principals decrypt); enable key rotation; least-privilege secrets-manager access; separate keys per environment; no hardcoded keys; use CMEK where required.

Secrets & key management — full coverage

Checklist itemHow to testReport as
Secrets in env/user-data/IaC/configgrep config & IaCPlaintext secret
KMS key policy over-permissivereview key policyOver-permissive KMS policy
Key rotation disabledcheck rotationKey rotation disabled
Secrets manager access too broadreview accessBroad secrets access
Keys shared across environmentsreview key scopeCross-environment key reuse
Hardcoded keys in code/imagestrufflehogHardcoded key
No CMEK where requiredcheck encryption typeMissing customer-managed key

7   Logging, monitoring & detection

Detection gaps. Disabled audit logs and tamperable logs mean an attacker operates blind to the defender.

⚑ Report as: “Audit logging disabled (CloudTrail / Audit Logs / Activity Log)”
🛡 Fix: Enable audit logging in all regions/projects; centralise and make logs immutable; alert on privileged/anomalous actions; enable the native threat-detection service (GuardDuty/SCC/Defender).

Logging, monitoring & detection — full coverage

Checklist itemHow to testReport as
Audit logging disabledcheck trail/log configAudit logging disabled
Logs not centralized/immutablereview log sinksLogs not immutable
Log tampering by workloadscheck write permsLog tampering possible
No alerting on privileged actionsreview alertsMissing security alerting
Threat-detection disabledcheck GuardDuty/SCC/DefenderThreat detection disabled
Logging gap in regions/projectsaudit all regionsLogging coverage gap
No detection for cred exfilreview anomaly rulesNo credential-exfil detection

8   Data & databases

Managed databases exposed publicly or with weak/default creds, and PII sitting in non-prod.

⚑ Report as: “Managed database publicly accessible / default credentials”
🛡 Fix: Keep managed DBs private; encrypt at rest and in transit; strong unique creds; don't share snapshots; least-privilege grants; no real PII in non-prod.

Data & databases — full coverage

Checklist itemHow to testReport as
Managed DB publicly accessiblecheck endpoint exposurePublic managed database
DB unencrypted at rest/in transitcheck encryptionUnencrypted database
DB default/weak credentialstry defaultsWeak database credentials
DB snapshot public/sharedcheck snapshot sharingPublic DB snapshot
Data warehouse over-sharedreview accessOver-shared analytics store
No least-privilege DB grantsreview grantsExcessive DB privileges
PII in non-prodinspect non-prod dataPII in non-production

9   Privilege escalation & lateral movement

The story of a cloud pentest: turn an initial credential into account/org takeover via IAM privesc primitives and service chaining.

# AWS PassRole + service privesc (classic): pass a high-priv role to a service you control
aws iam pass-role ... ; aws lambda create-function --role <highPrivRole> ...   # then invoke
# Pacu automates discovery of these:
pacu > run iam__privesc_scan
# GCP SA impersonation
gcloud auth print-access-token --impersonate-service-account=PRIV_SA@proj.iam.gserviceaccount.com
⚑ Report as: “Privilege escalation via iam:PassRole / role-assignment / SA impersonation”
🛡 Fix: Remove dangerous privesc primitives (PassRole+service, policy self-attach, actAs, role-assignment) from non-admin identities; least privilege on CI/CD roles; constrain trust; tie every finding back to blast radius.

Privilege escalation & lateral movement — full coverage

Checklist itemHow to testReport as
PassRole / role-assignment abusepacu privesc / manualIAM privilege escalation
Create/modify policy on selfattach policy to selfSelf-escalation
Assume higher-priv roleAssumeRole via broad trustRole-assumption escalation
Function/compute role escalatefunction→role abuseCompute-role escalation
CI/CD role over-privilegedreview pipeline roleCI/CD takeover path
Resource policy cross-account pivotabuse resource policyCross-account pivot
Metadata creds → broader accesspivot with stolen credsLateral movement via metadata
Service chaining (compute→storage→IAM)map chainService-chain escalation
Backup/restore to bypass controlsrestore to weaker envControl bypass via restore
Org-level escalationreach org/adminOrganization-level escalation
Provider-specific checks

A   AWS

AWS privesc lives in IAM/STS primitives plus S3, IMDS and broad resource policies.

⚑ Report as: “AWS: iam:PassRole + service privesc / public S3 / IMDSv1”
🛡 Fix: Enforce IMDSv2 + SCP guardrails; remove PassRole/CreatePolicyVersion from non-admins; Block Public Access on S3; AssumeRole with external ID; multi-region CloudTrail + GuardDuty on.

AWS — full coverage

Checklist itemHow to testReport as
IMDSv1 enabledcurl metadata w/o tokenIMDSv1 enabled
PassRole + service privescpacu iam__privesc_scanPassRole privilege escalation
CreatePolicyVersion / AttachUserPolicy self-escalateattempt self-attachIAM self-escalation
AssumeRole broad / no external IDreview trustConfused-deputy / broad trust
Access keys not rotated; root keyscheck key ageUnrotated / root keys
No SCP guardrailscheck org SCPsMissing SCPs
* resource on iam/kms/s3policy reviewWildcard on sensitive actions
Public S3 (ACL/policy)s3 ls --no-sign-requestPublic S3 bucket
Block Public Access disabledcheck BPABlock Public Access off
EC2 SSRF → IMDS role credsapp SSRF to IMDSSSRF to IMDS
SG 0.0.0.0/0 sensitive portsdescribe-security-groupsOpen security group
Public AMI / EBS snapshotcheck share settingsPublic AMI/snapshot
Lambda env secrets / public URLget-function-configurationLambda exposure
RDS public/unencrypteddescribe-db-instancesRDS exposure
Secrets Manager/SSM over-permissivereview resource policyBroad secrets access
KMS broad decryptreview key policyOver-permissive KMS
CloudTrail disabled/single-regiondescribe-trailsCloudTrail gap
GuardDuty disabledcheck GuardDutyGuardDuty disabled
ECR public / ECS task role broadreview ECR/ECSECR/ECS misconfig
EKS public endpoint / loose aws-authreview EKSEKS misconfig

B   Google Cloud (GCP)

GCP privesc centers on service-account impersonation and key creation, plus default-SA scopes and public GCS.

⚑ Report as: “GCP: SA impersonation (actAs / getAccessToken) or key creation privesc”
🛡 Fix: Avoid primitive roles (owner/editor); remove actAs/serviceAccountKeys.create from non-admins; uniform bucket access; conceal GCE metadata + minimal default-SA scopes; enable Data Access audit logs + SCC.

Google Cloud (GCP) — full coverage

Checklist itemHow to testReport as
actAs / getAccessToken → SA impersonationgcloud impersonateSA impersonation privesc
serviceAccountKeys.create privescmint key for priv SASA key-creation privesc
owner/editor granted broadlyreview bindingsPrimitive-role over-grant
SA key (JSON) leaked/long-livedfind key filesLeaked SA key
Primitive instead of predefined rolesreview rolesPrimitive roles in use
allUsers/allAuthenticatedUsers bindingcheck IAM bindingsPublic IAM binding
Project-level where resource-level neededreview scopeOver-broad binding scope
GCS public (allUsers)gsutil iam getPublic GCS bucket
Uniform access disabled / legacy ACLscheck bucket configLegacy ACLs enabled
GCE metadata reachable / default SA scopescurl metadataMetadata / default-SA exposure
setMetadata → add SSH key privesccompute.instances.setMetadataSSH-key metadata privesc
Firewall 0.0.0.0/0 sensitive portsreview firewallOpen firewall rule
Cloud Function/Run publicinvoke unauthenticatedPublic function/service
Cloud SQL public IP / weak authreview Cloud SQLCloud SQL exposure
Secret Manager too broadreview accessBroad secret access
GKE legacy auth/public/loose RBAC/metadatareview GKEGKE misconfig
Data Access audit logs disabledcheck audit configAudit logging disabled
SCC not enabledcheck SCCSecurity Command Center off

C   Microsoft Azure

Azure privesc is role-assignment and app/service-principal Graph permissions, plus managed identity and public blob/SAS.

⚑ Report as: “Azure: role-assignment privesc / over-permissioned app or managed identity”
🛡 Fix: Least-privilege RBAC at the right scope; review app/SP Graph permissions and rotate secrets/certs; enforce Conditional Access + MFA; constrain managed-identity scope; disable anonymous blob; tight Key Vault access; enable Activity Log + Defender for Cloud.

Microsoft Azure — full coverage

Checklist itemHow to testReport as
Owner/Contributor at sub/MG scopeaz role assignment listOver-privileged role assignment
User Access Administrator privesccheck role-assignment rightsRole-assignment privesc
SP/app over-permissionedreview app permsOver-permissioned service principal
App high Graph permissionsreview Graph consentExcessive Graph permissions
Stale/leaked app secrets & certscheck credentialsLeaked app secret
Conditional Access / MFA gapsreview CA policiesConditional Access gap
Guest user over-privilegedreview guest rolesOver-privileged guest
Managed identity over-scopedreview MI rolesOver-scoped managed identity
Dynamic group rule abusereview group rulesDynamic-group privesc
Public blob containeraz storage blob listPublic blob container
Anonymous blob accessanonymous requestAnonymous blob access
Over-permissive/long-lived SASinspect SASOver-permissive SAS
Storage account key exposedfind keyStorage key exposure
VM IMDS → MI tokencurl IMDSManaged-identity token theft
NSG 0.0.0.0/0 sensitive portsreview NSGOpen NSG rule
Public IP on sensitive VMcheck public IPsExposed VM
Key Vault access too broadreview access policy/RBACBroad Key Vault access
Function App public / secrets in settingsreview Function AppFunction App exposure
Azure SQL firewall allows allreview firewallAzure SQL exposure
AKS public API / loose RBACreview AKSAKS misconfig
Activity Log / diagnostics disabledcheck loggingLogging disabled
Defender for Cloud disabledcheck DefenderDefender disabled

D   Oracle Cloud (OCI)

OCI privesc is broad tenancy policies and instance/dynamic-group principals, plus public buckets and PARs.

⚑ Report as: “OCI: overly broad tenancy policy / instance-principal abuse”
🛡 Fix: Scope policies to compartments, not tenancy; rotate API signing keys; least-privilege dynamic groups; MFA on admins; constrain federation trust; private buckets; tight, short PARs; enable Audit + Cloud Guard across compartments.

Oracle Cloud (OCI) — full coverage

Checklist itemHow to testReport as
Broad policy (manage all-resources)review policiesOver-broad tenancy policy
Policy at tenancy where compartment fitsreview scopeExcessive policy scope
Stale API signing keyscheck key ageUnrotated API key
Over-privileged dynamic groupreview dynamic groupsDynamic-group privesc
Admin group too broad / no MFAreview adminsWeak admin controls
Cross-tenancy policy permissivereview cross-tenancyBroad cross-tenancy trust
Federation/IdP misconfigreview federationFederation misconfig
Object Storage publiccheck visibilityPublic bucket
PAR over-permissive/long-livedinspect PAROver-permissive PAR
Bucket not CMEK where requiredcheck encryptionMissing CMEK
Instance metadata → principal tokencurl metadataInstance-principal abuse
SSH exposed to 0.0.0.0/0review security listOpen SSH
Security list/NSG open portsreview rulesOpen network rule
Public DB / Autonomous DBcheck exposurePublic database
Vault/secret access too broadreview accessBroad secret access
Functions over-privileged/publicreview functionsFunction exposure
OKE public API / loose RBACreview OKEOKE misconfig
Audit/logging not enabledcheck auditAudit disabled
Cloud Guard not enabledcheck Cloud GuardCloud Guard disabled

✓   Coverage map & how to run it

Run universal 0–9 on every cloud assessment, then the provider block. The highest-value work is the privesc + lateral-movement chains, not isolated public buckets.

SectionRun onFocus
Universal 0–9Every cloud assessmentRecon, IAM, compute/metadata, storage, networking, serverless, secrets, logging, data, privesc
AWSAWS accountsPassRole, policy self-attach, IMDSv1, S3, AssumeRole trust
GCPGCP projectsSA impersonation, key creation, default-SA scopes, GCS allUsers
AzureAzure tenantsRole-assignment privesc, app/SP Graph, managed identity, public blob/SAS
OCIOCI tenanciesBroad tenancy policy, instance/dynamic-group principals, PAR, public buckets

Core principle: identity is the perimeter. Most cloud compromise is misconfigured IAM + metadata-reachable credentials + over-shared storage, chained. Map every finding back to least-privilege and blast radius, and report the chain, not just the list. Tick a box only when you've actually verified it.

Reactions

Related Articles