IAM-Rechteausweitung und Persistenz in CloudTrail erkennen
Wie sich Angreifer über IAM Zugang zu AWS sichern: Backdoor-Benutzer, weitere Schlüssel, Adminrichtlinien, Rollen-Vertrauen, IdPs – und was CloudTrail zeigt.
Kurzfassung. Nach dem Leak eines Schlüssels hat der Angreifer vor allem ein Ziel: nicht mehr von diesem Schlüssel abhängig zu sein. Die üblichen Schritte, alle in CloudTrail unter iam.amazonaws.com sichtbar: CreateUser → AttachUserPolicy (AdministratorAccess) → CreateAccessKey und CreateLoginProfile für diesen Benutzer. Leisere Varianten: ein zweiter Schlüssel für einen bestehenden Benutzer, ein zusätzlicher Principal in der Vertrauensrichtlinie einer Rolle, ein neuer SAML-/OIDC-Anbieter, eine öffentliche Lambda-Funktion oder geänderte EC2-User-Data. Lesen Sie in requestParameters das Ziel und in responseElements die IDs neuer Schlüssel ab, und entfernen Sie jedes dieser Elemente, bevor Sie den Vorfall für abgeschlossen erklären.
Die geleakten Anmeldedaten zu widerrufen, ist der einfache Teil eines AWS-Vorfalls. Schief geht in der Regel die Hintertür, die Sie nicht gefunden haben – diejenige, über die derselbe Akteur eine Woche später mit einem Schlüssel wieder hereinkommt, den Sie nie gesehen haben. Dieser Beitrag geht die Techniken für Persistenz und Rechteausweitung in IAM durch, die in den Logs immer wieder auftauchen, und zeigt, wie jede davon in CloudTrail aussieht.
IAM-Ereignisse sind global und werden in us-east-1 protokolliert
IAM ist ein globaler Dienst; wie bei den meisten Ereignissen globaler Dienste werden seine CloudTrail-Ereignisse mit awsRegion = us-east-1 aufgezeichnet. Wenn Sie den Ereignisverlauf nur für die Region abgerufen haben, in der Ihre Workloads laufen, haben Sie möglicherweise sämtliche IAM-Änderungen übersehen. Prüfen Sie diese Region ausdrücklich.
Backdoor-Benutzer
Die laute Variante, und nach wie vor die häufigste:
{"eventSource": "iam.amazonaws.com", "eventName": "CreateUser",
"requestParameters": {"userName": "backup-admin"}}
{"eventName": "AttachUserPolicy",
"requestParameters": {"userName": "backup-admin",
"policyArn": "arn:aws:iam::aws:policy/AdministratorAccess"}}
{"eventName": "CreateAccessKey",
"requestParameters": {"userName": "backup-admin"},
"responseElements": {"accessKey": {"accessKeyId": "AKIA..."}}}
{"eventName": "CreateLoginProfile",
"requestParameters": {"userName": "backup-admin", "passwordResetRequired": false}}
Was sie verrät:
- Die vier Aufrufe erfolgen im Abstand weniger Sekunden mit demselben Schlüssel und von derselben IP.
- Der Name ist so gewählt, dass er nicht auffällt:
backup,support,svc-…,terraform– etwas, das wie ein Dienstkonto aussieht. passwordResetRequired: falsebei einem Login-Profil, das von einem Skript angelegt wurde.- Der Benutzer meldet sich anschließend ohne MFA an der Konsole an (
ConsoleLoginmitadditionalEventData.MFAUsed = "No").
ATT&CK: T1136.003 Create Account: Cloud Account, T1098.003 Additional Cloud Roles.
Zusätzliche Anmeldedaten für bestehende Identitäten
Leiser: Statt einen Benutzer anzulegen, fügt der Angreifer einem bestehenden Benutzer einen zweiten Access Key hinzu (Benutzer können zwei haben) oder setzt ein Konsolenpasswort für einen Dienstbenutzer, der nie eines hatte.
CreateAccessKey, bei dem sichrequestParameters.userNamevom Benutzernamen des Aufrufers unterscheidet – dass ein Principal einen Schlüssel für jemand anderen erzeugt, kommt im normalen Betrieb selten vor.CreateLoginProfileoderUpdateLoginProfilefür einen Benutzer, der nur programmatischen Zugriff haben sollte.
Der Credential-Report hilft hier: access_key_2_active = true bei einem Benutzer, der immer nur einen Schlüssel hatte, oder password_enabled = true bei einem Dienstkonto verdienen eine Nachfrage.
ATT&CK: T1098.001 Additional Cloud Credentials.
Administratorrechte: angehängt, inline oder über eine Gruppe
| Technik | Ereignisse | Was zu prüfen ist |
|---|---|---|
| Verwaltete Administratorrichtlinie | AttachUserPolicy, AttachRolePolicy, AttachGroupPolicy | policyArn = …:policy/AdministratorAccess oder IAMFullAccess |
Inline-Richtlinie mit *:* | PutUserPolicy, PutRolePolicy, PutGroupPolicy | policyDocument mit Action: "*" und Resource: "*" |
| Neue Richtlinienversion | CreatePolicyVersion (oft mit setAsDefault: true) | Dieselbe Prüfung des Dokuments; der Name der Richtlinie kann harmlos wirken |
| Mitgliedschaft in einer Admin-Gruppe | AddUserToGroup | groupName wie etwa Admins |
CreatePolicyVersion verdient besondere Aufmerksamkeit, weil es ändert, was eine bestehende, vertrauenswürdige Richtlinie gewährt, ohne ihren Namen oder ihre Zuordnungen zu verändern. SetDefaultPolicyVersion kann dasselbe erreichen, indem es auf eine ältere, weiter gefasste Version zurückschaltet.
Rollen-Vertrauen und Föderation
Rollen sind schwerer zu erkennen als Benutzer, weil in der Benutzerliste nichts Neues auftaucht.
UpdateAssumeRolePolicylegt neu fest, wer eine Rolle übernehmen darf. Ein Angreifer fügt seine eigene AWS-Konto-ID oder einen externen Principal hinzu. Vergleichen Sie das neuepolicyDocumentmit dem vorherigen (AWS-Config-Historie, Infrastructure as Code oder ein früheresGetRole).CreateSAMLProvider,CreateOpenIDConnectProvider,AddClientIDToOpenIDConnectProvider,UpdateOpenIDConnectProviderThumbprint: Wer den Identitätsanbieter kontrolliert, kann über AssumeRoleWithSAML / AssumeRoleWithWebIdentity Rollen-Anmeldedaten im Konto erhalten. ATT&CK: T1484.002 Trust Modification.
Wenn die Organisation über einen externen Identitätsanbieter föderiert, kann der Angreifer auch über diesen statt über IAM hereingekommen sein; für Zugriffe über Okta siehe oktaforensics.com.
Persistenz über Compute-Ressourcen
| Technik | Ereignisse | Warum sie bestehen bleibt |
|---|---|---|
| Öffentliche Lambda-Funktion | AddPermission mit Principal *; CreateFunctionUrlConfig mit authType: NONE | Jeder kann Code aufrufen, der mit der Rolle der Funktion läuft |
| Neuer oder geänderter Lambda-Code | CreateFunction, UpdateFunctionCode von einem interaktiv genutzten Schlüssel | Code unter Kontrolle des Angreifers, mit den Berechtigungen der Rolle |
| EC2-User-Data | ModifyInstanceAttribute mit userData | Das Skript läuft beim nächsten Start als root |
| SSH-Schlüsselpaare | CreateKeyPair, ImportKeyPair | Zugang zu allen Instanzen, die mit dem Schlüsselpaar gestartet werden |
Lambda-Deployments aus der CI sind normal. Dasselbe Ereignis vom langfristigen Schlüssel eines Menschen zu einer ungewöhnlichen Uhrzeit ist es nicht.
Wie Sie sicher sein können, alle gefunden zu haben
- Pivotieren Sie auf jeden Principal, den der Angreifer kontrolliert hat (den Benutzer des geleakten Schlüssels, angelegte Benutzer, übernommene Rollen), und listen Sie deren erfolgreiche Schreibzugriffe auf (
readOnly = false, keinerrorCode). - Extrahieren Sie jede neue Schlüssel-ID aus den Antworten von
CreateAccessKeyund pivotieren Sie auch auf diese. - Vergleichen Sie den heutigen IAM-Stand mit dem vorherigen: Credential-Report, Ausgabe von
aws iam get-account-authorization-detailsoder Ihr IaC-State. - Suchen Sie nach fehlgeschlagenen Versuchen: Ein
AccessDeniedbeiCreateUserzeigt Ihnen, was der Angreifer versucht hat, und ob ein späterer Erfolg von einem anderen Principal ausging.
Im Analysetool
AWS Forensics hat für jede der oben genannten Techniken eine Regel – „IAM-Benutzer erstellt“, „Access Key für einen anderen Benutzer erstellt“, „Konsolenpasswort für einen Benutzer gesetzt“, „Vertrauensrichtlinie einer Rolle geändert“, „Identitätsanbieter hinzugefügt oder geändert“, „Benutzer zu einer Admin-Gruppe hinzugefügt“, „Lambda-Funktion öffentlich zugänglich gemacht“, „Lambda-Funktion erstellt oder Code aktualisiert“, „EC2-User-Data geändert“, „SSH-Schlüsselpaar erstellt oder importiert“, „Administratorrichtlinie angehängt“, „Richtlinie mit Vollzugriff (:)“ –, und die Checkliste zur Bereinigung nennt die genauen Benutzer, Schlüssel und Rollen, die aufgeräumt werden müssen. Die Referenz der zu überwachenden Ereignisse listet sie mit ihren ATT&CK-IDs auf, und der fiktive Durchgang durch einen Vorfall zeigt, wie ein Backdoor-Admin angelegt und gefunden wird.