2 points par GN⁺ 2024-02-27 | 1 commentaires | Partager sur WhatsApp
  • Tracebit présente une technique pour déduire l’ID de compte AWS de buckets S3 publics comme privés, et reconstitue 123456789101 pour le bucket d’exemple bucket-alpha
  • L’indice clé repose sur la condition s3:ResourceAccount des 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 utilisant aws:userid et RoleSessionName ramène cela à moins de 10 minutes
  • Cette technique est possible parce que StringLike autorise une correspondance partielle sur s3: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-alpha sont collectés afin de reconstituer finalement 123456789101

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:ResourceAccount chiffre 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 StringLike et 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 curl vers l’endpoint HTTP du bucket, l’en-tête x-amz-bucket-region est renvoyé même si la requête est interdite
    • Dans l’exemple, la réponse de bucket-alpha.s3.amazonaws.com permet de confirmer us-east-1
  • 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:ResourceAccount commence par un chiffre donné
    • Par exemple, pour vérifier si l’ID de compte commence par 0, on applique la condition "0*" à s3:ResourceAccount
  • Depuis l’instance EC2, une requête de gestion comme GetBucketAcl est 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 GetBucketAcl apparaî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 par 0
  • 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
  • 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
  • Dans un exemple exécuté sur plusieurs heures, l’ID de compte de bucket-alpha a bien été retrouvé comme étant 123456789101

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:ResourceAccount avec une condition aws:userid
  • La condition aws:userid sert à faire correspondre la valeur RoleSessionName, qui peut être librement définie lors d’un appel STS AssumeRole
    • En assumant un rôle avec un RoleSessionName précis, il devient possible de ne faire passer sélectivement que l’instruction de politique correspondant à un test position/chiffre donné
  • 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
  • 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

 
GN⁺ 2024-02-27
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.

    • L’exécution des politiques AWS repose sur plusieurs opérateurs et opérandes ; dans ce cas, il semble que la structure consiste à utiliser StringLike sur 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
    • Cette partie m’a aussi surpris. Ce champ ne devrait probablement autoriser qu’une correspondance exacte, et je ne vois aucun cas d’usage pour faire du pattern matching sur un ID de compte.
    • Cela vient probablement d’une tendance à généraliser.
      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.
    • C’est un peu comme faire correspondre un champ de bits d’ID de groupe sur les systèmes Unix.
      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.

    • C’est justement ce que je me demande. Que peut faire un attaquant avec un ID de compte AWS ? En quoi est-ce différent de connaître l’adresse e-mail de quelqu’un ?
  • 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.

    • AWS PrivateLink a une autre propriété qui le rend généralement peu souhaitable pour ce type d’intégration : la communication est bidirectionnelle, et les sous-réseaux IP ne doivent pas se chevaucher.
      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.

    • Si vous configurez un agrégateur AWS Config pour l’organisation, vous pouvez interroger l’inventaire des ressources de tous les comptes de l’organisation avec Athena SQL.
      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

    The Zone ID and Account ID are not sensitive. Sensitive data like account API Key, Secrets etc. can all be revoked, rotated or changed. See the comment 36 below on the Wrangler repo: as per our security team, it’s completely Fine to have your zone_id and account_id public, the Global API key and associated email address should be kept secret.

    • L’ID de compte AWS peut lui aussi être rendu public sans risque
      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
    • Pour le compte CF, j’utilise la fonction + de Gmail afin de créer une adresse e-mail totalement unique et difficile à deviner
      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é

    • Dans ce fil, pas mal de personnes semblent considérer l’ID de clé AWS comme une forme de sécurité par l’obscurité ou comme une partie de la défense en profondeur
      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

    • C’est vrai uniquement si l’on utilise le même compte pour la production et le développement. Voilà une raison de plus de ne pas utiliser le même compte
    • Pour faire cela, il suffit de connaître le nom du bucket
      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
    • Comment est-ce possible ? Ne faut-il pas d’abord connaître le nom du bucket de développement ?
    • Peu probable, sauf si le bucket de développement se trouve d’une manière ou d’une autre dans le même compte
  • While account IDs, like any identifying information, should be used and shared carefully, they are not considered secret, sensitive, or confidential information.
    https://docs.aws.amazon.com/accounts/latest/reference/manage...

    • Au moins dans le monde numérique, l’information semble être soit publique, soit privée. On a peu de bonnes notions pour les informations nécessitant une autorisation ou les informations protégées
      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
    • Qu’est-ce que cela veut dire ?
      Si ce n’est ni secret, ni sensible, ni confidentiel, pourquoi faut-il le partager avec prudence ?
    • « n’est pas considéré comme une information secrète, sensible ou confidentielle » devrait probablement être écrit « selon nos critères »
      Les utilisateurs peuvent voir les choses autrement