FROM logs-azure.signinlogs* metadata _id, _version, _index
// filter for Microsoft Entra ID Sign-in Logs
| where event.dataset == "azure.signinlogs"
// filters on member principals, excluding service principals
and azure.signinlogs.properties.user_type == "Member"
and source.ip is not null
and azure.signinlogs.identity is not null
and azure.signinlogs.properties.user_principal_name is not null
and event.outcome == "success"
// filter for successful sign-ins to Microsoft Graph and DRS/AAD from the Microsoft Authentication Broker
and (azure.signinlogs.properties.app_display_name == "Microsoft Authentication Broker" or azure.signinlogs.properties.app_id == "29d9ed98-a469-4536-ade2-f981bc1d605e")
and azure.signinlogs.properties.resource_display_name in ("Device Registration Service", "Microsoft Graph", "Windows Azure Active Directory")
// keep relevant fields
| keep @timestamp, azure.signinlogs.identity, source.ip, azure.signinlogs.properties.app_display_name, azure.signinlogs.properties.resource_display_name, azure.signinlogs.properties.user_principal_name, azure.signinlogs.properties.incoming_token_type, user_agent.original, azure.signinlogs.properties.device_detail.operating_system
// aggregate by 30-minute time window
| eval target_time_window = DATE_TRUNC(30 minutes, @timestamp)
// case statements to track which are MS Graph, DRS, and AAD access
| eval ms_graph = case(azure.signinlogs.properties.resource_display_name == "Microsoft Graph", source.ip, null), drs = case(azure.signinlogs.properties.resource_display_name == "Device Registration Service", source.ip, null), aad = case(azure.signinlogs.properties.resource_display_name == "Windows Azure Active Directory", source.ip, null)
// aggregate by principal and time window
// store token types, target user, unique source IPs, and user agents in arrays for investigation
| stats is_ms_graph = COUNT_DISTINCT(ms_graph), is_drs = COUNT_DISTINCT(drs), is_aad = COUNT_DISTINCT(aad), unique_src_ip = COUNT_DISTINCT(source.ip), ips = VALUES(source.ip), incoming_token_type = VALUES(azure.signinlogs.properties.incoming_token_type), target = VALUES(azure.signinlogs.properties.user_principal_name), user_agents = VALUES(user_agent.original), OS = VALUES(azure.signinlogs.properties.device_detail.operating_system) by azure.signinlogs.identity, target_time_window
// filter for cases with multiple unique source IPs, and at least one DRS or AAD access, and multiple MS Graph accesses
| where unique_src_ip >= 2 and (is_drs >= 1 or is_aad >= 1) and is_ms_graph >= 2
Install detection rules in Elastic Security
Detect Suspicious Activity via Auth Broker On-Behalf-of Principal User in the Elastic Security detection engine by installing this rule into your Elastic Stack.
To setup this rule, check out the installation guide for Prebuilt Security Detection Rules(opens in a new tab or window).