Multiple Activity From Anonymous IP Addresses
Query
https://learn.microsoft.com/en-us/defender-cloud-apps/anomaly-detection-policy
let query_frequency = 5m;
let query_period = 2d;
AADUserRiskEvents
| where TimeGenerated > ago(query_period)
| where Source == "MicrosoftCloudAppSecurity" and RiskEventType == "riskyIPAddress"
| summarize FirstTimeGenerated = min(TimeGenerated), arg_max(TimeGenerated, *) by Id
| where FirstTimeGenerated > ago(query_frequency)
| mv-apply Auxiliar = AdditionalInfo on (
summarize AdditionalInfoBag = make_bag(bag_pack(tostring(Auxiliar["Key"]), Auxiliar["Value"]))
)
| extend VendorOriginalId = tostring(split(tostring(AdditionalInfoBag["alertUrl"]), "/")[-1])
| project
//TimeGenerated,
ActivityDateTime,
DetectedDateTime,
Source,
Activity,
DetectionTimingType,
UserDisplayName,
UserPrincipalName,
UserId,
IpAddress,
RequestId,
CorrelationId,
TokenIssuerType,
RiskEventType,
RiskDetail,
RiskLevel,
RiskState,
AdditionalInfo,
Id,
VendorOriginalId
| extend AltAlertLink = strcat("https://entra.microsoft.com/#blade/Microsoft_AAD_IAM/RiskDetectionsBlade/riskState~/[]/userId/", UserId, "/riskLevel/[]/daysBack/90")// Someone wrote "90s" incorrectly in Defender XDR portal
| join kind=leftouter (
SecurityAlert
| where ProviderName == "MCAS" and ProductName == "Microsoft Cloud App Security"// and AlertType == "MCAS_ALERT_ANUBIS_???"
| summarize arg_max(TimeGenerated, *) by VendorOriginalId
| project
AlertName,
AlertSeverity,
Description,
AlertStatus = Status,
Entities,
ExtendedProperties,
VendorName,
ProviderName,
ProductName,
ProductComponentName,
RemediationSteps,
Tactics,
Techniques,
SubTechniques,
VendorOriginalId,
SystemAlertId,
CompromisedEntity,
AlertLink
) on VendorOriginalId
| extend
AlertLink = coalesce(AlertLink, AltAlertLink),
ExtendedPropertiesDynamic = todynamic(ExtendedProperties)
| as _Events
| lookup kind=leftouter (
union SigninLogs, AADNonInteractiveUserSignInLogs
| where TimeGenerated > ago(query_period)
//| where RiskEventTypes_V2 has "riskyIPAddress"
| where OriginalRequestId in (toscalar(_Events | summarize make_list(RequestId)))
| extend TimeReceived = _TimeReceived
| summarize arg_max(TimeReceived, *) by OriginalRequestId
| invoke UnifySignInLogs()
| project
TimeGenerated,
CreatedDateTime,
Type,
//UserDisplayName,
//UserPrincipalName,
//UserId,
AlternateSignInName,
SignInIdentifier,
UserType,
IPAddress,
AutonomousSystemNumber,
Location,
NetworkLocationDetails,
ResultType,
ResultSignature,
ResultDescription,
ClientAppUsed,
AppDisplayName,
ResourceDisplayName,
DeviceDetail,
UserAgent,
Status,
MfaDetail,
AuthenticationContextClassReferences,
AuthenticationDetails,
AuthenticationProcessingDetails,
AuthenticationProtocol,
AuthenticationRequirement,
AuthenticationRequirementPolicies,
SessionLifetimePolicies,
//TokenIssuerType,
IncomingTokenType,
TokenProtectionStatusDetails,
ConditionalAccessStatus,
ConditionalAccessPolicies,
SignInLogs_RiskDetail = RiskDetail,
RiskEventTypes,
RiskEventTypes_V2,
RiskLevelAggregated,
RiskLevelDuringSignIn,
SignInLogs_RiskState = RiskState,
HomeTenantId,
ResourceTenantId,
CrossTenantAccessType,
AppId,
ResourceIdentity,
UniqueTokenIdentifier,
SessionId,
OriginalRequestId//,
//CorrelationId
) on $left.RequestId == $right.OriginalRequestId
// | where case(
// // AlertStatus == "Resolved" and tostring(todynamic(ExtendedProperties)["State"]) == "Closed", false,
// SignInLogs_RiskState == "dismissed" and SignInLogs_RiskDetail == "aiConfirmedSigninSafe", false,
// SignInLogs_RiskState == "remediated" and SignInLogs_RiskDetail == "userPassedMFADrivenByRiskBasedPolicy", false,
// true
// )
| project
//TimeGenerated,
ActivityDateTime,
DetectedDateTime,
Source,
Activity,
DetectionTimingType,
UserDisplayName,
UserPrincipalName,
UserId,
IpAddress,
RequestId,
CorrelationId,
TokenIssuerType,
RiskEventType,
RiskDetail,
RiskLevel,
RiskState,
AdditionalInfo,
Id,
AlertName,
AlertSeverity,
Description,
AlertStatus,
Entities,
ExtendedProperties,
VendorName,
ProviderName,
ProductName,
ProductComponentName,
RemediationSteps,
Tactics,
Techniques,
SubTechniques,
VendorOriginalId,
SystemAlertId,
CompromisedEntity,
AlertLink,
TimeGenerated,
CreatedDateTime,
Type,
//UserDisplayName,
//UserPrincipalName,
//UserId,
AlternateSignInName,
SignInIdentifier,
UserType,
IPAddress,
AutonomousSystemNumber,
Location,
NetworkLocationDetails,
ResultType,
ResultSignature,
ResultDescription,
ClientAppUsed,
AppDisplayName,
ResourceDisplayName,
DeviceDetail,
UserAgent,
Status,
MfaDetail,
AuthenticationContextClassReferences,
AuthenticationDetails,
AuthenticationProcessingDetails,
AuthenticationProtocol,
AuthenticationRequirement,
AuthenticationRequirementPolicies,
SessionLifetimePolicies,
//TokenIssuerType,
IncomingTokenType,
TokenProtectionStatusDetails,
ConditionalAccessStatus,
ConditionalAccessPolicies,
SignInLogs_RiskDetail,
RiskEventTypes,
RiskEventTypes_V2,
RiskLevelAggregated,
RiskLevelDuringSignIn,
SignInLogs_RiskState,
HomeTenantId,
ResourceTenantId,
CrossTenantAccessType,
AppId,
ResourceIdentity,
UniqueTokenIdentifier,
SessionId//,
//OriginalRequestId,
//CorrelationIdExplanation
This KQL (Kusto Query Language) query is designed to analyze and correlate security events related to risky IP addresses from Azure Active Directory (AAD) and Microsoft Cloud App Security (MCAS). Here's a simplified breakdown of what the query does:
-
Define Timeframes:
query_frequencyis set to 5 minutes.query_periodis set to 2 days.
-
Filter AAD User Risk Events:
- It retrieves events from the
AADUserRiskEventstable where the events are generated within the last 2 days. - It specifically looks for events sourced from "MicrosoftCloudAppSecurity" with a risk event type of "riskyIPAddress".
- It retrieves events from the
-
Summarize Events:
- For each event, it identifies the first occurrence and the most recent occurrence, grouping by the event ID.
- Filters out events that first occurred more than 5 minutes ago.
-
Extract Additional Information:
- It processes additional information from the events to create a structured data bag.
- Extracts a unique identifier (
VendorOriginalId) from the alert URL.
-
Project Relevant Fields:
- Selects specific fields to include in the output, such as user details, risk information, and additional info.
-
Create Alternative Alert Link:
- Constructs an alternative alert link for each event.
-
Join with Security Alerts:
- Performs a left outer join with the
SecurityAlerttable to enrich the data with alert details from MCAS. - Projects additional alert-related fields.
- Performs a left outer join with the
-
Join with Sign-in Logs:
- Looks up sign-in logs from
SigninLogsandAADNonInteractiveUserSignInLogstables to correlate sign-in activities with the risk events. - Filters and projects relevant sign-in details.
- Looks up sign-in logs from
-
Final Projection:
- The final output includes a comprehensive set of fields from both the risk events and the correlated sign-in logs, providing a detailed view of each incident.
Overall, this query is used to identify and analyze risky IP address activities, correlate them with security alerts and sign-in logs, and provide detailed insights into potential security threats.
Details

