Proofpoint dokumentierte in diesem Jahr zwei Kampagnen, die gestohlene Anmeldedaten gegen Entra ID validieren, ohne je eine erfolgreiche Anmeldung zu erzeugen. Die Technik ist einfach in einem Satz zu erklären: Senden Sie ein Passwort an den Token-Endpunkt mit einer Client-ID, die keiner registrierten Anwendung entspricht, und lesen Sie den zurückgegebenen Fehler. Diese Fehlercodes sind wichtig, aber das größere Leck ist, an welcher Stelle jeder Code in der Authentifizierungssequenz steht.
Drei Codes, drei verschiedene Bedeutungen
Die Anfragen gehen an den OAuth 2.0 Resource Owner Password Credentials (ROPC)-Endpunkt: ein POST mit Benutzername, Passwort und client_id. Diese Technik ist explizit auf ROPC beschränkt, und deren Einschränkung gehört zu den Gegenmaßnahmen.
Drei Antworten zählen:
- AADSTS50034 (
UserAccountNotFound): Das Konto ist nicht im Verzeichnis. - AADSTS50126 (
InvalidUserNameOrPassword): Dokumentiert als allgemeiner Fehler für verschiedene Ausfälle. - AADSTS700016: Die Anwendungskennung wurde im Verzeichnis nicht gefunden.
AADSTS50126 sollte nicht zwischen einem falschen Benutzernamen und einem falschen Passwort unterscheiden, aber das beobachtete Verhalten trennt sie. Ein fehlgeschlagener Versuch bei einem nicht existierenden Benutzernamen wird überhaupt nicht im Anmeldeprotokoll erfasst, da Entra erst eine Protokollzeile schreibt, wenn ein Benutzername als gültig erkannt wurde. Entra gibt 50034 für nicht vorhandene Konten und 50126 für vorhandene Konten mit falschem Passwort zurück, was eine beobachtete Verhaltensunterscheidung ist, die in Microsofts Dokumentation verwischt wird. Auch der Geltungsbereich ist wichtig. Diese Beobachtungen gelten für verwaltete Mandanten am Token-Endpunkt. Föderierte Mandanten validieren Passwörter lokal über Pass-through Authentication (PTA) oder ADFS, daher unterscheidet sich der Fehlerpfad.
Die Protokolle zeigen die Unterschiede in der Handhabung:
Request | Log row written? | What the attacker learns |
|---|---|---|
|
Account not in directory (50034)
|
No |
This username doesn't exist |
|
Account exists, wrong password (50126) |
Yes, failed sign-in |
This username exists |
|
Account exists, correct password (700016) |
Yes, failed sign-in
|
This credential pair works |
AADSTS700016 bedeutet, dass eine App-Registrierung fehlerhaft ist. Nach einer Reihe von Authentifizierungsversuchen mit unbekannten Client-IDs bestätigt dies, dass der Angreifer ein funktionierendes Passwort besitzt.
Die zwei Kampagnen
UNK_pyreq2323 hat die AWS-Infrastruktur vom 14. Januar 2026 bis Anfang März erschöpft. Es erzeugte über 700.000 gefälschte Client-IDs durch Randomisierung der letzten sechs Ziffern einer legitimen First-Party Exchange Online-Anwendungs-ID (z. B. 00000002-0000-0ff1-ce00-000000XXXXXX). Es zielte auf mehr als eine Million Konten in etwa 4.000 Mandanten ab und verwendete jede gefälschte ID bei nicht mehr als 12 Konten, bevor sie verworfen wurde. Eine First-Party Microsoft-Anwendungs-ID ist in jedem Mandanten vorab genehmigt, daher wirken IDs mit diesem Präfix legitim und nicht wie Störgeräusche.
UNK_OutFlareAZ tauchte im Dezember 2025 auf und kehrte im Februar und März 2026 zurück, wobei es über die Cloudflare-Infrastruktur gegen mehr als 2 Millionen Nutzer vorging mit 3,7 Millionen gefälschten Anwendungs-IDs.
Die beiden verwendeten unterschiedliche Generierungsmethoden, und der Unterschied ist für die Erkennung wichtig. Während pyreq2323 ein echtes Präfix behielt und jede ID bis zu 12 Mal wiederverwendete, erzeugte OutFlareAZ pro Anfrage eine neue zufällige UUIDv4, einen Benutzer pro ID, sodass jede Heuristik, die auf Wiederverwendung basiert, dies verpasst.
(Proofpoint verfolgt beide Kampagnen unter seiner Bezeichnung UNK_, die nicht zugeordnete Cluster statt benannte Akteure kennzeichnet.)
Erkennung
Die Verteidiger sahen die Fehler und Sperrungen, konnten aber nicht erkennen, welche dieser Fehler Anmeldebestätigungen waren. Das Signal war da, zusammen mit jedem Benutzer, der an diesem Morgen sein Passwort falsch eingegeben hatte, aber es war unlesbar, ohne zu wissen, welchen Fehlercode man herausfiltern muss. Die wirklich unsichtbare Hälfte ist die Enumeration. Nicht existierende Benutzernamen erzeugen überhaupt keine Protokollzeile, sodass die Aufklärung, die allem anderen vorausgeht, in keinem Tenant Spuren hinterlässt.
Jede dieser Anfragen wird in den interaktiven Anmeldeprotokollen erfasst. Das folgt aus der Definition von Microsoft: IsInteractive umfasst Anmeldungen, bei denen der Benutzer einen Authentifizierungsfaktor angibt, die Definition nennt Passwörter ausdrücklich, und ROPC übermittelt ein Passwort.
Die Signatur ist ein leerer Anwendungsname:
Client ID in request |
|
|
|---|---|---|
|
Real registered app |
populated |
populated |
|
Well-formed UUID, unregistered
|
populated
|
blank |
|
Malformed client ID |
blank |
blank |
Zeile zwei ist das, wonach Sie suchen. Kombinieren Sie isnotempty(AppId) mit isempty(AppDisplayName) um den wohlgeformten, aber nicht registrierten Fall zu isolieren, anstatt auch fehlerhafte Daten zu erfassen.
Die entscheidende Abfrage liefert bestätigte Anmeldeinformationen-Kompromittierungen zurück:
SigninLogs
| where TimeGenerated > ago(30d)
| where ResultType == "700016"
| where isnotempty(AppId) and isempty(AppDisplayName)
| project TimeGenerated, UserPrincipalName, AppId, IPAddress,
UserAgent, AuthenticationProtocol, ResultDescription
| order by TimeGenerated asc
Jede Zeile ist ein von Entra validiertes Anmeldepaar, behandeln Sie die Ausgabe daher als Liste für Passwortzurücksetzung und Sitzungswiderruf. Es ist kein App-Registrierungsticket, und der folgenschwerste Fehler hier ist, 700016 Treffer an den Besitzer der Anwendungsregistrierungen weiterzuleiten.
Zur Kampagnenerkennung, auf die Quelle statt auf die Kunden-ID pivotieren:
SigninLogs
| where TimeGenerated > ago(7d)
| where isnotempty(AppId) and isempty(AppDisplayName)
| summarize
DistinctAppIds = dcount(AppId),
TargetedUsers = dcount(UserPrincipalName),
ConfirmedCreds = countif(ResultType == "700016"),
WrongPassword = countif(ResultType == "50126"),
Lockouts = countif(ResultType == "50053"),
UserAgents = make_set(UserAgent, 10)
by IPAddress, bin(TimeGenerated, 1h)
| where DistinctAppIds > 10
| order by DistinctAppIds desc
Die Fokussierung auf IPAddress ist absichtlich. Jede Heuristik, die auf der 12-Konten-Wiederverwendungsgrenze basiert, erkennt pyreq2323, übersieht aber OutFlareAZ vollständig, da letzterer niemals eine ID wiederverwendet. Beide Kampagnen sehen von der Quelle her gleich aus: ein Ursprung, der eine große Anzahl von Client-IDs präsentiert, die ins Leere laufen. Das Beibehalten von ConfirmedCreds und Lockouts in derselben Zeile zeigt das Rauschen neben den echten Kompromittierungen.
Was die Korrektur abdeckt und was nicht
Die Einschränkung von ROPC durch Conditional Access ist der richtige Schritt und wird von Proofpoint empfohlen. Aber ich möchte klarstellen, was das bewirkt.
Es betrifft die Enumeration nicht. AADSTS50034 wird zurückgegeben, wenn Entra den Benutzernamen auflöst, vor jeglicher Anmeldeinformationen-Validierung und zwei Schritte vor der Richtlinienbewertung. Keine Conditional Access-Richtlinie kann eine Antwort abfangen, die vor der Richtlinienabfrage ausgegeben wird, und es wird unabhängig von der Mandantenkonfiguration keine Protokollzeile geschrieben. Die Benutzernamen-Enumeration gegen Ihr Verzeichnis übersteht jede Mandantenseitige Kontrolle, einschließlich einer strengen Legacy-Authentifizierungsblockade.
Eine Richtlinie, die Legacy-Authentifizierung blockiert, gibt AADSTS53003 zurück, BlockedByConditionalAccess. Nach derselben Reihenfolge-Logik ist 53003 erst erreichbar, wenn das Passwort validiert wurde, daher wird die Fehlermeldung des Angreifers zu 50126 statt 53003. Unterschiedlicher Code, gleiche Information.
Referenzen
Teilen auf
Erfahren Sie mehr
Über den Autor
Darryl Baker
Senior Security Researcher
Darryl G. Baker ist Senior Staff Security Researcher bei Netwrix und eine anerkannte Autorität im Bereich Identity und Active Directory Sicherheit. Mit über einem Jahrzehnt Erfahrung in Identitätssystemen hat er Unternehmenssicherheitsbewertungen, Schulungen zur Identitätssicherheit und Bedrohungsimulationen mit Fokus auf Active Directory, Entra ID und Azure-Umgebungen geleitet. Darryl hat hoch bewertete Schulungen und Demos bei BlueTeamCon, BSidesCT, The Experts Conference und Wild Wild West Hackin’ Fest gehalten. Er ist der Architekt zahlreicher praxisorientierter Angriffsemulationslabore, die aktuelle Red-Team- und Blue-Team-Tools nutzen, um Verteidigern zu helfen, alles von Angriffspfadanalyse bis Bedrohungsjagd zu meistern. In seinen Sitzungen verbindet Darryl tiefgehende technische Einblicke mit realen Fallstudien und befähigt Blue-Team-Profis, ihre Identity-Sicherheitslage zu stärken und sich gegen sich entwickelnde Angreifertechniken zu verteidigen.
Erfahren Sie mehr zu diesem Thema
Netwrix Innovation Week: Einführung in AIHound
Bring Your Own Vault: Warum „Rip and Replace“ nicht die einzige Option ist
Ihr Passwort-Tresoranbieter ist nicht Ihr Backup-Plan
Den Passwortmanager selbst hosten oder nicht?
Statische Anmeldedaten sind für KI immer noch der einfachste Zugang