Cloud attack hunting for AWS / Azure / GCP - credential discovery, metadata SSRF, IAM privesc, service enumeration, persistence. Scope + billing aware. Wiki-first, FIND schema output.
npx skills add https://github.com/Encod3d-Sec/TORCH --skill hunt-cloud
Assumes hunt-core for the scope gate, two-account rule, confirmation gate, enumeration limits, stop conditions, wiki protocol, FIND output, and Deadends. Do not re-derive any of that here.
qmd_query "cloud AWS Azure GCP metadata SSRF IAM privilege escalation credential discovery persistence" via wiki-search MCP
Hub: [[cloud-moc]] (live index). Primary page: [[cloud-iam-attacks]]. Payload arsenal: wiki/payloads/imds-cloud-metadata.md.
Anchors: [[aws-metadata-ssrf]] (SSRF -> IMDS creds), [[azure-ad-iam]].
hunt-core owns the scope gate. Cloud stacks three specifics on top of it:
loot.md first.169.254.169.254 / metadata.google.internal hands you instance/managed-identity creds. Highest-value chain..env, ~/.aws/credentials, CI/CD vars, JS bundles, git history: AKIA*/ASIA* (AWS), AccountKey= (Azure), "type":"service_account" JSON (GCP).*.s3.amazonaws.com, Azure *.blob.core.windows.net, GCS storage.googleapis.com/<bucket>. Ranked last: frequently non-sensitive, easy to over-claim.Chaining: SSRF that reaches the metadata endpoint -> pull IMDS creds; this is a hand-off from / to hunt-ssrf (that skill owns reaching the endpoint, this one owns what the creds unlock). A leaked key -> IAM enumeration -> privesc chain (step 4).
Evasion: AWS IMDSv2 needs a session token first (PUT /latest/api/token with X-aws-ec2-metadata-token-ttl-seconds, then X-aws-ec2-metadata-token on the GET) - an SSRF that cannot set headers only reaches IMDSv1. Enumeration is logged: prefer a compromised in-account principal over external calls, and read-only actions over anything that writes an audit event you cannot explain.
The provider CLIs and roadrecon do enumeration + attack in one authenticated call - **install them
FIRST**; hand-rolled curl/urllib against Graph/ARM is the drift to avoid (weaker, no paging, easy
to misquote). Reach for a script only for the rare thing the CLI can't express.
az login -u <upn> -p <pass> (ROPC; works on Managed tenants when the CLIclient isn't MFA-gated). Then az account show, az account list, az resource list -o table,
az vm list -d -o table, az role assignment list --all. Entra dump = roadrecon (`roadrecon auth
-r <refresh-token> reuses a token cross-client via FOCI, no password quoting; then roadrecon dump`).
AzureHound for attack paths; MicroBurst Get-AzPasswords (pwsh) to sweep KV/automation/storage secrets.
your system"). Install with curl -sL https://aka.ms/InstallAzureCLIDeb | DIST_CODE=bookworm bash,
or just run az on the target Ubuntu VM where it installs cleanly.
az login --identity authenticates AS that resource's managed identity straight from IMDS; then use
az normally. az account show confirms user.type=servicePrincipal / systemAssignedIdentity.
aws sts get-caller-identity
az account show; az ad signed-in-user show
gcloud auth list; gcloud config list
# AWS IMDSv1
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/<role>
# Azure (Metadata:true header)
curl -H "Metadata:true" "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"
# GCP (Metadata-Flavor: Google)
curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token"
hunt-core, but each of these fans out into many billed, logged API calls, so scope tightly and do not loop them):aws iam get-account-authorization-details; enumerate-iam --access-key ... --secret-key ... # or pacu
az role assignment list --assignee <id>; ScoutSuite azure
gcloud projects get-iam-policy <proj>; curl https://... (roadtools / ROADrecon for Entra)
iam:PassRole+lambda/ec2, sts:AssumeRole, policy version, iam:CreateAccessKey); Azure (Owner/Contributor on subscription, Microsoft.Authorization/*, managed identity abuse, Automation runbooks); GCP (iam.serviceAccounts.actAs, setIamPolicy, deployment manager, actAs chains).az vm extension show ... -n CustomScriptExtension leaks commandToExecute/fileUris (secrets, SAS URLs), no Contributor/RunCommand needed (see [[azure-services-virtual-machine]]).python3 scripts/wiki-stage.py --kind technique --slug <slug> --target-page techniques/cloud/cloud-iam-attacks.md. Full protocol in hunt-core.NOT confirmation: an enumerated bucket / blob / GCS name; a role ARN or service-account email you listed but never assumed; a metadata endpoint that merely responds; AKIA* / AccountKey= / service-account JSON found but never exercised; a 200 from a permissions enumerator that only reads policy, not access.
IS confirmation: credentials actually retrieved AND validated with a SINGLE benign read-only call that names the principal (aws sts get-caller-identity, az account show, gcloud auth list), or a resource actually read cross-account / cross-tenant - reproduced in a clean session. One benign call proves control: stop there. Do NOT spin up resources or mass-enumerate to "prove more" - that only adds billing, audit noise, and abuse-detection risk without changing the finding.
CRITICAL = creds to admin/owner, cross-account/tenant takeover, metadata role creds. HIGH = sensitive data read (secrets/buckets), IAM privesc path. MEDIUM = enumeration / public bucket with non-sensitive data.
<!-- auto-wired: documented tools to reach for; do not hand-roll -->
Take encod3d-sec/hunt-cloud from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.