Jose Sebastián Canós
Released: September 26, 2025
Tables
AADUserRiskEventsSecurityAlertSigninLogsAADNonInteractiveUserSignInLogs
Keywords
AADUserRiskEventsSecurityAlertSigninLogsAADNonInteractiveUserSignInLogsMicrosoftCloudAppSecurityRiskyIPAddressMCASUserIpAddressDeviceAppResourceLocationNetworkAuthenticationSessionTenantTokenAlertRiskSignInRequestCorrelationVendorProviderProductCompromisedEntityExtendedPropertiesRemediationStepsTacticsTechniquesSubTechniquesConditionalAccessMfaUserAgentClientAppAppDisplayNameResourceDisplayNameDeviceDetailAutonomousSystemNumberNetworkLocationDetailsResultTypeResultSignatureResultDescriptionAuthenticationContextClassReferencesAuthenticationDetailsAuthenticationProcessingDetailsAuthenticationProtocolAuthenticationRequirementAuthenticationRequirementPoliciesSessionLifetimePoliciesTokenProtectionStatusDetailsConditionalAccessStatusConditionalAccessPoliciesRiskEventTypesRiskEventTypesV2RiskLevelAggregatedRiskLevelDuringSignInHomeTenantIdResourceTenantIdCrossTenantAccessTypeAppIdResourceIdentityUniqueTokenIdentifierSessionId
Operators
letagowheresummarizeminarg_maxmv-applymake_bagbag_packtostringsplitprojectextendstrcatjoincoalescetodynamicaslookupunionintoscalarinvoke