2 Punkte von GN⁺ 2024-02-27 | 1 Kommentare | Auf WhatsApp teilen
  • Tracebit fasst eine Technik zusammen, mit der sich die AWS Account ID von öffentlichen und privaten S3-Buckets herleiten lässt, und rekonstruiert beim Beispiel-Bucket bucket-alpha die 123456789101
  • Der zentrale Hinweis ist die Bedingung s3:ResourceAccount in Richtlinien für Interface VPC Endpoints von S3 und die Frage, ob eine Anfrage im eigenen CloudTrail-Log erscheint
  • Bei privaten Buckets bleibt die endgültige Antwort zwar weiterhin AccessDenied, aber nur Anfragen, die die VPC-Endpoint-Richtlinie passieren, tauchen in CloudTrail auf, sodass sich prüfen lässt, ob ein Zahlenmuster passt
  • Wegen Richtlinien-Propagation und CloudTrail-Verzögerungen kann eine einfache Suche bis zu etwa 40 * 12 Minuten = 8 Stunden dauern, lässt sich aber mit 120 Richtlinienanweisungen und parallelen Tests über aws:userid und RoleSessionName auf unter 10 Minuten verkürzen
  • Diese Technik ist möglich, weil StringLike bei s3:ResourceAccount Teilübereinstimmungen erlaubt, und einige Aktivitäten können auch im CloudTrail des Bucket-Eigentümers erscheinen

Erweiterung eines Verfahrens für öffentliche Buckets

  • 2021 veröffentlichte Ben Bridts How to find the AWS Account ID of any Public S3 Bucket
  • Der Ansatz von Tracebit nutzt mehrere Elemente dieser Idee wieder, konzentriert sich aber darauf, die Account ID von S3-Buckets einschließlich privater Buckets zu finden
  • In der Beispielausführung werden für bucket-alpha die in CloudTrail durchgelassenen Sitzungsnamen gesammelt und daraus schließlich 123456789101 rekonstruiert

Warum das bisherige Verfahren für öffentliche Buckets funktioniert

  • Die Methode von Ben Bridts funktioniert, weil drei Bedingungen zusammenspielen
    • Auf die Anfrage lässt sich eine IAM-Richtlinie anwenden
    • Es lässt sich ableiten, ob die Richtlinie die Anfrage erlaubt oder blockiert hat
    • Auf den Bedingungsschlüssel s3:ResourceAccount lässt sich Wildcard-Matching anwenden
  • Bei öffentlichen Buckets führt eine blockierende Richtlinie zu AccessDenied, während eine erlaubende Richtlinie die Anfrage erfolgreich durchlässt, sodass sich leicht erkennen lässt, ob die Richtlinie passiert wurde
  • Wenn man s3:ResourceAccount Stelle für Stelle eingrenzt, schrumpft der gesamte Suchraum von Billionen auf einige Hundert Möglichkeiten

Bei privaten Buckets schaut man statt auf die Antwort auf CloudTrail

  • Bei privaten Buckets lautet die endgültige Antwort unabhängig von der angewandten Richtlinie wegen der Richtlinie des Ziel-Buckets AccessDenied
  • Der Ansatz von Tracebit orientiert sich deshalb nicht am Antwortergebnis, sondern daran, ob eine Anfrage im eigenen CloudTrail-Log erscheint
    • Erscheint die Anfrage in CloudTrail, hat die VPC-Endpoint-Richtlinie sie erlaubt, und sie wurde erst danach von der Bucket-Richtlinie abgelehnt
    • Erscheint die Anfrage nicht in CloudTrail, wurde sie von der VPC-Endpoint-Richtlinie blockiert
  • Wenn man einen Interface VPC Endpoint für S3 erstellt, kann man auf Anfragen eine VPC-Endpoint-Richtlinie anwenden, die zusammen mit anderen Richtlinien wie Bucket-Richtlinie und IAM-Richtlinie des Anfrage-Principals ausgewertet wird
  • Auch in VPC-Endpoint-Richtlinien lassen sich StringLike-Wildcards und Resource-Condition-Keys nutzen, wodurch dieselbe Suchmethode möglich wird

