Geleakter GCP-Dienstkontoschlüssel: so untersuchen Sie ihn
Dienstkontoschlüssel in Repo oder CI-Log geleakt? Über serviceAccountKeyName Schlüssel-ID, nutzende IPs und Aktionen finden, dann richtig eindämmen.
Kurz gesagt. Jeder API-Aufruf, der mit einem nutzerverwalteten Dienstkontoschlüssel authentifiziert wird, enthält protoPayload.authenticationInfo.serviceAccountKeyName, das auf /keys/<KEY_ID> endet. Filtern Sie nach dieser Schlüssel-ID, listen Sie die Aufrufer-IPs und User-Agents in zeitlicher Reihenfolge auf und suchen Sie die erste öffentliche IP, die Sie nicht erklären können. Folgen Sie von dort dieser IP: Erkundung (Wellen von PERMISSION_DENIED), SetIamPolicy, neue Schlüssel, neue Dienstkonten. Erst den Schlüssel deaktivieren, dann untersuchen.
Herunterladbare JSON-Schlüssel sind der häufigste Weg, über den ein Google-Cloud-Projekt von außen geöffnet wird. Sie laufen standardmäßig nicht ab, landen in Git-Repositories, CI-Variablen, Docker-Images und auf Laptops, und wer die Datei besitzt, ist das Dienstkonto. Googles Best Practices zur Schlüsselverwaltung empfehlen, ganz auf sie zu verzichten; bis dahin müssen Sie wissen, wie man einen solchen Schlüssel untersucht.
Schritt 1: den Schlüssel identifizieren
Meist beginnen Sie mit einem der folgenden Punkte:
- der Schlüsseldatei selbst, deren Feld
private_key_iddie Schlüssel-ID ist; - einer Benachrichtigung von Google, dass ein Schlüssel öffentlich offengelegt wurde;
- einem Befund zu einem Dienstkonto, das Dinge tut, die es sonst nie tut.
Listen Sie die Schlüssel des Dienstkontos mit gcloud iam service-accounts keys list --iam-account=SA_EMAIL auf und notieren Sie für jeden nutzerverwalteten Schlüssel die ID und den Erstellungszeitpunkt. Suchen Sie dann den Erstellungseintrag in den Admin-Activity-Logs:
protoPayload.methodName="google.iam.admin.v1.CreateServiceAccountKey"
Der Ersteller steht in authenticationInfo.principalEmail, der Name des neuen Schlüssels in protoPayload.response.name. Ein Schlüssel, den eine Person Wochen vor dem Vorfall von einer Büro-IP erstellt hat, erzählt die Geschichte eines „versehentlichen Leaks“. Ein Schlüssel, den der Angreifer während des Vorfalls erstellt hat, erzählt eine Geschichte über Persistenz: MITRE ATT&CK T1098.001, zusätzliche Cloud-Anmeldedaten. Suchen Sie außerdem nach google.iam.admin.v1.UploadServiceAccountKey: Ein hochgeladener öffentlicher Schlüssel bedeutet, dass jemand außerhalb die private Hälfte besitzt.
Schritt 2: jede Nutzung des Schlüssels finden
Googles Beispiel-Logs für Dienstkonten zeigen, dass mit einem Schlüssel getätigte Aufrufe Folgendes enthalten:
"serviceAccountKeyName": "//iam.googleapis.com/projects/PROJECT/serviceAccounts/SA_EMAIL/keys/KEY_ID"
Die Abfrage ist also einfach:
protoPayload.authenticationInfo.serviceAccountKeyName:"KEY_ID"
Ordnen Sie die Ergebnisse zeitlich und erstellen Sie eine kleine Tabelle: zuerst gesehen, zuletzt gesehen, Aufrufer-IP, User-Agent, Anzahl. Wonach Sie suchen:
| Muster | Deutung |
|---|---|
| Eine IP, Ihr CI-Runner oder Büro, gleichbleibender User-Agent | Normale Nutzung |
Eine neue öffentliche IP, ein anderer User-Agent (gcloud, wo es bisher nur Terraform gab) | Der Schlüssel wurde kopiert |
| Eine Welle von Statuscode 7 (PERMISSION_DENIED) über viele Dienste hinweg | Jemand testet, was der Schlüssel darf: T1580 / T1526 |
SetIamPolicy, CreateServiceAccountKey, CreateServiceAccount von dieser IP | Rechteausweitung und Persistenz |
Denken Sie daran, dass lesende Aufrufe (GetIamPolicy, storage.objects.get, ListServiceAccounts) in den Data-Access-Logs stehen. Ohne Data-Access-Logging sehen Sie nur die Schreibzugriffe des Schlüssels. Bei lesenden Aufrufen, die mit PERMISSION_DENIED scheitern, kann Google die E-Mail-Adresse des Aufrufers schwärzen, aber nicht, wenn der Aufrufer ein Dienstkonto ist (Aufruferidentitäten in Audit-Logs); die fehlgeschlagenen Lesezugriffe eines geleakten Schlüssels bleiben also zuordenbar.
Schritt 3: CI und Angreifer auseinanderhalten
Schwierig ist nicht, externe IPs zu finden, sondern dass auch legitime Schlüssel außerhalb von Google Cloud genutzt werden. Ein GitHub-Actions-Runner, der Server eines Partners, der Laptop eines Entwicklers: Alle sind „öffentliche IPs“. Hilfreiche Unterscheidungsmerkmale:
- User-Agent: Terraform und Client-Bibliotheken tragen versionierte Kennungen; eine gcloud-CLI unter Linux mit
interactive/Truevon einem VPS ist nicht Ihre Pipeline. - Zeitpunkt: CI läuft bei Commits und nach Zeitplan; eine Angreifersitzung ist eine dichte Welle zu ungewöhnlicher Stunde.
- Fehler: Pipelines laufen selten binnen weniger Minuten in Dutzende verweigerter Aufrufe; eine Erkundung schon.
- Methoden: Pipelines wiederholen dieselben Methoden; Angreifer rufen
GetIamPolicyfür die Organisation auf und listen Secrets, Rechnungskonten und Benachrichtigungskonfigurationen des Security Command Center auf.
Schritt 4: der Angreifer-IP folgen, nicht nur dem Schlüssel
Sobald Sie die Angreifer-IP haben, lassen Sie den Schlüsselfilter weg und suchen nur nach der IP:
protoPayload.requestMetadata.callerIp="203.0.113.66"
Angreifer wechseln die Identität, sobald sie können: Sie erteilen einem Konto, das sie kontrollieren (oft eine Gmail-Adresse), Owner-Rechte und machen von derselben Maschine aus mit diesem Konto weiter. Die IP verbindet beide Phasen. Zu dieser zweiten Phase siehe SetIamPolicy-Missbrauch, und Impersonation von Dienstkonten, falls mit dem Schlüssel Tokens für andere Dienstkonten ausgestellt wurden.
Schritt 5: in der richtigen Reihenfolge eindämmen
Googles Leitfaden für kompromittierte Anmeldedaten und die Seite Schlüssel deaktivieren und aktivieren beschreiben die Mechanik. Die Reihenfolge, die ich verwende:
- Den Schlüssel deaktivieren (umkehrbar, sofort wirksam). Ist das Dienstkonto über den Schlüssel hinaus kompromittiert, deaktivieren Sie das Dienstkonto.
- Entfernen, was der Angreifer damit hinzugefügt hat: IAM-Bindungen, Schlüssel, Dienstkonten, HMAC-Schlüssel.
- Dem legitimen Workload neue Anmeldedaten bereitstellen, möglichst keinen Schlüssel: Workload Identity Federation für CI.
- Den alten Schlüssel löschen, sobald die Untersuchung alles über ihn festgehalten hat.
- Davon ausgehen, dass alles offengelegt ist, was das Dienstkonto lesen konnte: Secrets, Buckets, Datasets. Rotieren Sie diese Secrets.
Beseitigen Sie dann die Ursache: Entfernen Sie die Datei aus der Repository-Historie und den CI-Logs und suchen Sie nach weiteren Kopien.
Prävention, die tatsächlich wirkt
- Organisationsrichtlinie
iam.disableServiceAccountKeyCreation: keine neuen nutzerverwalteten Schlüssel. iam.serviceAccountKeyExposureResponseaufDISABLE_KEYgesetzt: Google erkennt an öffentlichen Orten offengelegte Schlüssel, deaktiviert sie und benachrichtigt Inhaber und Sicherheitskontakte (Google-Cloud-Blog).- Ein Ablaufdatum für die Schlüssel, auf die Sie nicht verzichten können, und ein Inventar der verbleibenden.
Was der Analyzer markiert
Für einen im Analyzer abgelegten Export erzeugt die Geschichte eines Schlüssels bis zu fünf Befunde:
| Regel | Schweregrad | Schlägt an, wenn |
|---|---|---|
sa_key_created | Mittel | CreateServiceAccountKey erfolgreich war |
sa_key_uploaded | Hoch | UploadServiceAccountKey erfolgreich war |
sa_key_used_external | Mittel | Ein Dienstkonto sich mit einem nutzerverwalteten Schlüssel von einer öffentlichen IP authentifiziert hat (unabhängig vom Ergebnis) |
sa_key_new_ip | Hoch | Ein Schlüssel von einer anderen öffentlichen IP genutzt wurde als der ersten, die für ihn in den Logs auftaucht |
permission_denied_burst | Mittel | 20 verweigerte Aufrufe einer Identität innerhalb von 10 Minuten |
Der Reiter „Entitäten“ listet jeden Schlüssel mit seinem Ersteller und jeder IP, die ihn genutzt hat. Eine Grenze sollten Sie im Blick behalten: „Neue IP“ bezieht sich auf den Export. Beginnt Ihr Export erst nach der ersten Nutzung durch den Angreifer, wird die Angreifer-IP zur Baseline. Exportieren Sie nach Möglichkeit einen längeren Zeitraum.
Häufige Fragen
Woran erkenne ich, ob ein geleakter Dienstkontoschlüssel genutzt wurde?
Durchsuchen Sie die Audit-Logs nach protoPayload.authenticationInfo.serviceAccountKeyName, das mit der Schlüssel-ID endet. Jeder mit dem Schlüssel getätigte Aufruf enthält dieses Feld. Aufrufe von IP-Adressen, die Sie nicht kennen, besonders nach dem Datum des Leaks, bedeuten, dass jemand anderes den Schlüssel verwendet hat.
Deaktiviert Google geleakte Dienstkontoschlüssel automatisch?
Google durchsucht öffentliche Repositories nach offengelegten Schlüsseln. Ist die Organisationsrichtlinie iam.serviceAccountKeyExposureResponse auf DISABLE_KEY gesetzt, werden erkannte Schlüssel automatisch deaktiviert und Projektinhaber sowie Sicherheitskontakte benachrichtigt.
Sollte ich den Schlüssel sofort löschen?
Deaktivieren Sie ihn zuerst: Die Deaktivierung ist umkehrbar und stoppt den Angreifer. Notieren Sie die Schlüssel-ID und die Details der Erstellung und löschen Sie ihn, sobald die Untersuchung ihn nicht mehr braucht und die legitimen Workloads einen Ersatz haben.
Weiterführende Links
- Best practices for managing service account keys – Dokumentation von Google Cloud.
- MITRE ATT&CK T1078.004, Valid Accounts: Cloud Accounts.
- MITRE ATT&CK T1552.001, Unsecured Credentials: Credentials In Files – wie Schlüsseldateien nach außen gelangen.
- Incident Response in Google Cloud: kompromittiertes Projekt.