Comment trouver l’ID de compte AWS d’un bucket S3
(tracebit.com)- Tracebit présente une technique pour déduire l’ID de compte AWS de buckets S3 publics comme privés, et reconstitue
123456789101pour le bucket d’exemplebucket-alpha - L’indice clé repose sur la condition
s3:ResourceAccountdes politiques d’Interface VPC Endpoint pour S3, ainsi que sur le fait qu’une requête apparaisse ou non dans ses propres journaux CloudTrail - Pour un bucket privé, même si la réponse finale reste toujours
AccessDenied, seules les requêtes ayant passé la politique du VPC Endpoint apparaissent dans CloudTrail, ce qui permet de déterminer si un motif numérique correspond - À cause de la propagation des politiques et de la latence de CloudTrail, une exploration simple peut prendre jusqu’à environ
40 * 12 minutes = 8 heures, mais un test parallèle de 120 instructions de politique utilisantaws:useridetRoleSessionNameramène cela à moins de 10 minutes - Cette technique est possible parce que
StringLikeautorise une correspondance partielle surs3:ResourceAccount, et certaines activités peuvent aussi apparaître dans le CloudTrail du propriétaire du bucket
Extension d’une technique initialement conçue pour les buckets publics
- En 2021, Ben Bridts a publié Comment trouver l’ID de compte AWS de n’importe quel bucket S3 public
- L’approche de Tracebit réutilise plusieurs éléments de cette idée, mais se concentre sur la découverte de l’ID de compte de buckets S3, y compris privés
- Dans l’exemple d’exécution, les noms de session ayant passé dans CloudTrail pour
bucket-alphasont collectés afin de reconstituer finalement123456789101
Pourquoi la méthode existante pour les buckets publics fonctionne
- La méthode de Ben Bridts fonctionne grâce à la combinaison de trois conditions
- Il est possible d’appliquer une politique IAM à la requête
- Il est possible de déduire si la politique a autorisé ou bloqué la requête
- Il est possible d’appliquer une correspondance par caractères génériques à la clé de condition
s3:ResourceAccount
- Avec un bucket public, si la politique bloque la requête, on obtient
AccessDenied, et si elle l’autorise, la requête réussit, ce qui permet de distinguer facilement si la politique a été franchie - En affinant
s3:ResourceAccountchiffre par chiffre, l’espace de recherche passe de plusieurs milliers de milliards de possibilités à seulement quelques centaines
Pour les buckets privés, on regarde CloudTrail au lieu de la réponse
- Pour un bucket privé, quelle que soit la politique appliquée, la réponse finale sera AccessDenied à cause de la politique du bucket cible
- L’approche de Tracebit ne se base donc pas sur le résultat de la réponse, mais sur l’apparition ou non de la requête dans ses propres journaux CloudTrail
- Si la requête apparaît dans CloudTrail, la politique du VPC Endpoint l’a autorisée, puis la politique du bucket l’a rejetée ensuite
- Si la requête n’apparaît pas dans CloudTrail, elle a été bloquée par la politique du VPC Endpoint
- En créant un Interface VPC Endpoint pour S3, il devient possible d’appliquer une politique de VPC Endpoint aux requêtes, politique qui est évaluée avec d’autres politiques comme celle du bucket et les politiques IAM du principal de la requête
- La politique du VPC Endpoint peut elle aussi utiliser les jokers
StringLikeet des clés de condition de ressource, ce qui permet la même stratégie d’exploration
Procédure de base : de l’identification de la région à la consultation des événements
- Il faut d’abord trouver la région du bucket cible
- En envoyant un
curlvers l’endpoint HTTP du bucket, l’en-têtex-amz-bucket-regionest renvoyé même si la requête est interdite - Dans l’exemple, la réponse de
bucket-alpha.s3.amazonaws.compermet de confirmerus-east-1
- En envoyant un
- Un VPC et un VPC Endpoint pour S3 sont ensuite déployés dans la même région que le bucket cible
- Le VPC Endpoint doit être de type Interface, afin qu’une politique puisse lui être appliquée
- Comme ce VPC Endpoint influence les requêtes S3 du VPC, il est préférable de créer un VPC dédié à cet usage
- Une instance EC2 est lancée dans le VPC pour envoyer des requêtes S3, en vérifiant qu’elle utilise bien le VPC Endpoint pour S3
- La politique du VPC Endpoint est modifiée pour tester si
s3:ResourceAccountcommence par un chiffre donné- Par exemple, pour vérifier si l’ID de compte commence par
0, on applique la condition"0*"às3:ResourceAccount
- Par exemple, pour vérifier si l’ID de compte commence par
- Depuis l’instance EC2, une requête de gestion comme
GetBucketAclest envoyée au bucket cible- Utiliser une requête de gestion évite d’avoir à faire des réglages supplémentaires dans la configuration de CloudTrail
- Le résultat de la requête est, comme prévu,
AccessDenied
Comment CloudTrail permet de valider un motif numérique
- Après la requête, il faut vérifier dans CloudTrail si un événement
GetBucketAclapparaît - Si l’événement apparaît, cela signifie que la politique du VPC Endpoint a autorisé la requête, donc que l’ID de compte correspond au motif testé
- Exemple : si un événement apparaît avec la condition
"0*", l’ID de compte commence par0
- Exemple : si un événement apparaît avec la condition
- Si aucun événement n’apparaît, cela signifie que la politique du VPC Endpoint a bloqué la requête, donc que le motif ne correspond pas
- Comme plusieurs minutes peuvent s’écouler avant qu’un événement apparaisse dans CloudTrail, il est recommandé d’attendre 10 minutes avant de conclure à l’absence d’événement
- Les changements de politique du VPC Endpoint demandent eux aussi du temps pour être complètement propagés et appliqués ; attendre 5 minutes après une modification fonctionne bien
Automatisée, mais la méthode de base reste lente
- Tracebit a écrit un script pour automatiser ce processus et retrouver de façon fiable l’ID de compte du bucket
- Au lieu de tester simplement tous les chiffres un par un, la méthode réduit le nombre d’essais à chaque position avec une approche proche d’une recherche binaire
- Par exemple, en mettant plusieurs motifs dans la condition
s3:ResourceAccount, comme["0*", "1*", "2*", "3*", "4*"], on découpe l’espace en plages
- Par exemple, en mettant plusieurs motifs dans la condition
- Malgré cela, le temps d’application des politiques et l’attente de vérification dans CloudTrail restent le principal goulet d’étranglement
- Même avec une recherche binaire, cela peut encore prendre environ
40 * 12 minutes = 8 heures
- Même avec une recherche binaire, cela peut encore prendre environ
- Dans un exemple exécuté sur plusieurs heures, l’ID de compte de
bucket-alphaa bien été retrouvé comme étant123456789101
Moins de 10 minutes grâce à 120 instructions de politique
- Une méthode plus rapide consiste à préremplir la politique du VPC Endpoint avec toutes les combinaisons possibles de position et de chiffre
- La politique contient au total 120 instructions
- Les 10 chiffres possibles sont testés pour chaque position d’un ID de compte AWS
- Chaque instruction combine un motif de position spécifique sur
s3:ResourceAccountavec une conditionaws:userid
- La condition
aws:useridsert à faire correspondre la valeurRoleSessionName, qui peut être librement définie lors d’un appel STSAssumeRole- En assumant un rôle avec un
RoleSessionNameprécis, il devient possible de ne faire passer sélectivement que l’instruction de politique correspondant à un test position/chiffre donné
- En assumant un rôle avec un
- Cette politique tient tout juste dans la longueur maximale autorisée pour une politique de VPC Endpoint
- Comme les 120 possibilités sont testées en parallèle, il n’est plus nécessaire de modifier la politique à chaque fois ni d’attendre individuellement les résultats de CloudTrail
- Avec cette méthode, le temps de recherche de l’ID de compte passe à moins de 10 minutes
Portée de l’exposition et possibilités d’extension
- Certaines activités peuvent apparaître dans les journaux CloudTrail du propriétaire du bucket cible
- Tracebit indique avoir consulté l’équipe AWS Security avant publication
- Le caractère sensible ou non d’un ID de compte AWS a déjà fait l’objet de nombreux débats, et dans l’exemple d’événement CloudTrail, l’ID de compte tiers est masqué par
HIDDEN_DUE_TO_SECURITY_REASONS - La même technique peut s’appliquer à d’autres clés de condition de ressource liées au bucket
- Ex. :
aws:ResourceOrgID - Ex. :
aws:ResourceOrgPaths - Ex. :
aws:ResourceTag
- Ex. :
- Elle pourrait aussi être adaptée à d’autres services que S3
- En créant des VPC et VPC Endpoint interconnectés dans toutes les régions, il serait peut-être possible de construire une configuration fonctionnant quelle que soit la région du bucket cible
- Cette technique est possible parce qu’une correspondance partielle StringLike peut être utilisée sur la condition
s3:ResourceAccount - Il pourrait être utile que les événements rejetés par la politique du VPC Endpoint soient eux aussi enregistrés dans CloudTrail
1 commentaires
Commentaires sur Hacker News
C’est vraiment étrange que l’on puisse appliquer une correspondance par joker à la clé de condition s3:ResourceAccount.
Je ne vois aucune raison légitime d’autoriser ou de refuser des permissions sur la base d’une correspondance partielle de l’ID de compte.
StringLikesur la chaîne de l’ID de compte.C’est assez intéressant de voir que le monde DevOps commence maintenant à découvrir des attaques par canal auxiliaire. Les canaux auxiliaires liés à l’exécution spéculative des CPU, comme Meltdown et Spectre, avaient aussi fait beaucoup de bruit lors de leur découverte ; avant cela, il y avait déjà des domaines comme l’analyse de consommation, la détection par distorsion magnétique et la cryptographie en temps constant.
https://en.m.wikipedia.org/wiki/Side-channel_attack
https://en.m.wikipedia.org/wiki/Power_analysis
Dans un side project récent, j’ai créé une fonctionnalité pour écrire des requêtes dans un format inspiré d’OWL, avec une bibliothèque d’opérateurs relationnels permettant d’extraire l’hôte d’une URL, de faire des requêtes par préfixe, des requêtes
like, des requêtes par expression régulière, etc.Comme c’était un side project d’un autre side project, j’ai fait au plus simple et j’ai laissé les opérateurs toujours disponibles, même dans les cas où cela n’a pas de sens. Je ne sais pas ce que donne une requête par expression régulière sur un nombre, et je ne m’en soucie pas. Il peut y avoir quelque chose de similaire en interne chez AWS, mais pour un système avec beaucoup d’utilisateurs et sensible en matière de sécurité, les exigences devraient être différentes.
Quelqu’un peut avoir cette idée et la trouver intelligente, mais l’implémenter dans un système que l’on ne contrôle pas à 100 % semble idiot.
En général, on ne diffuse pas publiquement un ID de compte, mais il faut partir du principe qu’une partie finira un jour par fuiter.
De plus en plus de fournisseurs tiers et de plateformes SaaS passent à des intégrations qui privilégient la délégation de rôle plutôt que les utilisateurs IAM et les clés d’accès, et c’est ce qu’il faut faire. Dans ce cas, au minimum, l’ID du compte utilisé comme point d’intégration est communiqué à d’autres parties, lesquelles ont aussi leurs dépendances, vulnérabilités, etc.
Un ID de compte AWS ressemble à une adresse IP. Il peut être sensible, mais pour travailler, quelqu’un doit le connaître.
Par exemple, il y a un an ou deux, nous devions intégrer un tiers pour des procédures de lutte contre le blanchiment. Nous leur avons proposé de mettre en place PrivateLink avec cette organisation, puisque c’est généralement plus sûr qu’un port SFTP public. L’entreprise en face a refusé pour des raisons de sécurité, au motif qu’elle devait cacher son ID de compte, alors même qu’il était nécessaire dans l’ARN du rôle du point de terminaison PV pour les permissions mutuelles.
Au final, nous avons mis sur liste blanche la plage d’IP publiques qu’ils utilisaient sur le port entrant 22.
La leçon, c’est qu’on peut penser être malin en obscurcissant un ID, mais il est difficile de faire tourner une activité si l’autre partie ne connaît pas l’adresse à laquelle répondre.
Du point de vue d’un fournisseur, nous nous intégrons généralement via un VPC Endpoint Service. Avec cette approche, la communication est unidirectionnelle, et notre service est exposé comme endpoint de load balancer dans le VPC du client.
Pour les personnes intéressées, j’ai publié le code ici : https://github.com/tracebit-com/find-s3-account
C’est bien une découverte intéressante, mais au vu du titre, je pensais qu’il existait une méthode plus directe.
Ce serait bien, avec un compte administrateur AWS, de pouvoir simplement demander au sein d’une organisation « où se trouve la ressource X » et de savoir rapidement dans quel compte se trouve un bucket S3 donné. C’est vrai aussi pour d’autres ressources, mais les buckets S3 sont particulièrement concernés.
Honnêtement, c’est surtout un problème avec des buckets legacy datant d’avant l’arrivée de meilleures pratiques, ou avec des buckets qui existaient avant que tout soit défini sous forme de code. Cela dit, quand on a beaucoup de comptes AWS, chercher des ressources dans des comptes et des régions inconnus peut devenir fastidieux.
Trouver quel compte possède une ressource revient alors à peu près à faire
select accountId where arn = "x".D’autres ressources AWS publiques avec un espace de noms global révèlent aussi l’ID de compte AWS.
https://blog.plerion.com/conditional-love-for-aws-metadata-e...
À ce propos, les Cloudflare account_id et zone_id peuvent être rendus publics sans risque
https://github.com/cloudflare/cloudflare-docs/issues/474
https://community.cloudflare.com/t/api-zone-id/355566
Cela dit, l’une des choses qu’on peut faire avec est d’établir des corrélations. Si plusieurs sites S3 sont exploités depuis le même compte AWS, les gens peuvent voir qu’ils sont hébergés par le même compte. L’importance de ce point dépend du modèle de menace
Ce n’est pas parfait, mais cela ajoute une couche d’abstraction
Dans le même ordre d’idées, l’ID de clé AWS, même sans la partie clé secrète, contient l’ID de compte sous une forme décalée d’un bit
https://medium.com/@TalBeerySec/a-short-note-on-aws-key-id-f...
Cet ID de clé étant inclus dans les URL présignées S3, il y a de fortes chances que l’ID de compte ait déjà été exposé
Je vais probablement me faire downvoter, mais si quelqu’un lit quand même ceci, c’est un exemple de pourquoi la sécurité par l’obscurité n’est pas une bonne défense. Vous finirez par rater quelque chose, alors qu’un attaquant déterminé ne le ratera pas
Une sécurité qui ne repose pas sur l’obscurité s’applique indépendamment de ce que j’ai compris ou non, sauf si l’attaquant embauche, par exemple, un génie capable de casser AES-256 comme ça : https://www.youtube.com/watch?v=KEkrWRHCDQU
Pourquoi cela peut-il être important ? Pour donner un exemple clair, à partir d’un bucket de production, il devient désormais possible de trouver les buckets de développement de la même organisation. Personnellement, ce n’est pas le comportement auquel je m’attendais
Pour empêcher ce type de tentative d’énumération, il faut ajouter au nom du bucket un préfixe ou un suffixe généré aléatoirement. En complément, et non comme substitut, il est aussi préférable d’exposer les objets du bucket sous un nom autre que le nom d’hôte par défaut, afin d’éviter de divulguer le nom du bucket lui-même
Par exemple, mon adresse postale est techniquement une information publique, mais je ne voudrais absolument pas qu’elle apparaisse sur un panneau publicitaire au bord de l’autoroute avec des photos de ma famille, indiquant que c’est là que j’habite. Je la donne seulement aux personnes qui en ont besoin, et je crois et j’attends généralement qu’elle reste proche du confidentiel ou qu’elle soit limitée à certains usages
Si ce n’est ni secret, ni sensible, ni confidentiel, pourquoi faut-il le partager avec prudence ?
Les utilisateurs peuvent voir les choses autrement