Grundablauf: von der Regionsbestimmung bis zur Ereignisabfrage

  • Zuerst muss die Region des Ziel-Buckets ermittelt werden
    • Schickt man ein curl an den HTTP-Endpunkt des Buckets, wird trotz verweigerter Anfrage der Header x-amz-bucket-region zurückgegeben
    • Im Beispiel wird im Antwort-Header von bucket-alpha.s3.amazonaws.com us-east-1 festgestellt
  • In derselben Region wie der Ziel-Bucket werden ein VPC und ein S3-VPC-Endpoint bereitgestellt
    • Der VPC Endpoint muss vom Typ Interface sein, damit sich eine Richtlinie anwenden lässt
    • Da dieser VPC Endpoint die S3-Anfragen des VPC beeinflusst, empfiehlt sich ein eigenes VPC nur für diesen Zweck
  • Innerhalb des VPC wird eine EC2-Instanz gestartet, um S3-Anfragen abzusetzen, und es wird geprüft, ob die Instanz den S3-VPC-Endpoint nutzt
  • Anschließend wird die VPC-Endpoint-Richtlinie geändert, um zu testen, ob s3:ResourceAccount mit einer bestimmten Ziffer beginnt
    • Um zum Beispiel zu prüfen, ob die Account ID mit 0 beginnt, wird für s3:ResourceAccount die Bedingung "0*" gesetzt
  • Von der EC2-Instanz aus wird eine Management-Anfrage wie GetBucketAcl an den Ziel-Bucket gesendet
    • Management-Anfragen erfordern in der CloudTrail-Konfiguration weniger Sonderbehandlung
    • Das Anfrageergebnis ist erwartungsgemäß AccessDenied

So wird das Zahlenmuster mit CloudTrail erkannt

  • Nach der Anfrage wird in CloudTrail geprüft, ob ein GetBucketAcl-Ereignis erscheint
  • Erscheint das Ereignis, hat die VPC-Endpoint-Richtlinie die Anfrage erlaubt, also passt die Account ID zum getesteten Muster
    • Beispiel: Wenn beim Muster "0*" ein Ereignis sichtbar ist, beginnt die Account ID mit 0
  • Erscheint das Ereignis nicht, hat die VPC-Endpoint-Richtlinie die Anfrage blockiert, also passt das Muster nicht
  • Da es einige Minuten dauern kann, bis ein Ereignis in CloudTrail erscheint, wird empfohlen, 10 Minuten zu warten, bevor man davon ausgeht, dass kein Ereignis vorhanden ist
  • Auch Änderungen an der VPC-Endpoint-Richtlinie brauchen Zeit, bis sie vollständig propagiert und wirksam werden; nach einer Richtlinienänderung funktionieren 5 Minuten Wartezeit gut

Automatisiert, aber im Grundansatz langsam

  • Tracebit schrieb ein Skript, das diesen Prozess automatisiert und die Account ID eines Buckets zuverlässig finden kann
  • Statt einfach jede Ziffer einzeln durchzuprobieren, wird an jeder Stelle ein Verfahren verwendet, das einer Binärsuche ähnelt und die Zahl der Tests reduziert
    • Zum Beispiel lassen sich mit mehreren Mustern wie ["0*", "1*", "2*", "3*", "4*"] in der Bedingung s3:ResourceAccount Bereiche aufteilen
  • Trotzdem bleiben die Wartezeiten für Richtlinienanwendung und CloudTrail-Abfrage der Engpass
    • Selbst mit Binärsuche kann das etwa 40 * 12 Minuten = 8 Stunden dauern
  • In einem Beispiel, das über mehrere Stunden lief, wurde die Account ID von bucket-alpha erfolgreich als 123456789101 ermittelt

