Entra ID ROPC Authentication with Unknown Client ID
Identifies potential OAuth client ID spoofing in Microsoft Entra ID sign-in logs. Adversaries submit fabricated or non-existent application identifiers (client IDs) in Resource Owner Password Credentials (ROPC) authentication requests to the token endpoint. Because Entra ID validates the submitted credential before rejecting the request on application resolution, the resulting error code acts as a credential- and account-validity oracle while never producing a successful sign-in. By fragmenting attempts across many fictional application identifiers, adversaries evade per-application detections, rate limiting, and application-scoped Conditional Access. This rule detects a ROPC authentication that fails with error code 700016 (application not found in the directory) where no application display name resolves, which is characteristic of a spoofed client ID used for stealthy user enumeration and password spraying.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2026/07/15"
3integration = ["azure"]
4maturity = "production"
5updated_date = "2026/07/15"
6
7[rule]
8author = ["Elastic"]
9description = """
10Identifies potential OAuth client ID spoofing in Microsoft Entra ID sign-in logs. Adversaries submit fabricated or
11non-existent application identifiers (client IDs) in Resource Owner Password Credentials (ROPC) authentication requests
12to the token endpoint. Because Entra ID validates the submitted credential before rejecting the request on application
13resolution, the resulting error code acts as a credential- and account-validity oracle while never producing a
14successful sign-in. By fragmenting attempts across many fictional application identifiers, adversaries evade
15per-application detections, rate limiting, and application-scoped Conditional Access. This rule detects a ROPC
16authentication that fails with error code 700016 (application not found in the directory) where no application display
17name resolves, which is characteristic of a spoofed client ID used for stealthy user enumeration and password spraying.
18"""
19false_positives = [
20 """
21 A legitimate application that has been deleted from the tenant while a client continues to authenticate against its
22 former client ID via ROPC can generate error code 700016. A misconfigured legacy client submitting an incorrect
23 client ID is also possible. In both cases the client ID is typically stable and low-volume, unlike the many distinct
24 or randomized identifiers seen in spoofing. Verify the application identifier, the source infrastructure, and
25 whether the same principal is targeted by many different unresolved client IDs.
26 """,
27]
28from = "now-9m"
29index = ["logs-azure.signinlogs-*"]
30language = "kuery"
31license = "Elastic License v2"
32name = "Entra ID ROPC Authentication with Unknown Client ID"
33note = """## Triage and analysis
34
35### Investigating Entra ID ROPC Authentication with Unknown Client ID
36
37Adversaries submit fabricated application identifiers (client IDs) in ROPC authentication requests to Microsoft's token endpoint. Entra ID validates the supplied username and password before rejecting the request because the application does not exist, so the returned error code reveals whether the credential and account are valid without ever producing a successful sign-in. A valid credential paired with a spoofed client ID returns `AADSTS700016` (application not found), an invalid password returns `AADSTS50126`, and a non-existent user returns `AADSTS50034`. Because the application never resolves, application-scoped Conditional Access is bypassed, and fragmenting requests across many random client IDs defeats per-application correlation and rate limiting. This behavior is used for stealthy user enumeration and password spraying (for example, the campaigns Proofpoint tracks as UNK_pyreq2323 and UNK_OutFlareAZ).
38
39This rule detects a ROPC authentication (`authentication_protocol: ropc`) that fails with `status.error_code: 700016` and carries no resolved `app_display_name`, the signature of a spoofed or non-existent client ID. This is a New Terms rule that triggers only when the application identifier (`app_id`) has not been observed in the tenant's sign-in logs in the previous 10 days, so each newly introduced spoofed client ID surfaces once rather than on every attempt.
40
41### Possible investigation steps
42
43- Review `azure.signinlogs.properties.app_id`: the value is a client ID that does not resolve to any registered application in the tenant. Determine whether the same principal or source is presenting many distinct or randomized client IDs (fragmentation) versus a single stable identifier (possible deleted app).
44- Assess `azure.signinlogs.properties.user_principal_name`: a valid user account produces a sign-in log for this activity, so the targeted principal exists in the directory and its credentials are being probed. Prioritize privileged or high-value accounts.
45- Correlate `azure.signinlogs.properties.status.error_code` for the same user and source over time. A shift from `50126` (invalid password) to `700016` (application not found) for the same account indicates the adversary has confirmed a valid credential, because the request advanced past credential validation.
46- Review `source.ip`, `source.as.organization.name`, and `source.geo.country_name`: enumeration commonly originates from hosting providers, VPNs, or proxy infrastructure rather than corporate ranges.
47- Inspect `user_agent.original` and `azure.signinlogs.properties.client_app_used`: scripted enumeration frequently uses generic HTTP libraries and logs `client_app_used` as `Unknown`.
48- Pivot on the source IP or ASN to determine how many distinct user principals are being probed, which distinguishes targeted probing from broad spraying.
49
50### False positive analysis
51
52- A legitimate application deleted from the tenant while a client keeps authenticating against its former client ID via ROPC can produce `700016`. Such activity is typically a single, stable client ID at low volume, unlike the many distinct or randomized identifiers seen in spoofing.
53- A misconfigured legacy client submitting an incorrect client ID may also trigger this rule. Confirm the client ID, the source, and whether the same principal is targeted by multiple unresolved client IDs before dismissing.
54
55### Response and remediation
56
57- If enumeration is confirmed, treat the targeted accounts as credential-probing targets: force password resets and revoke refresh tokens for any account where the error code progressed to `700016` (credential likely validated).
58- Block the offending source IPs or ASNs at the firewall, proxy, or via Conditional Access named locations.
59- Ensure MFA and Conditional Access are enforced for all user types, and disable legacy and ROPC authentication where not required, since ROPC cannot satisfy MFA.
60- Audit targeted accounts for credential reuse across services and monitor for follow-on interactive or non-interactive sign-in success from the same source.
61- Notify your identity security team and correlate with any concurrent brute-force or password-spray detections.
62"""
63references = [
64 "https://www.proofpoint.com/us/blog/threat-insight/oauth-client-id-spoofing-why-fake-client-ids-are-gaining-traction-stealthy",
65 "https://learn.microsoft.com/en-us/entra/identity-platform/reference-error-codes",
66 "https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth-ropc",
67]
68risk_score = 47
69rule_id = "a222b46e-eba8-492f-a376-b7f5f397a34f"
70severity = "medium"
71tags = [
72 "Domain: Cloud",
73 "Domain: Identity",
74 "Data Source: Azure",
75 "Data Source: Entra ID",
76 "Data Source: Entra ID Sign-in Logs",
77 "Use Case: Identity and Access Audit",
78 "Use Case: Threat Detection",
79 "Tactic: Credential Access",
80 "Tactic: Discovery",
81 "Resources: Investigation Guide",
82]
83timestamp_override = "event.ingested"
84type = "new_terms"
85
86query = '''
87data_stream.dataset: "azure.signinlogs"
88 and event.category: "authentication"
89 and azure.signinlogs.properties.authentication_protocol: "ropc"
90 and azure.signinlogs.properties.status.error_code: 700016
91 and not azure.signinlogs.properties.app_display_name: *
92'''
93
94
95[[rule.threat]]
96framework = "MITRE ATT&CK"
97[[rule.threat.technique]]
98id = "T1110"
99name = "Brute Force"
100reference = "https://attack.mitre.org/techniques/T1110/"
101[[rule.threat.technique.subtechnique]]
102id = "T1110.003"
103name = "Password Spraying"
104reference = "https://attack.mitre.org/techniques/T1110/003/"
105
106
107
108[rule.threat.tactic]
109id = "TA0006"
110name = "Credential Access"
111reference = "https://attack.mitre.org/tactics/TA0006/"
112[[rule.threat]]
113framework = "MITRE ATT&CK"
114[[rule.threat.technique]]
115id = "T1087"
116name = "Account Discovery"
117reference = "https://attack.mitre.org/techniques/T1087/"
118[[rule.threat.technique.subtechnique]]
119id = "T1087.004"
120name = "Cloud Account"
121reference = "https://attack.mitre.org/techniques/T1087/004/"
122
123
124
125[rule.threat.tactic]
126id = "TA0007"
127name = "Discovery"
128reference = "https://attack.mitre.org/tactics/TA0007/"
129
130[rule.investigation_fields]
131field_names = [
132 "@timestamp",
133 "azure.signinlogs.properties.user_principal_name",
134 "azure.signinlogs.properties.app_id",
135 "azure.signinlogs.properties.app_display_name",
136 "azure.signinlogs.properties.status.error_code",
137 "azure.signinlogs.properties.authentication_protocol",
138 "azure.signinlogs.properties.client_app_used",
139 "azure.signinlogs.category",
140 "source.ip",
141 "source.as.organization.name",
142 "source.geo.country_name",
143 "user_agent.original",
144 "event.outcome",
145]
146
147[rule.new_terms]
148field = "new_terms_fields"
149value = ["azure.signinlogs.properties.app_id"]
150[[rule.new_terms.history_window_start]]
151field = "history_window_start"
152value = "now-10d"
Triage and analysis
Investigating Entra ID ROPC Authentication with Unknown Client ID
Adversaries submit fabricated application identifiers (client IDs) in ROPC authentication requests to Microsoft's token endpoint. Entra ID validates the supplied username and password before rejecting the request because the application does not exist, so the returned error code reveals whether the credential and account are valid without ever producing a successful sign-in. A valid credential paired with a spoofed client ID returns AADSTS700016 (application not found), an invalid password returns AADSTS50126, and a non-existent user returns AADSTS50034. Because the application never resolves, application-scoped Conditional Access is bypassed, and fragmenting requests across many random client IDs defeats per-application correlation and rate limiting. This behavior is used for stealthy user enumeration and password spraying (for example, the campaigns Proofpoint tracks as UNK_pyreq2323 and UNK_OutFlareAZ).
This rule detects a ROPC authentication (authentication_protocol: ropc) that fails with status.error_code: 700016 and carries no resolved app_display_name, the signature of a spoofed or non-existent client ID. This is a New Terms rule that triggers only when the application identifier (app_id) has not been observed in the tenant's sign-in logs in the previous 10 days, so each newly introduced spoofed client ID surfaces once rather than on every attempt.
Possible investigation steps
- Review
azure.signinlogs.properties.app_id: the value is a client ID that does not resolve to any registered application in the tenant. Determine whether the same principal or source is presenting many distinct or randomized client IDs (fragmentation) versus a single stable identifier (possible deleted app). - Assess
azure.signinlogs.properties.user_principal_name: a valid user account produces a sign-in log for this activity, so the targeted principal exists in the directory and its credentials are being probed. Prioritize privileged or high-value accounts. - Correlate
azure.signinlogs.properties.status.error_codefor the same user and source over time. A shift from50126(invalid password) to700016(application not found) for the same account indicates the adversary has confirmed a valid credential, because the request advanced past credential validation. - Review
source.ip,source.as.organization.name, andsource.geo.country_name: enumeration commonly originates from hosting providers, VPNs, or proxy infrastructure rather than corporate ranges. - Inspect
user_agent.originalandazure.signinlogs.properties.client_app_used: scripted enumeration frequently uses generic HTTP libraries and logsclient_app_usedasUnknown. - Pivot on the source IP or ASN to determine how many distinct user principals are being probed, which distinguishes targeted probing from broad spraying.
False positive analysis
- A legitimate application deleted from the tenant while a client keeps authenticating against its former client ID via ROPC can produce
700016. Such activity is typically a single, stable client ID at low volume, unlike the many distinct or randomized identifiers seen in spoofing. - A misconfigured legacy client submitting an incorrect client ID may also trigger this rule. Confirm the client ID, the source, and whether the same principal is targeted by multiple unresolved client IDs before dismissing.
Response and remediation
- If enumeration is confirmed, treat the targeted accounts as credential-probing targets: force password resets and revoke refresh tokens for any account where the error code progressed to
700016(credential likely validated). - Block the offending source IPs or ASNs at the firewall, proxy, or via Conditional Access named locations.
- Ensure MFA and Conditional Access are enforced for all user types, and disable legacy and ROPC authentication where not required, since ROPC cannot satisfy MFA.
- Audit targeted accounts for credential reuse across services and monitor for follow-on interactive or non-interactive sign-in success from the same source.
- Notify your identity security team and correlate with any concurrent brute-force or password-spray detections.
References
Related rules
- Entra ID Sign-in Brute Force Attempted (Microsoft 365)
- Entra ID User Sign-in Brute Force Attempted
- Entra ID OAuth Device Code Sign-in to Azure AD Graph Enumeration
- Entra ID MFA TOTP Brute Force Attempted
- Entra ID OAuth Device Code Flow with Concurrent Sign-ins