Query Details
let query_frequency = 15m;
let query_period = 1h;
let unexpected_strings_useragent = strcat("(?i)(", strcat_array(dynamic([
"kali",
"AZURECLI"
]), "|"), ")");
MicrosoftGraphActivityLogs
| where TimeGenerated > ago(query_frequency)
| where UserAgent matches regex unexpected_strings_useragent
| summarize arg_min(TimeGenerated, *) by UserId, ServicePrincipalId
| project TimeGenerated, UserId, ServicePrincipalId, IPAddress, RequestMethod, ApiVersion, RequestUri, UserAgent, SignInActivityId, AppId, TokenIssuedAt
| join hint.strategy=shuffle kind=leftouter (
union SigninLogs, AADNonInteractiveUserSignInLogs
| where TimeGenerated > ago(query_period)
| project
UserPrincipalName,
UserDisplayName,
AppDisplayName,
ResourceDisplayName,
Token_IPAddress = IPAddress,
Token_Location = Location,
Token_UserAgent = UserAgent,
Token_OriginalRequestId = OriginalRequestId,
Token_CorrelationId = CorrelationId,
UniqueTokenIdentifier
) on $left.SignInActivityId == $right.UniqueTokenIdentifier
The query is looking for Microsoft Graph activity logs where the UserAgent matches certain unexpected strings. It then summarizes the results by UserId and ServicePrincipalId, and selects specific columns for the output. It also joins the results with SigninLogs and AADNonInteractiveUserSignInLogs based on the SignInActivityId and UniqueTokenIdentifier.

Jose Sebastián Canós
Released: November 15, 2023
Tables
Keywords
Operators