Mit 120 Richtlinienanweisungen auf unter 10 Minuten verkürzt

  • Ein schnellerer Ansatz besteht darin, alle möglichen Kombinationen aus Stellen und Ziffern vorab in die VPC-Endpoint-Richtlinie einzutragen
  • Die Richtlinie enthält insgesamt 120 Anweisungen
    • Für jede Position einer AWS Account ID werden die 10 möglichen Ziffern getestet
    • Jede Anweisung verwendet zusammen ein Muster für eine bestimmte Stelle in s3:ResourceAccount und eine Bedingung auf aws:userid
  • Die Bedingung aws:userid wird genutzt, um den bei einem STS-AssumeRole-Aufruf frei wählbaren Wert RoleSessionName abzugleichen
    • Nimmt man eine Rolle mit einem bestimmten RoleSessionName an, lässt sich gezielt die Richtlinienanweisung passieren, die zu einem bestimmten Stellen-Ziffern-Test gehört
  • Diese Richtlinie passt nur knapp innerhalb der maximalen Zeichenlänge für VPC-Endpoint-Richtlinien
  • Da alle 120 Möglichkeiten parallel getestet werden, entfällt weitgehend die Notwendigkeit, die Richtlinie ständig zu ändern oder auf einzelne CloudTrail-Ergebnisse separat zu warten
  • Damit sinkt die Suchzeit nach der Account ID auf unter 10 Minuten

Sichtbarkeit und mögliche Anwendungen

  • Einige Aktivitäten können im CloudTrail-Log des Eigentümers des Ziel-Buckets sichtbar sein
  • Tracebit hat vor der Veröffentlichung mit dem AWS Security Team gesprochen
  • Ob eine AWS Account ID sensible Information ist, wird schon lange diskutiert; im Beispiel-CloudTrail-Ereignis ist die Account ID eines Drittanbieters als HIDDEN_DUE_TO_SECURITY_REASONS maskiert
  • Dieselbe Technik lässt sich auch auf andere Resource-Condition-Keys im Zusammenhang mit Buckets anwenden
    • Beispiel: aws:ResourceOrgID
    • Beispiel: aws:ResourceOrgPaths
    • Beispiel: aws:ResourceTag
  • Möglicherweise lässt sich das Verfahren auch auf andere Services außerhalb von S3 übertragen
  • Wenn man in allen Regionen gegenseitig gepeerte VPCs und VPC Endpoints aufbaut, könnte sich eventuell eine Konfiguration erstellen lassen, die unabhängig von der Region des Ziel-Buckets funktioniert
  • Diese Technik ist möglich, weil sich für die Bedingung s3:ResourceAccount partielle Übereinstimmung mit StringLike verwenden lässt
  • Es könnte nützlich sein, wenn auch durch VPC-Endpoint-Richtlinien abgelehnte Ereignisse in CloudTrail protokolliert würden

