- 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-alphadie123456789101 - Der zentrale Hinweis ist die Bedingung
s3:ResourceAccountin 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 Stundendauern, lässt sich aber mit 120 Richtlinienanweisungen und parallelen Tests überaws:useridundRoleSessionNameauf unter 10 Minuten verkürzen - Diese Technik ist möglich, weil
StringLikebeis3:ResourceAccountTeilü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-alphadie in CloudTrail durchgelassenen Sitzungsnamen gesammelt und daraus schließlich123456789101rekonstruiert
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:ResourceAccountlä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:ResourceAccountStelle 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
curlan den HTTP-Endpunkt des Buckets, wird trotz verweigerter Anfrage der Headerx-amz-bucket-regionzurückgegeben - Im Beispiel wird im Antwort-Header von
bucket-alpha.s3.amazonaws.comus-east-1festgestellt
- Schickt man ein
- 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:ResourceAccountmit einer bestimmten Ziffer beginnt- Um zum Beispiel zu prüfen, ob die Account ID mit
0beginnt, wird fürs3:ResourceAccountdie Bedingung"0*"gesetzt
- Um zum Beispiel zu prüfen, ob die Account ID mit
- Von der EC2-Instanz aus wird eine Management-Anfrage wie
GetBucketAclan 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 mit0
- Beispiel: Wenn beim Muster
- 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 Bedingungs3:ResourceAccountBereiche aufteilen
- Zum Beispiel lassen sich mit mehreren Mustern wie
- Trotzdem bleiben die Wartezeiten für Richtlinienanwendung und CloudTrail-Abfrage der Engpass
- Selbst mit Binärsuche kann das etwa
40 * 12 Minuten = 8 Stundendauern
- Selbst mit Binärsuche kann das etwa
- In einem Beispiel, das über mehrere Stunden lief, wurde die Account ID von
bucket-alphaerfolgreich als123456789101ermittelt
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:ResourceAccountund eine Bedingung aufaws:userid
- Die Bedingung
aws:useridwird genutzt, um den bei einem STS-AssumeRole-Aufruf frei wählbaren WertRoleSessionNameabzugleichen- Nimmt man eine Rolle mit einem bestimmten
RoleSessionNamean, lässt sich gezielt die Richtlinienanweisung passieren, die zu einem bestimmten Stellen-Ziffern-Test gehört
- Nimmt man eine Rolle mit einem bestimmten
- 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_REASONSmaskiert - 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
- Beispiel:
- 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:ResourceAccountpartielle Übereinstimmung mitStringLikeverwenden lässt - Es könnte nützlich sein, wenn auch durch VPC-Endpoint-Richtlinien abgelehnte Ereignisse in CloudTrail protokolliert würden
1 Kommentare
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.
StringLikeangewendet 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
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.
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.
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.
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.
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
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
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
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
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
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
Wenn es weder geheim noch sensibel noch vertraulich ist, warum sollte man es dann vorsichtig teilen?
Nutzer können das anders sehen