Clés cloud fuitées dans GitHub Actions : le pivot cloud
Clés AWS, Google Cloud ou Azure fuitées depuis GitHub Actions ou un dépôt : désactivez la clé, tracez-la dans les logs d'audit cloud, puis passez à OIDC.
En bref. Dès qu'une clé cloud sort de GitHub (affichée par un workflow, clonée avec l'historique d'un dépôt, détectée par le secret scanning), l'enquête GitHub devient une enquête cloud. Désactivez la clé, mais notez d'abord son identifiant et la fenêtre temporelle exacte. Recherchez dans les logs propres au cloud chaque appel effectué avec elle : CloudTrail pour AWS, Cloud Audit Logs pour Google Cloud, Activity log et logs de connexion Entra ID pour Azure. Remplacez les clés stockées par une fédération OIDC, afin que la prochaine compromission de workflow ne rapporte qu'un jeton à durée de vie courte et au périmètre étroit.
GitHub est rarement la cible finale de l'attaquant. Les dépôts et les secrets Actions contiennent les identifiants des systèmes qui comptent vraiment : comptes cloud de production, registres et bases de données. L'analyseur signale ce passage de relais comme un rebond suivant. Lorsque la règle actions-secret-exfil repère des noms d'identifiants AWS, Google Cloud ou Azure dans un script qui encode ou expédie des secrets, ou lorsqu'une alerte de secret scanning concerne un identifiant cloud, le résultat renvoie vers l'outil cloud correspondant.
D'où fuient les clés cloud sur GitHub
| Source | Preuves côté GitHub | Traité dans |
|---|---|---|
| Un workflow affiche ou envoie des secrets | Archive des logs d'exécution : encodeur ou curl dans le script de l'étape, longue chaîne encodée dans la sortie | Fuite de secrets Actions |
| Clé commitée dans un dépôt, puis clonée | Rafales de git.clone, alerte de secret scanning, contournement de la push protection | Exfiltration de dépôts |
| Protection d'environnement supprimée | environment.remove_protection_rule avant une exécution qui a utilisé l'environnement | Altération de la protection de branche |
| Runner auto-hébergé compromis | Hôte du runner doté d'un rôle d'instance ou d'identifiants CLI en cache | Sécurité des runners auto-hébergés |
Les alertes de secret scanning (secret_scanning_alert.create, secret_scanning_alert.public_leak) et les contournements de la push protection (secret_scanning_push_protection.bypass) sont signalés par les règles secret-leak-alert et push-protection-bypass. Déposez le JSON des alertes de secret scanning de l'organisation à côté du journal d'audit pour les inclure.
D'abord : identifier la clé et la fenêtre
Avant tout renouvellement, consignez :
- L'identifiant de la clé. Pour AWS, l'access key ID (
AKIA…pour les clés utilisateur de longue durée,ASIA…pour les identifiants temporaires). Pour Google Cloud, l'e-mail du compte de service et l'identifiant de clé présent dans le JSON. Pour Azure, l'identifiant d'application (client) du service principal et l'identifiant du secret ou du certificat. - Le début de l'exposition. L'heure de l'exécution ou du push malveillant, du clonage ou de l'alerte. Le constat de l'analyseur donne l'heure de première observation en UTC.
- Où elle était valide. Quel compte, projet ou abonnement, et avec quelles permissions.
Désactivez ou supprimez ensuite la clé. Sur AWS, désactiver une clé d'accès permet de la réactiver si la production casse. Une fois confirmé que plus rien de légitime n'en dépend, supprimez-la.
AWS : CloudTrail
Recherchez l'access key ID dans CloudTrail à partir du début de l'exposition. L'historique des événements et CloudTrail Lake permettent de filtrer sur la clé d'accès. Cherchez :
- les vérifications d'identité que les attaquants lancent généralement en premier (
GetCallerIdentity), suivies d'une énumération (List*,Describe*,Get*en rafales) ; - des appels depuis des adresses IP et des user agents qui ne correspondent pas à votre CI (les runners hébergés par GitHub proviennent des plages publiées par GitHub ; un
aws-clide poste de travail depuis un VPS, ce n'est pas eux) ; - de la persistance :
CreateUser,CreateAccessKey,CreateLoginProfile,AttachUserPolicy, nouveaux rôles ou modifications de trust policy ; - des accès aux données :
GetObjectS3 en volume, lectures dans Secrets Manager ou SSM Parameter Store.
L'outil voisin AWS Forensics analyse les exports CloudTrail de la même manière que ce site analyse GitHub : dans le navigateur, sans rien envoyer.
Google Cloud : Cloud Audit Logs
Pour une clé de compte de service fuitée, filtrez les Cloud Audit Logs avec le compte de service comme principal et examinez les logs Admin Activity et, s'ils sont activés, les logs Data Access. Surveillez les nouvelles clés de compte de service, les liaisons de stratégie IAM, et les accès à Cloud Storage ou Secret Manager. Poursuivez avec GCP Forensics.
Azure : Activity log et Entra ID
Pour un secret de service principal, consultez les logs de connexion des service principals dans Entra ID pour l'identifiant d'application, puis l'Activity log pour voir ce qu'il a modifié : attributions de rôles, nouveaux identifiants sur des applications et accès à Key Vault. Poursuivez avec Azure Forensics.
Remplacer les clés par une fédération OIDC
La plupart de ces incidents existent parce qu'une clé de longue durée est stockée dans un secret GitHub. GitHub Actions peut demander un jeton OIDC à courte durée de vie pour chaque job, et AWS, Google Cloud et Azure peuvent lui faire confiance directement. Consultez la documentation OpenID Connect de GitHub et l'entrée du glossaire sur la fédération OIDC. La référence d'utilisation sécurisée de GitHub la recommande pour les déploiements cloud.
Ce qui change pour un attaquant :
| Clé d'accès stockée | Fédération OIDC | |
|---|---|---|
| Durée de vie | Jusqu'à ce que quelqu'un la renouvelle | De quelques minutes à une heure (session côté cloud) |
| Utilisable hors du workflow | Oui, depuis n'importe où | Seulement jusqu'à son expiration |
| Périmètre | Tout ce que possède l'utilisateur de la clé | Un rôle dont la trust policy peut exiger un dépôt, une branche ou un environnement précis (claim sub) |
| Visible dans les logs | Identifiant de clé | Session de rôle liée aux claims GitHub |
OIDC n'est pas une panacée. Un workflow piégé qui s'exécute sur une branche autorisée obtient toujours un jeton valide pendant l'exécution. Mais la fenêtre passe de « jusqu'au renouvellement » à « pendant l'exécution du job », et des conditions de confiance comme repo:ORG/REPO:environment:production bloquent les jetons demandés depuis des branches de l'attaquant.
Checklist
- Consignez l'identifiant de la clé, le compte et la fenêtre d'exposition. Désactivez ensuite la clé.
- Récupérez les logs cloud de la fenêtre. Cherchez les vérifications d'identité, l'énumération, la persistance et les accès aux données.
- Renouvelez tous les autres secrets que le même workflow pouvait lire (voir l'article sur Actions).
- Supprimez ce que l'attaquant a créé dans le cloud : utilisateurs, clés, rôles, fonctions, instances.
- Passez les déploiements sur OIDC avec des conditions de confiance portant sur le dépôt et l'environnement.
À lire aussi
- Organisation GitHub compromise ? Guide de réponse à incident
- Le scénario fictif northwind-labs pas à pas : une paire de clés AWS affichée en double base64
- MITRE ATT&CK T1552.001 Credentials In Files