1 Kommentare

 
GN⁺ 2024-02-27
Hacker-News-Kommentare
  • Dass man beim Bedingungsschlüssel s3:ResourceAccount Wildcard-Matching anwenden kann, ist wirklich seltsam.
    Es scheint keinen legitimen Grund zu geben, Berechtigungen auf Basis einer teilweisen Übereinstimmung einer Account-ID zu erlauben oder zu verweigern.

    • In der AWS-Policy-Ausführung gibt es mehrere Operatoren und Operanden; in diesem Fall liegt es wohl daran, dass auf den Account-ID-String StringLike angewendet wird.
      Es ist irgendwie interessant, dass man im DevOps-Bereich jetzt Seitenkanalangriffe entdeckt. Auch die spekulativen CPU-Seitenkanäle Meltdown und Spectre haben bei ihrer Entdeckung große Wellen geschlagen; davor gab es bereits Bereiche wie Power Analysis, Magnetfeldverzerrungserkennung und Constant-Time-Kryptografie.
      https://en.m.wikipedia.org/wiki/Side-channel_attack
      https://en.m.wikipedia.org/wiki/Power_analysis
    • Mich hat dieser Teil auch überrascht. Dieses Feld sollte meiner Meinung nach nur exakte Übereinstimmungen zulassen, und mir fällt kein Anwendungsfall ein, bei dem Pattern Matching auf Account-IDs sinnvoll wäre.
    • Das kommt vermutlich aus einer Tendenz zur Verallgemeinerung.
      In einem aktuellen Side Project habe ich eine Funktion gebaut, mit der man Abfragen in einem von OWL inspirierten Format schreiben kann; dazu gibt es eine Bibliothek relationaler Operatoren, etwa um aus URLs den Host zu extrahieren, Präfixabfragen, like-Abfragen, Regex-Abfragen usw. zu machen.
      Da es ein Side Project zu einem anderen Side Project von mir ist, habe ich es mir einfach gemacht und die Operatoren immer verfügbar gelassen, selbst wenn sie keinen Sinn ergeben. Ich weiß nicht, was passiert, wenn man eine Regex-Abfrage auf eine Zahl macht, und es ist mir auch egal. Intern bei AWS könnte es etwas Ähnliches geben, aber bei einem System mit vielen Nutzern und hoher Sicherheitsrelevanz sollten andere Maßstäbe gelten.
    • Das ist ähnlich wie das Matching eines Bitfelds für Gruppen-IDs auf Unix-Systemen.
      Jemand kann auf so eine Idee kommen und sie für clever halten, aber sie in einem System umzusetzen, das man nicht zu 100 % kontrolliert, wirkt töricht.
  • Im Allgemeinen würde man Account-IDs nicht öffentlich streuen, aber man sollte davon ausgehen, dass irgendwann Teile davon offengelegt werden.
    Immer mehr Drittanbieter und SaaS-Plattformen wechseln zu Integrationen, die Role Delegation statt IAM-Usern und Access Keys bevorzugen — und das ist auch richtig so. Dann wird zumindest die Account-ID des Kontos, das als Integrationspunkt dient, anderen Parteien bekannt; und auch dort gibt es Abhängigkeiten, Schwachstellen usw.

    • Das würde mich interessieren: Was kann ein Angreifer mit einer AWS-Account-ID anfangen? Worin unterscheidet sich das davon, die E-Mail-Adresse von jemandem zu kennen?
  • AWS-Account-IDs sind wie IP-Adressen. Sie können sensibel sein, aber damit Arbeit erledigt werden kann, muss irgendjemand sie kennen.
    Vor ein oder zwei Jahren mussten wir uns beispielsweise wegen Geldwäschebekämpfungsprozessen mit einem Drittanbieter integrieren. Wir schlugen vor, mit dieser Organisation PrivateLink einzurichten, weil das normalerweise sicherer ist als ein öffentlich offener SFTP-Port. Das andere Unternehmen lehnte das aus Sicherheitsgründen ab, weil es seine Account-ID verbergen müsse — obwohl sie für die Role ARN des PV-Endpunkts zur gegenseitigen Autorisierung nötig war.
    Am Ende haben wir ihre öffentlichen IP-Bereiche für eingehenden Port 22 auf die Allowlist gesetzt.
    Die Lehre daraus: Man kann eine ID verschleiern und sich dabei clever fühlen, aber es ist schwer, ein Geschäft zu betreiben, wenn die Gegenseite keine Rücksendeadresse kennt.

    • AWS PrivateLink hat noch eine weitere Eigenschaft, die es für solche Integrationen meist unattraktiv macht: Die Kommunikation ist bidirektional, und IP-Subnetze dürfen sich nicht überschneiden.
      Aus Vendor-Sicht integrieren wir normalerweise über einen VPC Endpoint Service. Bei diesem Ansatz ist die Kommunikation unidirektional, und unser Service wird als Load-Balancer-Endpunkt im Kunden-VPC bereitgestellt.
  • Für alle Interessierten habe ich den Code hier veröffentlicht: https://github.com/tracebit-com/find-s3-account

  • Es ist definitiv eine interessante Entdeckung, aber nur anhand des Titels dachte ich, es gäbe eine direktere Methode.
    Es wäre schön, wenn man bei AWS als Admin-Konto innerhalb einer Organisation einfach fragen könnte: „Wo befindet sich Ressource X?“ und schnell herausfinden könnte, in welchem Account ein bestimmter S3-Bucket liegt. Das gilt auch für andere Ressourcen, aber bei S3-Buckets ist es besonders relevant.
    Ehrlich gesagt entsteht dieses Problem vor allem bei Legacy-Buckets von vor besseren Praktiken oder bei Dingen, die schon existierten, bevor alle Buckets vollständig als Code definiert wurden. Trotzdem kann es bei vielen AWS-Accounts mühsam werden, Ressourcen in unbekannten Accounts und Regionen aufzuspüren.

    • Wenn man einen AWS Config Aggregator für die Organisation einrichtet, kann man das Ressourceninventar aller Organisations-Accounts per Athena SQL abfragen.
      Dann lässt sich ungefähr mit select accountId where arn = "x" herausfinden, welchem Account eine Ressource gehört.
  • Auch andere öffentliche AWS-Ressourcen mit globalem Namespace legen AWS-Account-IDs offen.
    https://blog.plerion.com/conditional-love-for-aws-metadata-e...

  • Ein wenig verwandt: Cloudflare account_id und zone_id können gefahrlos öffentlich sein
    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.

    • Auch eine AWS-Konto-ID kann gefahrlos öffentlich sein
      Allerdings kann man damit unter anderem Korrelationen herstellen. Wenn mehrere S3-Sites über dasselbe AWS-Konto betrieben werden, können andere sehen, dass sie über dasselbe Konto gehostet werden. Ob das relevant ist, hängt vom Threat Model ab
    • Für CF-Konten wird mit der +-Funktion von Gmail eine vollständig eindeutige E-Mail-Adresse erstellt, die sich nicht leicht erraten lässt
      Das ist nicht perfekt, fügt aber eine weitere Abstraktionsschicht hinzu
  • Ebenfalls dazu: Eine AWS Key ID enthält, auch wenn sie nicht der geheime Schlüsselteil ist, die Konto-ID in einer um ein Bit verschobenen Form
    https://medium.com/@TalBeerySec/a-short-note-on-aws-key-id-f...
    Diese Key ID ist in vorsignierten S3-URLs enthalten, daher hat man die Konto-ID wahrscheinlich ohnehin schon offengelegt

    • In diesem Thread scheinen ziemlich viele Leute die AWS Key ID als Teil von Security through Obscurity oder Defense in Depth anzunehmen
      Vermutlich wird das Downvotes bekommen, aber falls es doch jemand liest: Das ist ein Beispiel dafür, warum Security through Obscurity keine gute Verteidigung ist. Man selbst wird etwas übersehen, ein hartnäckiger Angreifer nicht
      Sicherheit, die nicht auf Verschleierung beruht, gilt unabhängig davon, ob ich etwas verstanden habe – solange der Angreifer nicht etwa ein Genie anheuert, das einfach AES-256 knackt: https://www.youtube.com/watch?v=KEkrWRHCDQU
  • Warum kann das wichtig sein? Als klares Beispiel: Wenn ein Produktions-Bucket gegeben ist, kann man nun Entwicklungs-Buckets derselben Organisation finden. Persönlich finde ich das kein erwartetes Verhalten

    • Das stimmt nur, wenn für Produktion und Entwicklung dasselbe Konto verwendet wird. Ein weiterer Grund, nicht dasselbe Konto zu verwenden
    • Dafür braucht man nur den Bucket-Namen
      Um solche Enumeration-Versuche zu verhindern, sollte man dem Bucket-Namen ein zufällig erzeugtes Präfix oder Suffix hinzufügen. Außerdem ist es als zusätzliche Maßnahme, nicht als Ersatz, sinnvoll, Bucket-Objekte unter einem anderen Namen als dem Standard-Hostnamen öffentlich bereitzustellen, damit der Bucket-Name selbst nicht durchsickert
    • Wie kommt man dahin? Müsste man nicht zuerst den Namen des Entwicklungs-Buckets kennen?
    • Das ist unwahrscheinlich, solange der Entwicklungs-Bucket nicht irgendwie im selben Konto liegt
  • 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...

    • Zumindest in der digitalen Welt scheint Information entweder öffentlich oder privat zu sein. Es gibt kein besonders gutes Konzept für Informationen, die Berechtigungen erfordern oder geschützt sind
      Zum Beispiel ist meine Wohnadresse technisch gesehen öffentliche Information, aber ich möchte auf keinen Fall, dass sie zusammen mit Familienfotos auf einer Werbetafel neben der Autobahn als mein Wohnort gezeigt wird. Ich gebe sie nur an Personen weiter, die sie brauchen, und vertraue bzw. erwarte im Allgemeinen, dass sie eher vertraulich behandelt wird oder zweckgebunden ist
    • Was soll das bedeuten?
      Wenn es weder geheim noch sensibel noch vertraulich ist, warum sollte man es dann vorsichtig teilen?
    • „Wird nicht als geheime, sensible oder vertrauliche Information betrachtet“ sollte wohl heißen: „nach unseren Maßstäben
      Nutzer können das anders sehen