let AlertLinks = SecurityAlert
| summarize hint.strategy = shuffle arg_max(TimeGenerated, *), NumberOfUpdates = count() by SystemAlertId
| mv-expand todynamic(Entities)
| where Entities["Type"] =~ "account"
| extend Name = tostring(tolower(Entities["Name"])), NTDomain = tostring(Entities["NTDomain"]), UPNSuffix = tostring(Entities["UPNSuffix"]), AadUserId = tostring(Entities["AadUserId"]), AadTenantId = tostring(Entities["AadTenantId"]),
Sid = tostring(Entities["Sid"]), IsDomainJoined = tobool(Entities["IsDomainJoined"]), Host = tostring(Entities["Host"])
| extend UPN = iff(Name != "" and UPNSuffix != "", strcat(Name, "@", UPNSuffix), "")
| extend Href_ = tostring(parse_json(ExtendedLinks)[0].Href)
| where UPN <> ""
| summarize PreciousSecurityAlertLinks=make_set(AlertLink) by UPN;
SecurityAlert
| where ProductName == "Microsoft 365 Insider Risk Management"
| summarize hint.strategy = shuffle arg_max(TimeGenerated, *), NumberOfUpdates = count() by SystemAlertId
| mv-expand todynamic(Entities)
| where Entities["Type"] =~ "account"
| extend Name = tostring(tolower(Entities["Name"])), NTDomain = tostring(Entities["NTDomain"]), UPNSuffix = tostring(Entities["UPNSuffix"]), AadUserId = tostring(Entities["AadUserId"]), AadTenantId = tostring(Entities["AadTenantId"]),
Sid = tostring(Entities["Sid"]), IsDomainJoined = tobool(Entities["IsDomainJoined"]), Host = tostring(Entities["Host"])
| extend UPN = iff(Name != "" and UPNSuffix != "", strcat(Name, "@", UPNSuffix), "")
| extend Href_ = tostring(parse_json(ExtendedLinks)[0].Href)
| join kind=inner (AlertLinks) on UPN
| extend UserPrincipalName = UPN
| extend PreviousAlertsLinks = strcat(PreciousSecurityAlertLinks)
// | lookup kind=inner _GetWatchlist('<Your Watchlist Name>') on $left.UserPrincipalName == $right.SearchKey
| project UserPrincipalName, AlertName, ProductName, Tactics, Status, AlertLink, PreviousAlertsLinks, TimeGenerated
| sort by TimeGenerated desc
| extend AccountName = tostring(split(UserPrincipalName, "@")[0]), AccountUPNSuffix = tostring(split(UserPrincipalName, "@")[1])
queryFrequency: 6h
entityMappings:
- entityType: Account
fieldMappings:
- columnName: UserPrincipalName
identifier: FullName
- columnName: AccountName
identifier: Name
- columnName: AccountUPNSuffix
identifier: UPNSuffix
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/MicrosoftPurviewInsiderRiskManagement/Analytic Rules/InsiderRiskM365IRMAlertObserved.yaml
kind: Scheduled
queryPeriod: 6h
tactics:
- Execution
name: Insider Risk_Microsoft Purview Insider Risk Management Alert Observed
triggerThreshold: 0
requiredDataConnectors:
- connectorId: OfficeATP
dataTypes:
- SecurityAlert (Office 365)
eventGroupingSettings:
aggregationKind: SingleAlert
triggerOperator: gt
version: 1.1.3
description: |
'This alert is triggered when a Microsoft Purview Insider Risk Management alert is recieved in Microsoft Sentinel via the Microsoft Purview Insider Risk Management Connector. The alert extracts usernames from security alerts to provide UserPrincipalName, Alert Name, Reporting Product Name, Status, Alert Link, Previous Alerts Links, Time Generated. There is an option for configuration of correlations against Microsoft Sentinel watchlists. For more information, see [Learn about insider risk management](https://docs.microsoft.com/microsoft-365/compliance/insider-risk-management)'
query: |
let AlertLinks = SecurityAlert
| summarize hint.strategy = shuffle arg_max(TimeGenerated, *), NumberOfUpdates = count() by SystemAlertId
| mv-expand todynamic(Entities)
| where Entities["Type"] =~ "account"
| extend Name = tostring(tolower(Entities["Name"])), NTDomain = tostring(Entities["NTDomain"]), UPNSuffix = tostring(Entities["UPNSuffix"]), AadUserId = tostring(Entities["AadUserId"]), AadTenantId = tostring(Entities["AadTenantId"]),
Sid = tostring(Entities["Sid"]), IsDomainJoined = tobool(Entities["IsDomainJoined"]), Host = tostring(Entities["Host"])
| extend UPN = iff(Name != "" and UPNSuffix != "", strcat(Name, "@", UPNSuffix), "")
| extend Href_ = tostring(parse_json(ExtendedLinks)[0].Href)
| where UPN <> ""
| summarize PreciousSecurityAlertLinks=make_set(AlertLink) by UPN;
SecurityAlert
| where ProductName == "Microsoft 365 Insider Risk Management"
| summarize hint.strategy = shuffle arg_max(TimeGenerated, *), NumberOfUpdates = count() by SystemAlertId
| mv-expand todynamic(Entities)
| where Entities["Type"] =~ "account"
| extend Name = tostring(tolower(Entities["Name"])), NTDomain = tostring(Entities["NTDomain"]), UPNSuffix = tostring(Entities["UPNSuffix"]), AadUserId = tostring(Entities["AadUserId"]), AadTenantId = tostring(Entities["AadTenantId"]),
Sid = tostring(Entities["Sid"]), IsDomainJoined = tobool(Entities["IsDomainJoined"]), Host = tostring(Entities["Host"])
| extend UPN = iff(Name != "" and UPNSuffix != "", strcat(Name, "@", UPNSuffix), "")
| extend Href_ = tostring(parse_json(ExtendedLinks)[0].Href)
| join kind=inner (AlertLinks) on UPN
| extend UserPrincipalName = UPN
| extend PreviousAlertsLinks = strcat(PreciousSecurityAlertLinks)
// | lookup kind=inner _GetWatchlist('<Your Watchlist Name>') on $left.UserPrincipalName == $right.SearchKey
| project UserPrincipalName, AlertName, ProductName, Tactics, Status, AlertLink, PreviousAlertsLinks, TimeGenerated
| sort by TimeGenerated desc
| extend AccountName = tostring(split(UserPrincipalName, "@")[0]), AccountUPNSuffix = tostring(split(UserPrincipalName, "@")[1])
relevantTechniques:
- T1204
id: 69660e65-0e5c-4700-8b99-5caf59786606
incidentConfiguration:
groupingConfiguration:
lookbackDuration: 3d
enabled: true
groupByEntities:
- Account
matchingMethod: Selected
reopenClosedIncident: true
createIncident: true
severity: High