Knowledge Required: Strong understanding of KQL concepts

Tools required: Microsoft Sentinel

UPDATED WITH REFINED DETECTION BELOW

I’m reading a lot of chatter on using the Intune Company Portal to get a hashtag Entra ID refresh token and then bypassing Conditional Access to run other Entra attack tools. I tested a POC POCEntraDeviceComplianceBypass and used the Intune token to retrieve another one. Here’s a very rough KQL detection below where we look for Intune and something else in a 10 minute window:

Initial Detection


let BinBy=10m; // longer / shorter time window for Intune + Other Apps authenticating
union AADNonInteractiveUserSignInLogs, SigninLogs
| where ResultType == 0
| where AppDisplayName in ('Microsoft Azure CLI', 'Microsoft Intune Company Portal') or (AppDisplayName contains "Graph" and AppDisplayName != "Graph Files Manager") // filter by applications
| sort by UserPrincipalName, TimeGenerated desc
| where tostring(AuthenticationDetails) contains "MFA requirement satisfied by claim in the token" // we are using tokens to auth
| summarize Application=make_list(AppDisplayName), ApplicationSet=make_set(AppDisplayName), IntuneTime=make_set_if(TimeGenerated, AppDisplayName== "Microsoft Intune Company Portal" ), Time=make_list(TimeGenerated) by UserDisplayName, UserPrincipalName, BinTime=bin(TimeGenerated, BinBy)
| where ApplicationSet has "Microsoft Intune Company Portal" and array_length( ApplicationSet) > 1 // used Intune AND something else
| mv-expand Application, Time
| extend Time=todatetime(Time)
| extend Application=tostring(Application)
| mv-expand IntuneTime to typeof(datetime)
| where Application != "Microsoft Intune Company Portal" and Time > IntuneTime

Revised detection

After some greatly appreciated testing with Boaz ๐Ÿ‘จโ€๐Ÿ’ป , we’ve tested a detection that has been able to catch when the ROAD enumeration tools are used with an EntraID token that was issued to Intune using the POC. It’s still worth baselining this to make sure it’s not going to cause false positives. KQL query below!

let TimeBinSeconds=300;
union SigninLogs, AADNonInteractiveUserSignInLogs
| where ResultType == 0
| where AppId == @"9ba1a5c7-f17a-4de9-a1f1-6178c8d51223" // Intune
| where not(ResourceDisplayName in ('Microsoft Intune IW Service', 'Device Registration Service', 'Microsoft Intune Enrollment')) // filter out legitimate activity 
| extend UserAgentDetail=parse_user_agent(UserAgent,"os")
| where UserAgentDetail.OperatingSystem.Family !in ('Android','iOS') // desktop needed to steal tokens
| summarize ActivityCount=count(), ResourceIds=make_set(ResourceId), UserAgents=make_set(UserAgent), Resources=make_set(ResourceDisplayName), Ids=make_set(Id), make_set(tostring(UserAgentDetail)) by UserPrincipalName, bin(TimeGenerated, TimeBinSeconds*1s)
| where ActivityCount > 1
| where ResourceIds has_all ('Microsoft.aadiam', '') // null seems to occur on the request token to enumerate tenant. aadiam occurs when signing in through browser
| where array_length( UserAgents) > 1 // switch from browser to something else. 
| where Resources has_any ('Microsoft Graph', 'Windows Azure Active Directory')

EOF break