Clé de compte de service GCP divulguée : enquêter
Clé de compte de service fuitée dans un dépôt ou un log de CI ? Trouvez son ID, les IP qui l'ont utilisée, ses actions via serviceAccountKeyName.
En bref. Chaque appel d'API authentifié avec une clé de compte de service gérée par l'utilisateur porte protoPayload.authenticationInfo.serviceAccountKeyName, qui se termine par /keys/<KEY_ID>. Filtrez sur cet ID de clé, listez les IP d'appel et les user agents dans l'ordre chronologique, et cherchez la première IP publique que vous ne savez pas expliquer. Ensuite, suivez cette IP : énumération (rafales de PERMISSION_DENIED), SetIamPolicy, nouvelles clés, nouveaux comptes de service. Désactivez la clé d'abord, enquêtez ensuite.
Les clés JSON téléchargeables sont la façon la plus courante d'ouvrir un projet Google Cloud depuis l'extérieur. Elles n'expirent pas par défaut, finissent dans des dépôts Git, des variables de CI, des images Docker et des portables, et celui qui détient le fichier est le compte de service. Les bonnes pratiques de gestion des clés de Google recommandent de s'en passer ; en attendant, il faut savoir enquêter sur une clé.
Étape 1 : identifier la clé
On part généralement de l'un de ces éléments :
- le fichier de clé lui-même, dont le champ
private_key_idest l'ID de la clé ; - une notification de Google indiquant qu'une clé a été exposée publiquement ;
- un constat sur un compte de service qui fait des choses qu'il ne fait jamais.
Listez les clés du compte de service avec gcloud iam service-accounts keys list --iam-account=SA_EMAIL et notez, pour chaque clé gérée par l'utilisateur, son ID et sa date de création. Retrouvez ensuite l'entrée de création dans les journaux Admin Activity :
protoPayload.methodName="google.iam.admin.v1.CreateServiceAccountKey"
Le créateur figure dans authenticationInfo.principalEmail, le nom de la nouvelle clé dans protoPayload.response.name. Une clé créée par une personne depuis l'IP du bureau des semaines avant l'incident raconte une fuite par erreur. Une clé créée pendant l'incident, par l'attaquant, raconte une persistance : MITRE ATT&CK T1098.001, identifiants cloud supplémentaires. Cherchez aussi google.iam.admin.v1.UploadServiceAccountKey : une clé publique importée signifie que quelqu'un, à l'extérieur, détient la moitié privée.
Étape 2 : retrouver chaque utilisation de la clé
Les exemples de journaux pour les comptes de service de Google montrent que les appels effectués avec une clé contiennent :
"serviceAccountKeyName": "//iam.googleapis.com/projects/PROJECT/serviceAccounts/SA_EMAIL/keys/KEY_ID"
La requête est donc simple :
protoPayload.authenticationInfo.serviceAccountKeyName:"KEY_ID"
Classez les résultats par date et construisez un petit tableau : première et dernière apparition, IP d'appel, user agent, nombre d'appels. Ce que vous cherchez :
| Motif | Lecture |
|---|---|
| Une seule IP, votre runner de CI ou le bureau, user agent stable | Usage normal |
Une nouvelle IP publique, un user agent différent (gcloud là où il n'y avait que Terraform) | La clé a été copiée |
| Une rafale de code d'état 7 (PERMISSION_DENIED) sur de nombreux services | Quelqu'un teste ce que la clé permet : T1580 / T1526 |
SetIamPolicy, CreateServiceAccountKey, CreateServiceAccount depuis cette IP | Élévation de privilèges et persistance |
Rappelez-vous que les appels en lecture (GetIamPolicy, storage.objects.get, ListServiceAccounts) sont des journaux Data Access. Sans journalisation Data Access, vous ne verrez que les écritures de la clé. Pour les lectures refusées avec PERMISSION_DENIED, Google peut masquer l'e-mail de l'appelant, mais pas lorsqu'il s'agit d'un compte de service (identités des appelants dans les journaux d'audit) : les lectures refusées d'une clé divulguée restent donc attribuables.
Étape 3 : distinguer la CI de l'attaquant
Le plus difficile n'est pas de trouver des IP externes, c'est que les clés légitimes sont elles aussi utilisées hors de Google Cloud. Un runner GitHub Actions, le serveur d'un partenaire, le portable d'un développeur : ce sont toutes des « IP publiques ». Quelques critères discriminants :
- User agent : Terraform et les bibliothèques clientes portent des chaînes versionnées ; une CLI gcloud sous Linux en
interactive/Truedepuis un VPS n'est pas votre pipeline. - Horaires : la CI tourne sur des commits et des planifications ; une session d'attaquant est une rafale dense à une heure inhabituelle.
- Erreurs : un pipeline rencontre rarement des dizaines d'appels refusés en quelques minutes ; une énumération, si.
- Méthodes : un pipeline répète les mêmes méthodes ; un attaquant appelle
GetIamPolicysur l'organisation, liste les secrets, la facturation et les configurations de notification de Security Command Center.
Étape 4 : suivre l'IP de l'attaquant, pas seulement la clé
Une fois l'IP de l'attaquant connue, retirez le filtre sur la clé et cherchez l'IP seule :
protoPayload.requestMetadata.callerIp="203.0.113.66"
Les attaquants changent d'identité dès qu'ils le peuvent : ils accordent Owner à un compte qu'ils contrôlent (souvent une adresse Gmail) et continuent sous ce compte depuis la même machine. L'IP relie les deux phases. Voir l'abus de SetIamPolicy pour la seconde phase, et l'emprunt d'identité de comptes de service si la clé a servi à émettre des jetons pour d'autres comptes de service.
Étape 5 : contenir dans le bon ordre
Le guide de Google pour les identifiants compromis et la page désactiver et activer des clés décrivent la mécanique. L'ordre que j'applique :
- Désactiver la clé (réversible, immédiat). Si le compte de service lui-même est compromis au-delà de la clé, désactiver le compte de service.
- Retirer ce que l'attaquant a ajouté avec : liaisons IAM, clés, comptes de service, clés HMAC.
- Déployer un identifiant de remplacement pour la charge de travail légitime, de préférence pas une clé : la fédération d'identité de charge de travail pour la CI.
- Supprimer l'ancienne clé une fois que l'enquête a tout consigné à son sujet.
- Considérer comme exposé tout ce que le compte de service pouvait lire : secrets, buckets, jeux de données. Renouveler ces secrets.
Traitez ensuite la cause : purgez le fichier de l'historique du dépôt et des logs de CI, et cherchez d'autres copies.
La prévention qui fonctionne vraiment
- Règle d'administration
iam.disableServiceAccountKeyCreation: plus de nouvelles clés gérées par l'utilisateur. iam.serviceAccountKeyExposureResponseréglée surDISABLE_KEY: Google détecte les clés exposées dans des lieux publics et les désactive, en prévenant propriétaires et contacts de sécurité (blog Google Cloud).- Une expiration pour les clés inévitables, et un inventaire de celles qui restent.
Ce que l'analyseur signale
Sur un export déposé dans l'analyseur, l'histoire d'une clé produit jusqu'à cinq constats :
| Règle | Sévérité | Se déclenche quand |
|---|---|---|
sa_key_created | Moyenne | CreateServiceAccountKey a réussi |
sa_key_uploaded | Haute | UploadServiceAccountKey a réussi |
sa_key_used_external | Moyenne | Un compte de service s'est authentifié avec une clé gérée par l'utilisateur depuis une IP publique (quel que soit le résultat) |
sa_key_new_ip | Haute | Une clé a été utilisée depuis une IP publique autre que la première vue pour elle dans les journaux |
permission_denied_burst | Moyenne | 20 appels refusés pour un même principal en 10 minutes |
L'onglet Entités liste chaque clé avec son créateur et toutes les IP qui l'ont utilisée. Une limite à garder en tête : « nouvelle IP » est relatif à l'export. Si l'export commence après la première utilisation par l'attaquant, l'IP de l'attaquant devient la référence. Exportez une période plus longue quand c'est possible.
Questions fréquentes
Comment savoir si une clé de compte de service divulguée a été utilisée ?
Cherchez dans les journaux d'audit protoPayload.authenticationInfo.serviceAccountKeyName se terminant par l'ID de la clé. Chaque appel effectué avec la clé le porte. Des appels depuis des adresses IP que vous ne reconnaissez pas, surtout après la date de la fuite, signifient que quelqu'un d'autre a utilisé la clé.
Google désactive-t-il automatiquement les clés de compte de service divulguées ?
Google analyse les dépôts publics à la recherche de clés exposées. Avec la règle d'administration iam.serviceAccountKeyExposureResponse réglée sur DISABLE_KEY, les clés détectées sont désactivées automatiquement et les propriétaires du projet ainsi que les contacts de sécurité sont prévenus.
Faut-il supprimer la clé immédiatement ?
Désactivez-la d'abord : la désactivation est réversible et arrête l'attaquant. Consignez l'ID de la clé et les détails de sa création, puis supprimez-la quand l'enquête n'en a plus besoin et que les charges de travail légitimes disposent d'un remplacement.
Pour aller plus loin
- Bonnes pratiques de gestion des clés de compte de service — documentation Google Cloud.
- MITRE ATT&CK T1078.004, Valid Accounts: Cloud Accounts.
- MITRE ATT&CK T1552.001, Unsecured Credentials: Credentials In Files — comment les fichiers de clé fuient.
- Réponse à incident Google Cloud : projet compromis.