Clé d'accès AWS divulguée : comment mener l'enquête
Une clé d'accès AWS a fuité : désactivez-la, puis retrouvez dans CloudTrail où elle a servi, ce qu'elle a énuméré, ce qu'elle a créé et les données exposées.
En bref. 1) Désactivez la clé (aws iam update-access-key --status Inactive), ne la supprimez pas encore. 2) Récupérez tous les événements CloudTrail où userIdentity.accessKeyId correspond à la clé, depuis bien avant la fuite jusqu'à maintenant. 3) Trouvez la première utilisation depuis une nouvelle IP : c'est l'entrée de l'attaquant. 4) À partir de là, listez ce que la clé a énuméré, ce qu'elle a créé (utilisateurs, clés, mots de passe, politiques, instances) et quelles données elle pouvait lire. 5) Pivotez sur l'IP de l'attaquant pour repérer d'autres identifiants. Remédiez à tout ce que la clé a créé, pas seulement à la clé elle-même.
Les clés d'accès à long terme, celles dont l'identifiant commence par AKIA (référence des identifiants IAM), n'expirent pas. Quand l'une d'elles atterrit dans un dépôt public, un log de CI, une couche d'image Docker ou un ticket de support copié-collé, celui qui la trouve dispose des permissions de son utilisateur jusqu'à ce que quelqu'un s'en aperçoive. L'enquête consiste à répondre à la question « qu'en a-t-il fait ? » avec assez de précision pour tout défaire.
Étape 0 : désactiver, pas supprimer
aws iam update-access-key --user-name <user> --access-key-id AKIA... --status Inactive
Une clé inactive ne peut plus s'authentifier. La conserver (inactive) plutôt que la supprimer permet de garder son identifiant visible dans IAM et dans le rapport d'identifiants pendant l'investigation. Avant de la désactiver, identifiez ce qui l'utilise légitimement : un job de production qui tombe à 3 heures du matin est un prix qu'il vaut mieux connaître à l'avance, pas une raison d'attendre.
Vérifiez si AWS a déjà réagi : si l'utilisateur a la politique AWSCompromisedKeyQuarantineV3 attachée, AWS a détecté l'exposition et ouvert un dossier de support. Cette politique interdit une liste d'actions à haut risque (iam:CreateUser, iam:CreateAccessKey, ec2:RunInstances et d'autres) ; un attaquant qui a agi avant qu'elle soit attachée a très bien pu réussir.
Si la clé a fuité depuis un dépôt GitHub, la piste d'audit du dépôt lui-même (qui l'a poussée, quand, si le dépôt était public) relève d'une investigation distincte ; githubforensics.com couvre ce volet.
Étape 1 : obtenir l'historique complet de la clé
Avec un trail, filtrez les fichiers exportés sur la clé. Avec jq sur un dossier de fichiers décompressés :
zcat cloudtrail/**/*.json.gz | jq -c '.Records[]
| select(.userIdentity.accessKeyId == "AKIA...")
| [.eventTime, .sourceIPAddress, .eventSource, .eventName, (.errorCode // "")]'
Sans trail, l'historique des événements permet une recherche par clé (région par région) :
aws cloudtrail lookup-events --region us-east-1 \
--lookup-attributes AttributeKey=AccessKeyId,AttributeValue=AKIA...
Les colonnes access_key_1_last_used_date, _region et _service du rapport d'identifiants offrent une vérification rapide, mais elles n'enregistrent que la première utilisation de chaque tranche de 15 minutes (documentation IAM). CloudTrail reste la source qui fait foi.
Étape 2 : trouver la première utilisation malveillante
Regroupez les événements de la clé par sourceIPAddress et userAgent. L'usage légitime forme des grappes : l'IP de sortie du bureau, la plage d'un runner de CI, la version de CLI du développeur. L'attaquant se signale par :
- une nouvelle adresse (souvent un VPS ou un hébergeur),
- un user agent différent : un autre système d'exploitation, un SDK plus ancien, parfois un indice flagrant comme une chaîne de build Kali,
- un appel
GetCallerIdentitycomme toute première requête. Il ne nécessite aucune permission (référence de l'API STS) : c'est donc la vérification universelle « cette clé fonctionne-t-elle, et à qui appartient-elle ? ».
La détection « Clé d'accès à long terme utilisée depuis une nouvelle adresse IP » de l'analyseur automatise ce travail : elle apprend les adresses de la clé pendant sa première journée dans les journaux et signale toute utilisation ultérieure depuis une adresse publique hors de cet ensemble. Sa pertinence dépend de la référence : chargez donc quelques jours antérieurs à la fuite présumée.
Étape 3 : qu'a-t-elle énuméré ?
Les attaquants cartographient les permissions très vite. Dans CloudTrail, cela se traduit par une rafale de dizaines d'appels List*, Describe* et Get* différents sur IAM, S3, EC2, Lambda, Secrets Manager et d'autres, en quelques minutes, souvent mêlés d'erreurs AccessDenied là où la clé n'a pas les droits. GetAccountAuthorizationDetails est une cible de choix : il renvoie en un seul appel tous les utilisateurs, rôles, groupes et politiques.
| Schéma | Preuve | ATT&CK |
|---|---|---|
| Vérification de validité de la clé | sts:GetCallerIdentity depuis une nouvelle IP | T1087.004 |
| Énumération des services | Plus de 30 List/Describe/Get distincts en 10 min | T1580, T1526 |
| Sondage des permissions | Rafale d'AccessDenied / UnauthorizedOperation | T1069.003 |
| Outils offensifs | userAgent contenant Kali, Pacu, CloudFox… | T1078.004 |
Les appels en échec comptent : ils montrent ce que l'attaquant voulait, ce qui vous indique quoi protéger ensuite.
Étape 4 : qu'a-t-elle créé ?
C'est là que les investigations échouent le plus souvent. Recherchez chaque écriture réussie :
CreateUser,CreateLoginProfile,CreateAccessKey(surtout pour un autre utilisateur),AttachUserPolicy/PutUserPolicyavec des droits administrateur ;UpdateAssumeRolePolicy,CreateSAMLProvider,CreateOpenIDConnectProvider;RunInstances,CreateKeyPair,ImportKeyPair,AuthorizeSecurityGroupIngress;CreateFunction,AddPermission,CreateFunctionUrlConfig.
Les responseElements de CreateAccessKey contiennent l'identifiant de la nouvelle clé : c'est votre prochain pivot. L'article sur la persistance IAM et l'élévation de privilèges décrit chacune de ces techniques.
Étape 5 : à quelles données a-t-elle pu accéder ?
Les événements de gestion montrent ListBuckets et GetBucketPolicy, pas les lectures d'objets. Pour savoir si des objets ont été téléchargés, il vous faut les événements de données S3 ou les journaux d'accès serveur ; voir les preuves d'exfiltration de données S3. Vérifiez aussi GetSecretValue, GetParametersByPath, ModifySnapshotAttribute (partage d'un snapshot avec un autre compte) et GetPasswordData.
Étape 6 : pivoter sur l'IP de l'attaquant
Pivotez sur chaque adresse de l'attaquant, tous principaux confondus. Vous trouverez souvent la nouvelle clé de l'utilisateur servant de porte dérobée, une connexion console d'un utilisateur créé, ou une session de rôle assumé : autant d'activités qui ne portent plus l'identifiant de la clé divulguée.
Checklist de remédiation pour une clé divulguée
- Clé divulguée : inactive tout de suite, supprimée après délimitation du périmètre ; retirez-la du code, des variables de CI, des images et de l'historique.
- Chaque clé créée pendant l'incident : désactivez-la puis supprimez-la.
- Utilisateurs, profils de connexion, appartenances à des groupes et politiques créés ou attachés par l'attaquant : sauvegardez-les, puis retirez-les.
- Politiques d'approbation de rôle et fournisseurs d'identité modifiés : rétablissez-les.
- Instances, paires de clés, règles de groupe de sécurité, fonctions Lambda dans toutes les régions : snapshot si nécessaire, puis suppression.
- Secrets lus par l'attaquant : faites-les tourner.
- Services de journalisation et de détection désactivés : réactivez-les (article sur le contournement des défenses).
Déposez l'historique CloudTrail de la clé dans l'analyseur pour obtenir cette liste pré-remplie avec les identifiants de clés, les utilisateurs et les régions réellement présents dans vos journaux. Pour la vue à l'échelle du compte, revenez à la vue d'ensemble de la réponse à incident AWS.
FAQ
Peut-on voir quelles adresses IP ont utilisé une clé d'accès AWS divulguée ?
Oui. Chaque événement CloudTrail signé avec la clé la porte dans userIdentity.accessKeyId, et l'adresse de l'appelant dans sourceIPAddress. Filtrez sur la clé et listez les adresses distinctes ; si vous n'avez pas de trail, l'historique des événements couvre les 90 derniers jours d'événements de gestion.
Un appel GetCallerIdentity prouve-t-il qu'une clé a été volée ?
Non. L'AWS CLI et les SDK l'appellent couramment, et il ne nécessite aucune permission. Il devient significatif lorsqu'il s'agit du premier appel depuis une adresse que la clé n'a jamais utilisée, surtout si une énumération suit dans les minutes qui viennent.
Désactiver la clé suffit-il à arrêter l'attaquant ?
Cela neutralise cette clé-là. Cela ne neutralise pas les identifiants que l'attaquant a créés avec elle : autres clés d'accès, mots de passe console, utilisateurs, relations d'approbation de rôle modifiées. On les retrouve en délimitant l'activité de la clé dans CloudTrail.