Entra ID OAuth Flow by Microsoft Authentication Broker to Device Registration Service (DRS)
Identifies separate OAuth authorization flows in Microsoft Entra ID where the same user principal and session ID are observed across multiple IP addresses within a 5-minute window. These flows involve the Microsoft Authentication Broker (MAB) as the client application and the Device Registration Service (DRS) as the target resource. This pattern is highly indicative of OAuth phishing activity, where an adversary crafts a legitimate Microsoft login URL to trick a user into completing authentication and sharing the resulting authorization code, which is then exchanged for an access and refresh token by the attacker.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2025/04/30"
3integration = ["azure"]
4maturity = "production"
5updated_date = "2025/12/10"
6
7[rule]
8author = ["Elastic"]
9description = """
10Identifies separate OAuth authorization flows in Microsoft Entra ID where the same user principal and session ID are
11observed across multiple IP addresses within a 5-minute window. These flows involve the Microsoft Authentication Broker
12(MAB) as the client application and the Device Registration Service (DRS) as the target resource. This pattern is highly
13indicative of OAuth phishing activity, where an adversary crafts a legitimate Microsoft login URL to trick a user into
14completing authentication and sharing the resulting authorization code, which is then exchanged for an access and
15refresh token by the attacker.
16"""
17false_positives = [
18 """
19 Legitimate device registrations using Microsoft Authentication Broker may occur during corporate enrollment
20 scenarios or bulk provisioning, but it is uncommon for multiple source IPs to register the same identity across
21 Microsoft Graph, Device Registration Service (DRS), and Azure Active Directory (AAD) in a short time span.
22 """,
23]
24from = "now-61m"
25interval = "60m"
26language = "esql"
27license = "Elastic License v2"
28name = "Entra ID OAuth Flow by Microsoft Authentication Broker to Device Registration Service (DRS)"
29note = """## Triage and analysis
30
31### Investigating Entra ID OAuth Flow by Microsoft Authentication Broker to Device Registration Service (DRS)
32
33This rule identifies potential OAuth phishing behavior in Microsoft Entra ID where two OAuth authorization flows are observed in quick succession, sharing the same user principal and session ID but originating from different IP addresses. The client application is the Microsoft Authentication Broker, and the target resource is the Device Registration Service (DRS). This pattern is indicative of adversaries attempting to phish targets for OAuth sessions by tricking users into authenticating through a crafted URL, which then allows the attacker to obtain an authorization code and exchange it for access and refresh tokens.
34
35### Possible Investigation Steps:
36
37- `target`: The user principal name targeted by the authentication broker. Investigate whether this user has recently registered a device, signed in from new IPs, or had password resets or MFA changes.
38- `session_id`: Used to correlate all events in the OAuth flow. All sign-ins in the alert share the same session, suggesting shared or hijacked state.
39- `unique_token_id`: Lists tokens generated in the flow. If multiple IDs exist in the same session, this indicates token issuance from different locations.
40- `source_ip`, `city_name`, `country_name`, `region_name`: Review the IPs and geolocations involved. A mismatch in geographic origin within minutes can signal adversary involvement.
41- `user_agent`: Conflicting user agents (e.g., `python-requests` and `Chrome`) suggest one leg of the session was scripted or automated.
42- `os`: If multiple operating systems are observed in the same short session (e.g., macOS and Windows), this may suggest activity from different environments.
43- `incoming_token_type`: Look for values like `"none"` or `"refreshToken"` that can indicate abnormal or re-authenticated activity.
44- `token_session_status`: A value of `"unbound"` means the issued token is not tied to a device or CAE session, making it reusable from another IP.
45- `conditional_access_status`: If this is `"notApplied"`, it may indicate that expected access policies were not enforced.
46- `auth_count`: Number of events in the session. More than one indicates the session was reused within the time window.
47- `target_time_window`: Use this to pivot into raw sign-in logs to review the exact sequence and timing of the activity.
48- Search `azure.auditlogs` for any device join or registration activity around the `target_time_window`.
49- Review `azure.identityprotection` logs for anonymized IPs, impossible travel, or token replay alerts.
50- Search for other activity from the same IPs across all users to identify horizontal movement.
51
52### False Positive Analysis
53
54- A legitimate device join from a user switching networks (e.g., mobile hotspot to Wi-Fi) could explain multi-IP usage.
55- Some identity management agents or EDR tools may use MAB for background device registration flows.
56- Developers or IT administrators may access DRS across environments when testing.
57
58### Response and Remediation
59
60- If confirmed unauthorized, revoke all refresh tokens for the user and disable any suspicious registered devices.
61- Notify the user and verify if the authentication or device join was expected.
62- Review Conditional Access policies for the Microsoft Authentication Broker (`29d9ed98-a469-4536-ade2-f981bc1d605e`) to ensure enforcement of MFA and device trust.
63- Consider restricting token-based reauthentication from anonymized infrastructure or unusual user agents.
64- Continue monitoring for follow-on activity, such as privilege escalation, token misuse, or lateral movement.
65"""
66references = [
67 "https://www.volexity.com/blog/2025/04/22/phishing-for-codes-russian-threat-actors-target-microsoft-365-oauth-workflows/",
68 "https://github.com/dirkjanm/ROADtools",
69 "https://dirkjanm.io/phishing-for-microsoft-entra-primary-refresh-tokens/",
70]
71risk_score = 73
72rule_id = "375132c6-25d5-11f0-8745-f661ea17fbcd"
73setup = """#### Required Microsoft Entra ID Sign-In Logs
74This rule requires the Microsoft Entra ID Sign-In Logs integration be enabled and configured to collect sign-in logs. In Entra ID, sign-in logs must be enabled and streaming to the Event Hub used for the Azure integration.
75"""
76severity = "high"
77tags = [
78 "Domain: Cloud",
79 "Domain: Identity",
80 "Data Source: Azure",
81 "Data Source: Entra ID",
82 "Data Source: Entra ID Sign-in Logs",
83 "Use Case: Identity and Access Audit",
84 "Use Case: Threat Detection",
85 "Resources: Investigation Guide",
86 "Tactic: Initial Access",
87]
88timestamp_override = "event.ingested"
89type = "esql"
90
91query = '''
92from logs-azure.signinlogs-* metadata _id, _version, _index
93| where
94 event.dataset == "azure.signinlogs" and
95 event.outcome == "success" and
96 azure.signinlogs.properties.user_type == "Member" and
97 azure.signinlogs.identity is not null and
98 azure.signinlogs.properties.user_principal_name is not null and
99 source.address is not null and
100 azure.signinlogs.properties.app_id == "29d9ed98-a469-4536-ade2-f981bc1d605e" and // MAB
101 azure.signinlogs.properties.resource_id == "01cb2876-7ebd-4aa4-9cc9-d28bd4d359a9" // DRS
102
103| eval
104 Esql.time_window_date_trunc = date_trunc(30 minutes, @timestamp),
105 Esql.azure_signinlogs_properties_session_id = azure.signinlogs.properties.session_id,
106 Esql.is_browser_case = case(
107 to_lower(azure.signinlogs.properties.device_detail.browser) rlike "(chrome|firefox|edge|safari).*", 1, 0
108 )
109
110| stats
111 Esql_priv.azure_signinlogs_properties_user_display_name_values = values(azure.signinlogs.properties.user_display_name),
112 Esql_priv.azure_signinlogs_properties_user_principal_name_values = values(azure.signinlogs.properties.user_principal_name),
113 Esql.azure_signinlogs_properties_session_id_values = values(azure.signinlogs.properties.session_id),
114 Esql.azure_signinlogs_properties_unique_token_identifier_values = values(azure.signinlogs.properties.unique_token_identifier),
115
116 Esql.source_geo_city_name_values = values(source.geo.city_name),
117 Esql.source_geo_country_name_values = values(source.geo.country_name),
118 Esql.source_geo_region_name_values = values(source.geo.region_name),
119 Esql.source_address_values = values(source.address),
120 Esql.source_address_count_distinct = count_distinct(source.address),
121 Esql.source_as_organization_name_values = values(source.`as`.organization.name),
122
123 Esql.azure_signinlogs_properties_authentication_protocol_values = values(azure.signinlogs.properties.authentication_protocol),
124 Esql.azure_signinlogs_properties_authentication_requirement_values = values(azure.signinlogs.properties.authentication_requirement),
125 Esql.azure_signinlogs_properties_is_interactive_values = values(azure.signinlogs.properties.is_interactive),
126
127 Esql.azure_signinlogs_properties_incoming_token_type_values = values(azure.signinlogs.properties.incoming_token_type),
128 Esql.azure_signinlogs_properties_token_protection_status_details_sign_in_session_status_values = values(azure.signinlogs.properties.token_protection_status_details.sign_in_session_status),
129 Esql.azure_signinlogs_properties_session_id_count_distinct = count_distinct(azure.signinlogs.properties.session_id),
130 Esql.azure_signinlogs_properties_app_display_name_values = values(azure.signinlogs.properties.app_display_name),
131 Esql.azure_signinlogs_properties_app_id_values = values(azure.signinlogs.properties.app_id),
132 Esql.azure_signinlogs_properties_resource_id_values = values(azure.signinlogs.properties.resource_id),
133 Esql.azure_signinlogs_properties_resource_display_name_values = values(azure.signinlogs.properties.resource_display_name),
134
135 Esql.azure_signinlogs_properties_app_owner_tenant_id_values = values(azure.signinlogs.properties.app_owner_tenant_id),
136 Esql.azure_signinlogs_properties_resource_owner_tenant_id_values = values(azure.signinlogs.properties.resource_owner_tenant_id),
137
138 Esql.azure_signinlogs_properties_conditional_access_status_values = values(azure.signinlogs.properties.conditional_access_status),
139 Esql.azure_signinlogs_properties_risk_state_values = values(azure.signinlogs.properties.risk_state),
140 Esql.azure_signinlogs_properties_risk_level_aggregated_values = values(azure.signinlogs.properties.risk_level_aggregated),
141
142 Esql.azure_signinlogs_properties_device_detail_browser_values = values(azure.signinlogs.properties.device_detail.browser),
143 Esql.azure_signinlogs_properties_device_detail_operating_system_values = values(azure.signinlogs.properties.device_detail.operating_system),
144 Esql.user_agent_original_values = values(user_agent.original),
145 Esql.is_browser_case_max = max(Esql.is_browser_case),
146
147 Esql.event_count = count(*)
148 by
149 Esql.time_window_date_trunc,
150 azure.signinlogs.properties.user_principal_name,
151 azure.signinlogs.properties.session_id
152
153| keep
154 Esql.time_window_date_trunc,
155 Esql_priv.azure_signinlogs_properties_user_display_name_values,
156 Esql_priv.azure_signinlogs_properties_user_principal_name_values,
157 Esql.azure_signinlogs_properties_session_id_values,
158 Esql.azure_signinlogs_properties_unique_token_identifier_values,
159 Esql.source_geo_city_name_values,
160 Esql.source_geo_country_name_values,
161 Esql.source_geo_region_name_values,
162 Esql.source_address_values,
163 Esql.source_address_count_distinct,
164 Esql.source_as_organization_name_values,
165 Esql.azure_signinlogs_properties_authentication_protocol_values,
166 Esql.azure_signinlogs_properties_authentication_requirement_values,
167 Esql.azure_signinlogs_properties_is_interactive_values,
168 Esql.azure_signinlogs_properties_incoming_token_type_values,
169 Esql.azure_signinlogs_properties_token_protection_status_details_sign_in_session_status_values,
170 Esql.azure_signinlogs_properties_session_id_count_distinct,
171 Esql.azure_signinlogs_properties_app_display_name_values,
172 Esql.azure_signinlogs_properties_app_id_values,
173 Esql.azure_signinlogs_properties_resource_id_values,
174 Esql.azure_signinlogs_properties_resource_display_name_values,
175 Esql.azure_signinlogs_properties_app_owner_tenant_id_values,
176 Esql.azure_signinlogs_properties_resource_owner_tenant_id_values,
177 Esql.azure_signinlogs_properties_conditional_access_status_values,
178 Esql.azure_signinlogs_properties_risk_state_values,
179 Esql.azure_signinlogs_properties_risk_level_aggregated_values,
180 Esql.azure_signinlogs_properties_device_detail_browser_values,
181 Esql.azure_signinlogs_properties_device_detail_operating_system_values,
182 Esql.user_agent_original_values,
183 Esql.is_browser_case_max,
184 Esql.event_count
185
186| where
187 Esql.source_address_count_distinct >= 2 and
188 Esql.azure_signinlogs_properties_session_id_count_distinct == 1 and
189 Esql.is_browser_case_max >= 1 and
190 Esql.event_count >= 2
191'''
192
193
194[[rule.threat]]
195framework = "MITRE ATT&CK"
196[[rule.threat.technique]]
197id = "T1078"
198name = "Valid Accounts"
199reference = "https://attack.mitre.org/techniques/T1078/"
200[[rule.threat.technique.subtechnique]]
201id = "T1078.004"
202name = "Cloud Accounts"
203reference = "https://attack.mitre.org/techniques/T1078/004/"
204
205[[rule.threat.technique]]
206id = "T1566"
207name = "Phishing"
208reference = "https://attack.mitre.org/techniques/T1566/"
209[[rule.threat.technique.subtechnique]]
210id = "T1566.002"
211name = "Spearphishing Link"
212reference = "https://attack.mitre.org/techniques/T1566/002/"
213
214
215
216[rule.threat.tactic]
217id = "TA0001"
218name = "Initial Access"
219reference = "https://attack.mitre.org/tactics/TA0001/"
220[[rule.threat]]
221framework = "MITRE ATT&CK"
222[[rule.threat.technique]]
223id = "T1528"
224name = "Steal Application Access Token"
225reference = "https://attack.mitre.org/techniques/T1528/"
226
227
228
229[rule.threat.tactic]
230id = "TA0006"
231name = "Credential Access"
232reference = "https://attack.mitre.org/tactics/TA0006/"
Triage and analysis
Investigating Entra ID OAuth Flow by Microsoft Authentication Broker to Device Registration Service (DRS)
This rule identifies potential OAuth phishing behavior in Microsoft Entra ID where two OAuth authorization flows are observed in quick succession, sharing the same user principal and session ID but originating from different IP addresses. The client application is the Microsoft Authentication Broker, and the target resource is the Device Registration Service (DRS). This pattern is indicative of adversaries attempting to phish targets for OAuth sessions by tricking users into authenticating through a crafted URL, which then allows the attacker to obtain an authorization code and exchange it for access and refresh tokens.
Possible Investigation Steps:
target: The user principal name targeted by the authentication broker. Investigate whether this user has recently registered a device, signed in from new IPs, or had password resets or MFA changes.session_id: Used to correlate all events in the OAuth flow. All sign-ins in the alert share the same session, suggesting shared or hijacked state.unique_token_id: Lists tokens generated in the flow. If multiple IDs exist in the same session, this indicates token issuance from different locations.source_ip,city_name,country_name,region_name: Review the IPs and geolocations involved. A mismatch in geographic origin within minutes can signal adversary involvement.user_agent: Conflicting user agents (e.g.,python-requestsandChrome) suggest one leg of the session was scripted or automated.os: If multiple operating systems are observed in the same short session (e.g., macOS and Windows), this may suggest activity from different environments.incoming_token_type: Look for values like"none"or"refreshToken"that can indicate abnormal or re-authenticated activity.token_session_status: A value of"unbound"means the issued token is not tied to a device or CAE session, making it reusable from another IP.conditional_access_status: If this is"notApplied", it may indicate that expected access policies were not enforced.auth_count: Number of events in the session. More than one indicates the session was reused within the time window.target_time_window: Use this to pivot into raw sign-in logs to review the exact sequence and timing of the activity.- Search
azure.auditlogsfor any device join or registration activity around thetarget_time_window. - Review
azure.identityprotectionlogs for anonymized IPs, impossible travel, or token replay alerts. - Search for other activity from the same IPs across all users to identify horizontal movement.
False Positive Analysis
- A legitimate device join from a user switching networks (e.g., mobile hotspot to Wi-Fi) could explain multi-IP usage.
- Some identity management agents or EDR tools may use MAB for background device registration flows.
- Developers or IT administrators may access DRS across environments when testing.
Response and Remediation
- If confirmed unauthorized, revoke all refresh tokens for the user and disable any suspicious registered devices.
- Notify the user and verify if the authentication or device join was expected.
- Review Conditional Access policies for the Microsoft Authentication Broker (
29d9ed98-a469-4536-ade2-f981bc1d605e) to ensure enforcement of MFA and device trust. - Consider restricting token-based reauthentication from anonymized infrastructure or unusual user agents.
- Continue monitoring for follow-on activity, such as privilege escalation, token misuse, or lateral movement.
References
Related rules
- Entra ID Sign-in Brute Force Attempted (Microsoft 365)
- Entra ID User Sign-in Brute Force Attempted
- M365 or Entra ID Identity Sign-in from a Suspicious Source
- Entra ID Actor Token User Impersonation Abuse
- Entra ID Protection Admin Confirmed Compromise