diff --git a/Workbooks/Images/Preview/UserEntityBehaviorAnalyticsBlack2.png b/Workbooks/Images/Preview/UserEntityBehaviorAnalyticsBlack2.png new file mode 100644 index 00000000000..4ccaef8d588 Binary files /dev/null and b/Workbooks/Images/Preview/UserEntityBehaviorAnalyticsBlack2.png differ diff --git a/Workbooks/Images/Preview/UserEntityBehaviorAnalyticsWhite2.png b/Workbooks/Images/Preview/UserEntityBehaviorAnalyticsWhite2.png new file mode 100644 index 00000000000..0faa722fd02 Binary files /dev/null and b/Workbooks/Images/Preview/UserEntityBehaviorAnalyticsWhite2.png differ diff --git a/Workbooks/UserEntityBehaviorAnalytics.json b/Workbooks/UserEntityBehaviorAnalytics.json index 54e46f63eeb..a60d21ca73c 100644 --- a/Workbooks/UserEntityBehaviorAnalytics.json +++ b/Workbooks/UserEntityBehaviorAnalytics.json @@ -1,761 +1,3109 @@ { - "styleSettings": {}, - "fromTemplateId": "sentinel-UserAndEntityBehaviorAnalytics", - "$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json", - "version": "Notebook/1.0", - "items": [ - { - "type": 1, - "content": { - "json": "# User and Entity Behavior Analytics\n---\n\nWelcome to the User and Entity Behavior Analytics workbook. The workbook provides a guided investigation\nfor entities based on open incidents, alerts and anomalies identified by the UEBA engine. " + "version": "Notebook/1.0", + "items": [ + { + "type": 1, + "content": { + "json": "# User and Entity Behavior Analytics\n---\n\nWelcome to the User and Entity Behavior Analytics workbook. The workbook provides a guided investigation\nfor entities based on open incidents, alerts and anomalies identified by the UEBA engine." + }, + "name": "Title Text" }, - "name": "text - 2" - }, - { - "type": 9, - "content": { - "version": "KqlParameterItem/1.0", - "parameters": [ - { - "id": "36cdaf52-4303-405d-ac9c-de2037db99c3", - "version": "KqlParameterItem/1.0", - "name": "TimeRange", - "label": "Time Range", - "type": 4, - "value": { - "durationMs": 2419200000 - }, - "typeSettings": { - "selectableValues": [ - { - "durationMs": 1800000 - }, - { - "durationMs": 3600000 - }, - { - "durationMs": 14400000 - }, - { - "durationMs": 43200000 - }, - { - "durationMs": 86400000 - }, - { - "durationMs": 172800000 - }, - { - "durationMs": 259200000 - }, - { - "durationMs": 604800000 - }, - { - "durationMs": 1209600000 - }, - { - "durationMs": 2419200000 - }, - { - "durationMs": 2592000000 - }, - { - "durationMs": 5184000000 - }, - { - "durationMs": 7776000000 - } - ] + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "36cdaf52-4303-405d-ac9c-de2037db99c3", + "version": "KqlParameterItem/1.0", + "name": "TimeRange", + "label": "Time Range", + "type": 4, + "isRequired": true, + "typeSettings": { + "selectableValues": [ + { + "durationMs": 172800000 + }, + { + "durationMs": 259200000 + }, + { + "durationMs": 604800000 + }, + { + "durationMs": 1209600000 + }, + { + "durationMs": 2592000000 + } + ], + "allowCustom": true + }, + "timeContext": { + "durationMs": 86400000 + }, + "value": { + "durationMs": 1209600000 + } }, - "timeContext": { - "durationMs": 86400000 + { + "id": "c4470c37-5a8a-4ecd-8ece-5e98db8e8a92", + "version": "KqlParameterItem/1.0", + "name": "Help", + "label": "Show Help", + "type": 10, + "description": "This will show some help information to help you understand the page you are on", + "isRequired": true, + "value": "Yes", + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "jsonData": "[{ \"value\": \"Yes\", \"label\": \"Yes\"},\r\n {\"value\": \"No\", \"label\": \"No\", \"selected\":true }]" } - } - ], - "style": "pills", - "queryType": 0, - "resourceType": "microsoft.operationalinsights/workspaces" - }, - "name": "parameters - 2" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "SecurityIncident\r\n| where TimeGenerated {TimeRange:query}\r\n| summarize hint.strategy = shuffle arg_max(LastModifiedTime, *) by IncidentNumber\r\n| where Status == \"New\" or Status == \"Active\"\r\n| summarize IncidentCount=count() \r\n| project \"Open Incidents\", IncidentCount", - "size": 4, - "timeContext": { - "durationMs": 2419200000 + ], + "style": "pills", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces" }, - "timeContextFromParameter": "TimeRange", - "queryType": 0, - "resourceType": "microsoft.operationalinsights/workspaces", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Column1" - }, - "leftContent": { - "columnMatch": "IncidentCount", - "formatter": 12, - "formatOptions": { - "palette": "auto" - }, - "numberFormat": { - "unit": 0, - "options": { - "style": "decimal" - } - } - }, - "showBorder": false, - "size": "auto" - } + "name": "TimeRangeParameterDefinition" }, - "customWidth": "10", - "name": "query - 16" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "let TotalAlertsCount = SecurityIncident\r\n| where TimeGenerated {TimeRange:query}\r\n| summarize hint.strategy = shuffle arg_max(LastModifiedTime, *) by IncidentNumber\r\n| where Status == \"New\" or Status == \"Active\"\r\n| mv-expand AlertIds\r\n| extend AlertId = tostring(AlertIds)\r\n| join kind= innerunique ( \r\nSecurityAlert | where TimeGenerated {TimeRange:query}) on $left.AlertId == $right.SystemAlertId\r\n| summarize hint.strategy = shuffle arg_max(TimeGenerated,*), NumberOfUpdates = count() by SystemAlertId\r\n| summarize AlertCount=count()\r\n| project \"Alert Count\",AlertCount;\r\nTotalAlertsCount\r\n", - "size": 4, - "timeContext": { - "durationMs": 2419200000 + { + "type": 1, + "content": { + "json": "See below how many incidents and alerts were created during the time range selected in the time range picker above. Likewise, you will see the number of Anomalies that were triggered. To learn more about Anomalies, please click [here](https://learn.microsoft.com/en-us/azure/sentinel/work-with-anomaly-rules).", + "style": "info" }, - "timeContextFromParameter": "TimeRange", - "queryType": 0, - "resourceType": "microsoft.operationalinsights/workspaces", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Column1", - "formatter": 1 - }, - "leftContent": { - "columnMatch": "AlertCount", - "formatter": 12, - "formatOptions": { - "palette": "auto" - } - }, - "showBorder": false, - "size": "auto" - } - }, - "customWidth": "10", - "name": "query - 18" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "let AnomalousSigninActivity = BehaviorAnalytics\r\n| where TimeGenerated {TimeRange:query}\r\n| where ActionType == \"Sign-in\"\r\n| where (UsersInsights.NewAccount == True or UsersInsights.DormantAccount == True) and (\r\n ActivityInsights.FirstTimeUserAccessedResource == True and ActivityInsights.ResourceUncommonlyAccessedAmongPeers == True\r\nor ActivityInsights.FirstTimeUserUsedApp == True and ActivityInsights.AppUncommonlyUsedAmongPeers == False)\r\n| join (\r\nSigninLogs | where TimeGenerated {TimeRange:query} | where Status.errorCode == 0 or Status.errorCode == 0 and RiskDetail != \"none\"\r\n) on $left.SourceRecordId == $right._ItemId\r\n| extend UserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\r\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName)\r\n| extend AnomalyName = \"Anomalous Successful Logon\",\r\n Tactic = \"Persistence\",\r\n Technique = \"Valid Accounts\",\r\n SubTechnique = \"\",\r\n Description = \"Successful Sign-in with one or more of the following indications: sign by new or recently dormant accounts and sign in with resource for the first time (while none of their peers did) or to an app for the first time (while none of their peers did) or performed by a user with Risk indicaiton from AAD\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights, ResourceDisplayName,AppDisplayName,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \r\nlet critical = dynamic(['9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3','c4e39bd9-1100-46d3-8c65-fb160da0071f','158c047a-c907-4556-b7ef-446551a6b5f7','62e90394-69f5-4237-9190-012177145e10','d29b2b05-8046-44ba-8758-1e26182fcf32','729827e3-9c14-49f7-bb1b-9608f156bbb8','966707d0-3269-4727-9be2-8c3a10f19b9d','194ae4cb-b126-40b2-bd5b-6091b380977d','fe930be7-5e62-47db-91af-98c3a49a38b1']);\r\nlet high = dynamic(['cf1c38e5-3621-4004-a7cb-879624dced7c','7495fdc4-34c4-4d15-a289-98788ce399fd','aaf43236-0c0d-4d5f-883a-6955382ac081','3edaf663-341e-4475-9f94-5c398ef6c070','7698a772-787b-4ac8-901f-60d6b08affd2','b1be1c3e-b65d-4f19-8427-f6fa0d97feb9','9f06204d-73c1-4d4c-880a-6edb90606fd8','29232cdf-9323-42fd-ade2-1d097af3e4de','be2f45a1-457d-42af-a067-6ec1fa63bc45','7be44c8a-adaf-4e2a-84d6-ab2649e08a13','e8611ab8-c189-46e8-94e1-60213ab1f814']);\r\nlet AnomalousRoleAssignment = AuditLogs\r\n| where TimeGenerated {TimeRange:query}\r\n| where OperationName == \"Add member to role\"\r\n| mv-expand TargetResources\r\n| extend RoleId = tostring(TargetResources.modifiedProperties[0].newValue)\r\n| where isnotempty(RoleId) and RoleId in (critical,high)\r\n| extend RoleName = tostring(TargetResources.modifiedProperties[1].newValue)\r\n| where isnotempty(RoleName)\r\n| extend TargetId = tostring(TargetResources.id)\r\n| extend Target = tostring(TargetResources.userPrincipalName)\r\n| join kind=inner ( BehaviorAnalytics\r\n | where TimeGenerated {TimeRange:query}\r\n | where ActionType == \"Add member to role\"\r\n | where UsersInsights.BlasrRadius == \"High\" or ActivityInsights.FirstTimeUserPerformedAction == true\r\n) on $left._ItemId == $right.SourceRecordId\r\n| extend AnomalyName = \"Anomalous Role Assignemt\",\r\n Tactic = \"Persistence\",\r\n Technique = \"Account Manipulation\",\r\n SubTechnique = \"\",\r\n Description = \"Adversaries may manipulate accounts to maintain access to victim systems. These actions include adding new accounts to high privilleged groups. Dragonfly 2.0, for example, added newly created accounts to the administrators group to maintain elevated access. The query below generates an output of all high Blast Radius users performing Add member to priveleged role, or ones that add users for the first time.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType, [\"TargetUser\"]=Target,RoleName,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority;let LogOns=materialize(\r\nBehaviorAnalytics\r\n| where TimeGenerated {TimeRange:query}\r\n| where ActivityType == \"LogOn\");\r\nlet AnomalousResourceAccess = LogOns\r\n| where ActionType == \"ResourceAccess\"\r\n| where ActivityInsights.FirstTimeUserLoggedOnToDevice == true\r\n| extend AnomalyName = \"Anomalous Resource Access\",\r\n Tactic = \"Lateral Movement\",\r\n Technique = \"\",\r\n SubTechnique = \"\",\r\n Description = \"Adversary may be trying to move through the environment. APT29 and APT32, for example, has used PtH & PtT techniques to lateral move around the network. The query below generates an output of all users performing an resource access (4624:3) to devices for the first time.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \r\nlet AnomalousRDPActivity = LogOns\r\n| where ActionType == \"RemoteInteractiveLogon\"\r\n| where ActivityInsights.FirstTimeUserLoggedOnToDevice == true\r\n| extend AnomalyName = \"Anomalous RDP Activity\",\r\n Tactic = \"Lateral Movement\",\r\n Technique = \"\",\r\n SubTechnique = \"\",\r\n Description = \"Adversaries may use Valid Accounts to log into a computer using the Remote Desktop Protocol (RDP). The adversary may then perform actions as the logged-on user. FIN10, for example, has used RDP to move laterally to systems in the victim environment. The query below generates an output of all users performing a remote interactive logon (4624:10) to a device for the first time.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \r\nlet AnomalousLogintoDevices = LogOns\r\n| where ActionType == \"InteractiveLogon\"\r\n| where ActivityInsights.FirstTimeUserLoggedOnToDevice == true\r\n| where UsersInsights.DormantAccount == true or DevicesInsights.LocalAdmin == true\r\n| extend AnomalyName = \"Anomalous Login To Devices\",\r\n Tactic = \"Privilege Escalation\",\r\n Technique = \"Valid Accounts\",\r\n SubTechnique = \"\",\r\n Description = \"Adversaries may steal the credentials of a specific user or service account using Credential Access techniques or capture credentials earlier in their reconnaissance process through social engineering for means of gaining Initial Access. APT33, for example, has used valid accounts for initial access and privilege escalation. The query below generates an output of all administator users performing an interactive logon (4624:2) to a device for the first time.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \r\nlet AnomalousPasswordReset = BehaviorAnalytics\r\n| where TimeGenerated {TimeRange:query}\r\n| where ActionType == \"Reset user password\"\r\n| where ActivityInsights.FirstTimeUserPerformedAction == \"True\"\r\n| join (\r\nAuditLogs\r\n | where TimeGenerated {TimeRange:query}\r\n | where OperationName == \"Reset user password\"\r\n) on $left.SourceRecordId == $right._ItemId\r\n| mv-expand TargetResources\r\n| extend Target = iff(tostring(TargetResources.userPrincipalName) contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(TargetResources.userPrincipalName, \"#\")[0])),TargetResources.userPrincipalName),tostring(TargetResources.userPrincipalName)\r\n| extend UserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\r\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName)\r\n| extend AnomalyName = \"Anomalous Password Reset\",\r\n Tactic = \"Impact\",\r\n Technique = \"Account Access Removal\",\r\n SubTechnique = \"\",\r\n Description = \"Adversaries may interrupt availability of system and network resources by inhibiting access to accounts utilized by legitimate users. Accounts may be deleted, locked, or manipulated (ex: changed credentials) to remove access to accounts. LockerGoga, for example, has been observed changing account passwords and logging off current users. The query below generates an output of all users performing Reset user password for the first time.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType, [\"TargetUser\"]=Target,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority\r\n| sort by TimeGenerated desc;\r\nlet AnomalousGeoLocationLogon = BehaviorAnalytics\r\n| where TimeGenerated {TimeRange:query}\r\n| where ActionType == \"Sign-in\"\r\n| where ActivityInsights.FirstTimeUserConnectedFromCountry == True and (ActivityInsights.FirstTimeConnectionFromCountryObservedInTenant == True or ActivityInsights.CountryUncommonlyConnectedFromAmongPeers == True)\r\n| join (\r\nSigninLogs\r\n | where TimeGenerated {TimeRange:query}\r\n) on $left.SourceRecordId == $right._ItemId\r\n| extend UserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\r\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName)\r\n| extend AnomalyName = \"Anomalous Successful Logon\",\r\n Tactic = \"Initial Access\",\r\n Technique = \"Valid Accounts\",\r\n SubTechnique = \"\",\r\n Description = \"Adversaries may steal the credentials of a specific user or service account using Credential Access techniques or capture credentials earlier in their reconnaissance process through social engineering for means of gaining Initial Access. APT33, for example, has used valid accounts for initial access. The query below generates an output of successful Sign-in performed by a user from a new geo location he has never connected from before, and none of his peers as well.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights, ResourceDisplayName,AppDisplayName ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \r\nlet AnomalousFailedLogon = BehaviorAnalytics\r\n| where TimeGenerated {TimeRange:query}\r\n| where ActivityType == \"LogOn\"\r\n| where UsersInsights.BlastRadius == \"High\"\r\n| join (\r\n SigninLogs \r\n | where TimeGenerated {TimeRange:query}\r\n | where Status.errorCode == 50126\r\n) on $left.SourceRecordId == $right._ItemId\r\n| extend UserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\r\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName)\r\n| extend AnomalyName = \"Anomalous Failed Logon\",\r\n Tactic = \"Credential Access\",\r\n Technique = \"Brute Force\",\r\n SubTechnique = \"Password Guessing\",\r\n Description = \"Adversaries with no prior knowledge of legitimate credentials within the system or environment may guess passwords to attempt access to accounts. Emotet, for example, has been observed using a hard coded list of passwords to brute force user accounts. The query below generates an output of all users with 'High' BlastRadius that perform failed Sign-in:Invalid username or password.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights, ResourceDisplayName,AppDisplayName ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \r\nlet AnomalousAADAccountManipulation = AuditLogs\r\n| where TimeGenerated {TimeRange:query}\r\n| where OperationName == \"Update user\"\r\n| mv-expand AdditionalDetails\r\n| where AdditionalDetails.key == \"UserPrincipalName\"\r\n| mv-expand TargetResources\r\n| extend RoleId = tostring(TargetResources.modifiedProperties[0].newValue)\r\n| where isnotempty(RoleId) and RoleId in (critical,high)\r\n| extend RoleName = tostring(TargetResources.modifiedProperties[1].newValue)\r\n| where isnotempty(RoleName)\r\n| extend TargetId = tostring(TargetResources.id)\r\n| extend Target = iff(tostring(TargetResources.userPrincipalName) contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(TargetResources.userPrincipalName, \"#\")[0])),TargetResources.userPrincipalName),tostring(TargetResources.userPrincipalName)\r\n| join kind=inner ( \r\n BehaviorAnalytics\r\n | where TimeGenerated {TimeRange:query}\r\n | where ActionType == \"Update user\"\r\n | where UsersInsights.BlasrRadius == \"High\" or ActivityInsights.FirstTimeUserPerformedAction == true\r\n) on $left._ItemId == $right.SourceRecordId\r\n| extend UserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\r\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName) \r\n| extend AnomalyName = \"Anomalous Account Manipulation\",\r\n Tactic = \"Persistence\",\r\n Technique = \"Account Manipulation\",\r\n SubTechnique = \"\",\r\n Description = \"Adversaries may manipulate accounts to maintain access to victim systems. These actions include adding new accounts to high privilleged groups. Dragonfly 2.0, for example, added newly created accounts to the administrators group to maintain elevated access. The query below generates an output of all high Blast Radius users performing 'Update user' (name change) to priveleged role, or ones that changed users for the first time.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType, [\"TargetUser\"]=Target,RoleName,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; let AnomalousAADAccountCreation = BehaviorAnalytics\r\n| where TimeGenerated {TimeRange:query}\r\n| where ActionType == \"Add user\"\r\n| where ActivityInsights.FirstTimeUserPerformedAction == True or ActivityInsights.FirstTimeActionPerformedInTenant == True or ActivityInsights.ActionUncommonlyPerformedAmongPeers == true\r\n| join(\r\nAuditLogs\r\n | where TimeGenerated {TimeRange:query} \r\n | where OperationName == \"Add user\"\r\n) on $left.SourceRecordId == $right._ItemId\r\n| mv-expand TargetResources\r\n| extend Target = iff(tostring(TargetResources.userPrincipalName) contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(TargetResources.userPrincipalName, \"#\")[0])),TargetResources.userPrincipalName),tostring(TargetResources.userPrincipalName)\r\n| extend DisplayName = tostring(UsersInsights.AccountDisplayName),\r\nUserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\r\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName)\r\n| extend AnomalyName = \"Anomalous Account Creation\",\r\n Tactic = \"Persistence\",\r\n Technique = \"Create Account\",\r\n SubTechnique = \"Cloud Account\",\r\n Description = \"Adversaries may create a cloud account to maintain access to victim systems. With a sufficient level of access, such accounts may be used to establish secondary credentialed access that does not require persistent remote access tools to be deployed on the system. The query below generates an output of all the users performing user creation for the first time and the target users that were created.\"\t\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType, [\"TargetUser\"]=Target,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority\r\n| sort by TimeGenerated desc;\r\nlet AnomalyTable = union kind=outer AnomalousSigninActivity, AnomalousRoleAssignment, AnomalousResourceAccess, AnomalousRDPActivity, AnomalousPasswordReset, AnomalousLogintoDevices, AnomalousGeoLocationLogon, AnomalousAADAccountManipulation, AnomalousAADAccountCreation, AnomalousFailedLogon;\r\nAnomalyTable\r\n| summarize AnomaliesCount=count()\r\n| project \"Anomalies Count\", AnomaliesCount", - "size": 4, - "timeContext": { - "durationMs": 2419200000 + "conditionalVisibility": { + "parameterName": "Help", + "comparison": "isEqualTo", + "value": "Yes" }, - "timeContextFromParameter": "TimeRange", - "queryType": 0, - "resourceType": "microsoft.operationalinsights/workspaces", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Column1", - "formatter": 1 - }, - "leftContent": { - "columnMatch": "AnomaliesCount", - "formatter": 12, - "formatOptions": { - "palette": "auto" - }, - "numberFormat": { - "unit": 17, - "options": { - "maximumSignificantDigits": 3, - "maximumFractionDigits": 2 - } - } - }, - "showBorder": false, - "size": "auto" - } + "name": "General info help message" }, - "customWidth": "10", - "name": "query - 17", - "styleSettings": { - "margin": "12" - } - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "let AnomalousSigninActivity = BehaviorAnalytics\r\n| where TimeGenerated {TimeRange:query}\r\n| where ActionType == \"Sign-in\"\r\n| where (UsersInsights.NewAccount == True or UsersInsights.DormantAccount == True) and (\r\n ActivityInsights.FirstTimeUserAccessedResource == True and ActivityInsights.ResourceUncommonlyAccessedAmongPeers == True\r\nor ActivityInsights.FirstTimeUserUsedApp == True and ActivityInsights.AppUncommonlyUsedAmongPeers == False)\r\n| join (\r\nSigninLogs | where TimeGenerated {TimeRange:query} | where Status.errorCode == 0 or Status.errorCode == 0 and RiskDetail != \"none\"\r\n) on $left.SourceRecordId == $right._ItemId\r\n| extend UserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\r\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName)\r\n| extend AnomalyName = \"Anomalous Successful Logon\",\r\n Tactic = \"Persistence\",\r\n Technique = \"Valid Accounts\",\r\n SubTechnique = \"\",\r\n Description = \"Successful Sign-in with one or more of the following indications: sign by new or recently dormant accounts and sign in with resource for the first time (while none of their peers did) or to an app for the first time (while none of their peers did) or performed by a user with Risk indicaiton from AAD\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights, ResourceDisplayName,AppDisplayName,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \r\nlet critical = dynamic(['9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3','c4e39bd9-1100-46d3-8c65-fb160da0071f','158c047a-c907-4556-b7ef-446551a6b5f7','62e90394-69f5-4237-9190-012177145e10','d29b2b05-8046-44ba-8758-1e26182fcf32','729827e3-9c14-49f7-bb1b-9608f156bbb8','966707d0-3269-4727-9be2-8c3a10f19b9d','194ae4cb-b126-40b2-bd5b-6091b380977d','fe930be7-5e62-47db-91af-98c3a49a38b1']);\r\nlet high = dynamic(['cf1c38e5-3621-4004-a7cb-879624dced7c','7495fdc4-34c4-4d15-a289-98788ce399fd','aaf43236-0c0d-4d5f-883a-6955382ac081','3edaf663-341e-4475-9f94-5c398ef6c070','7698a772-787b-4ac8-901f-60d6b08affd2','b1be1c3e-b65d-4f19-8427-f6fa0d97feb9','9f06204d-73c1-4d4c-880a-6edb90606fd8','29232cdf-9323-42fd-ade2-1d097af3e4de','be2f45a1-457d-42af-a067-6ec1fa63bc45','7be44c8a-adaf-4e2a-84d6-ab2649e08a13','e8611ab8-c189-46e8-94e1-60213ab1f814']);\r\nlet AnomalousRoleAssignment = AuditLogs\r\n| where TimeGenerated {TimeRange:query}\r\n| where OperationName == \"Add member to role\"\r\n| mv-expand TargetResources\r\n| extend RoleId = tostring(TargetResources.modifiedProperties[0].newValue)\r\n| where isnotempty(RoleId) and RoleId in (critical,high)\r\n| extend RoleName = tostring(TargetResources.modifiedProperties[1].newValue)\r\n| where isnotempty(RoleName)\r\n| extend TargetId = tostring(TargetResources.id)\r\n| extend Target = tostring(TargetResources.userPrincipalName)\r\n| join kind=inner ( BehaviorAnalytics\r\n | where TimeGenerated {TimeRange:query}\r\n | where ActionType == \"Add member to role\"\r\n | where UsersInsights.BlasrRadius == \"High\" or ActivityInsights.FirstTimeUserPerformedAction == true\r\n) on $left._ItemId == $right.SourceRecordId\r\n| extend AnomalyName = \"Anomalous Role Assignemt\",\r\n Tactic = \"Persistence\",\r\n Technique = \"Account Manipulation\",\r\n SubTechnique = \"\",\r\n Description = \"Adversaries may manipulate accounts to maintain access to victim systems. These actions include adding new accounts to high privilleged groups. Dragonfly 2.0, for example, added newly created accounts to the administrators group to maintain elevated access. The query below generates an output of all high Blast Radius users performing Add member to priveleged role, or ones that add users for the first time.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType, [\"TargetUser\"]=Target,RoleName,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority;let LogOns=materialize(\r\nBehaviorAnalytics\r\n| where TimeGenerated {TimeRange:query}\r\n| where ActivityType == \"LogOn\");\r\nlet AnomalousResourceAccess = LogOns\r\n| where ActionType == \"ResourceAccess\"\r\n| where ActivityInsights.FirstTimeUserLoggedOnToDevice == true\r\n| extend AnomalyName = \"Anomalous Resource Access\",\r\n Tactic = \"Lateral Movement\",\r\n Technique = \"\",\r\n SubTechnique = \"\",\r\n Description = \"Adversary may be trying to move through the environment. APT29 and APT32, for example, has used PtH & PtT techniques to lateral move around the network. The query below generates an output of all users performing an resource access (4624:3) to devices for the first time.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \r\nlet AnomalousRDPActivity = LogOns\r\n| where ActionType == \"RemoteInteractiveLogon\"\r\n| where ActivityInsights.FirstTimeUserLoggedOnToDevice == true\r\n| extend AnomalyName = \"Anomalous RDP Activity\",\r\n Tactic = \"Lateral Movement\",\r\n Technique = \"\",\r\n SubTechnique = \"\",\r\n Description = \"Adversaries may use Valid Accounts to log into a computer using the Remote Desktop Protocol (RDP). The adversary may then perform actions as the logged-on user. FIN10, for example, has used RDP to move laterally to systems in the victim environment. The query below generates an output of all users performing a remote interactive logon (4624:10) to a device for the first time.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \r\nlet AnomalousLogintoDevices = LogOns\r\n| where ActionType == \"InteractiveLogon\"\r\n| where ActivityInsights.FirstTimeUserLoggedOnToDevice == true\r\n| where UsersInsights.DormantAccount == true or DevicesInsights.LocalAdmin == true\r\n| extend AnomalyName = \"Anomalous Login To Devices\",\r\n Tactic = \"Privilege Escalation\",\r\n Technique = \"Valid Accounts\",\r\n SubTechnique = \"\",\r\n Description = \"Adversaries may steal the credentials of a specific user or service account using Credential Access techniques or capture credentials earlier in their reconnaissance process through social engineering for means of gaining Initial Access. APT33, for example, has used valid accounts for initial access and privilege escalation. The query below generates an output of all administator users performing an interactive logon (4624:2) to a device for the first time.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \r\nlet AnomalousPasswordReset = BehaviorAnalytics\r\n| where TimeGenerated {TimeRange:query}\r\n| where ActionType == \"Reset user password\"\r\n| where ActivityInsights.FirstTimeUserPerformedAction == \"True\"\r\n| join (\r\nAuditLogs\r\n | where TimeGenerated {TimeRange:query}\r\n | where OperationName == \"Reset user password\"\r\n) on $left.SourceRecordId == $right._ItemId\r\n| mv-expand TargetResources\r\n| extend Target = iff(tostring(TargetResources.userPrincipalName) contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(TargetResources.userPrincipalName, \"#\")[0])),TargetResources.userPrincipalName),tostring(TargetResources.userPrincipalName)\r\n| extend UserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\r\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName)\r\n| extend AnomalyName = \"Anomalous Password Reset\",\r\n Tactic = \"Impact\",\r\n Technique = \"Account Access Removal\",\r\n SubTechnique = \"\",\r\n Description = \"Adversaries may interrupt availability of system and network resources by inhibiting access to accounts utilized by legitimate users. Accounts may be deleted, locked, or manipulated (ex: changed credentials) to remove access to accounts. LockerGoga, for example, has been observed changing account passwords and logging off current users. The query below generates an output of all users performing Reset user password for the first time.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType, [\"TargetUser\"]=Target,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority\r\n| sort by TimeGenerated desc;\r\nlet AnomalousGeoLocationLogon = BehaviorAnalytics\r\n| where TimeGenerated {TimeRange:query}\r\n| where ActionType == \"Sign-in\"\r\n| where ActivityInsights.FirstTimeUserConnectedFromCountry == True and (ActivityInsights.FirstTimeConnectionFromCountryObservedInTenant == True or ActivityInsights.CountryUncommonlyConnectedFromAmongPeers == True)\r\n| join (\r\nSigninLogs\r\n | where TimeGenerated {TimeRange:query}\r\n) on $left.SourceRecordId == $right._ItemId\r\n| extend UserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\r\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName)\r\n| extend AnomalyName = \"Anomalous Successful Logon\",\r\n Tactic = \"Initial Access\",\r\n Technique = \"Valid Accounts\",\r\n SubTechnique = \"\",\r\n Description = \"Adversaries may steal the credentials of a specific user or service account using Credential Access techniques or capture credentials earlier in their reconnaissance process through social engineering for means of gaining Initial Access. APT33, for example, has used valid accounts for initial access. The query below generates an output of successful Sign-in performed by a user from a new geo location he has never connected from before, and none of his peers as well.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights, ResourceDisplayName,AppDisplayName ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \r\nlet AnomalousFailedLogon = BehaviorAnalytics\r\n| where TimeGenerated {TimeRange:query}\r\n| where ActivityType == \"LogOn\"\r\n| where UsersInsights.BlastRadius == \"High\"\r\n| join (\r\n SigninLogs \r\n | where TimeGenerated {TimeRange:query}\r\n | where Status.errorCode == 50126\r\n) on $left.SourceRecordId == $right._ItemId\r\n| extend UserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\r\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName)\r\n| extend AnomalyName = \"Anomalous Failed Logon\",\r\n Tactic = \"Credential Access\",\r\n Technique = \"Brute Force\",\r\n SubTechnique = \"Password Guessing\",\r\n Description = \"Adversaries with no prior knowledge of legitimate credentials within the system or environment may guess passwords to attempt access to accounts. Emotet, for example, has been observed using a hard coded list of passwords to brute force user accounts. The query below generates an output of all users with 'High' BlastRadius that perform failed Sign-in:Invalid username or password.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights, ResourceDisplayName,AppDisplayName ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \r\nlet AnomalousAADAccountManipulation = AuditLogs\r\n| where TimeGenerated {TimeRange:query}\r\n| where OperationName == \"Update user\"\r\n| mv-expand AdditionalDetails\r\n| where AdditionalDetails.key == \"UserPrincipalName\"\r\n| mv-expand TargetResources\r\n| extend RoleId = tostring(TargetResources.modifiedProperties[0].newValue)\r\n| where isnotempty(RoleId) and RoleId in (critical,high)\r\n| extend RoleName = tostring(TargetResources.modifiedProperties[1].newValue)\r\n| where isnotempty(RoleName)\r\n| extend TargetId = tostring(TargetResources.id)\r\n| extend Target = iff(tostring(TargetResources.userPrincipalName) contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(TargetResources.userPrincipalName, \"#\")[0])),TargetResources.userPrincipalName),tostring(TargetResources.userPrincipalName)\r\n| join kind=inner ( \r\n BehaviorAnalytics\r\n | where TimeGenerated {TimeRange:query}\r\n | where ActionType == \"Update user\"\r\n | where UsersInsights.BlasrRadius == \"High\" or ActivityInsights.FirstTimeUserPerformedAction == true\r\n) on $left._ItemId == $right.SourceRecordId\r\n| extend UserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\r\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName) \r\n| extend AnomalyName = \"Anomalous Account Manipulation\",\r\n Tactic = \"Persistence\",\r\n Technique = \"Account Manipulation\",\r\n SubTechnique = \"\",\r\n Description = \"Adversaries may manipulate accounts to maintain access to victim systems. These actions include adding new accounts to high privilleged groups. Dragonfly 2.0, for example, added newly created accounts to the administrators group to maintain elevated access. The query below generates an output of all high Blast Radius users performing 'Update user' (name change) to priveleged role, or ones that changed users for the first time.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType, [\"TargetUser\"]=Target,RoleName,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; let AnomalousAADAccountCreation = BehaviorAnalytics\r\n| where TimeGenerated {TimeRange:query}\r\n| where ActionType == \"Add user\"\r\n| where ActivityInsights.FirstTimeUserPerformedAction == True or ActivityInsights.FirstTimeActionPerformedInTenant == True or ActivityInsights.ActionUncommonlyPerformedAmongPeers == true\r\n| join(\r\nAuditLogs\r\n | where TimeGenerated {TimeRange:query} \r\n | where OperationName == \"Add user\"\r\n) on $left.SourceRecordId == $right._ItemId\r\n| mv-expand TargetResources\r\n| extend Target = iff(tostring(TargetResources.userPrincipalName) contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(TargetResources.userPrincipalName, \"#\")[0])),TargetResources.userPrincipalName),tostring(TargetResources.userPrincipalName)\r\n| extend DisplayName = tostring(UsersInsights.AccountDisplayName),\r\nUserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\r\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName)\r\n| extend AnomalyName = \"Anomalous Account Creation\",\r\n Tactic = \"Persistence\",\r\n Technique = \"Create Account\",\r\n SubTechnique = \"Cloud Account\",\r\n Description = \"Adversaries may create a cloud account to maintain access to victim systems. With a sufficient level of access, such accounts may be used to establish secondary credentialed access that does not require persistent remote access tools to be deployed on the system. The query below generates an output of all the users performing user creation for the first time and the target users that were created.\"\t\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType, [\"TargetUser\"]=Target,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority\r\n| sort by TimeGenerated desc;\r\nlet AnomalyTable = union kind=outer AnomalousSigninActivity, AnomalousRoleAssignment, AnomalousResourceAccess, AnomalousRDPActivity, AnomalousPasswordReset, AnomalousLogintoDevices, AnomalousGeoLocationLogon, AnomalousAADAccountManipulation, AnomalousAADAccountCreation, AnomalousFailedLogon;\r\n\r\n\r\nlet TotalAnomaliesCount = AnomalyTable\r\n| make-series count() default=0 on TimeGenerated from {TimeRange:start} to {TimeRange:end} step 1d\r\n| extend series = \"Anomalies Trend\"\r\n| project series, count_, TimeGenerated ;\r\nlet TotalAlertsCount = SecurityIncident\r\n| where TimeGenerated {TimeRange:query}\r\n| summarize hint.strategy = shuffle arg_max(LastModifiedTime, *) by IncidentNumber\r\n| where Status == \"New\" or Status == \"Active\"\r\n| mv-expand AlertIds\r\n| extend AlertId = tostring(AlertIds)\r\n| join kind= innerunique ( \r\nSecurityAlert | where TimeGenerated {TimeRange:query}\r\n) on $left.AlertId == $right.SystemAlertId\r\n| summarize hint.strategy = shuffle arg_max(TimeGenerated,*), NumberOfUpdates = count() by SystemAlertId\r\n| make-series count() default=0 on TimeGenerated from {TimeRange:start} to {TimeRange:end} step 1d\r\n| extend series = \"Alerts Trend\"\r\n| project series, count_, TimeGenerated ;\r\nlet TotalIncidentsCount=SecurityIncident\r\n| summarize hint.strategy = shuffle arg_max(LastModifiedTime, *) by IncidentNumber\r\n| where Status == \"New\" or Status == \"Active\"\r\n| make-series count() default=0 on TimeGenerated from {TimeRange:start} to {TimeRange:end} step 1d \r\n| extend series = \"Incidents Trend\"\r\n| project series, count_, TimeGenerated;\r\nTotalIncidentsCount | union TotalAlertsCount, TotalAnomaliesCount\r\n\r\n\r\n", - "size": 1, - "timeContext": { - "durationMs": 2419200000 - }, - "timeContextFromParameter": "TimeRange", - "queryType": 0, - "resourceType": "microsoft.operationalinsights/workspaces", - "visualization": "linechart", - "chartSettings": { - "seriesLabelSettings": [ + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "title": "General Info", + "items": [ + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "title": "General Incident Summary", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "SecurityIncident\r\n| where TimeGenerated {TimeRange:query}\r\n| summarize hint.strategy = shuffle arg_max(LastModifiedTime, *) by IncidentNumber\r\n| where Status == \"New\" or Status == \"Active\"\r\n| summarize IncidentCount=count() \r\n| project \"New or active incidents\", IncidentCount", + "size": 4, + "timeContextFromParameter": "TimeRange", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Column1" + }, + "leftContent": { + "columnMatch": "IncidentCount", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "redDark" + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + "showBorder": false, + "size": "auto" + } + }, + "customWidth": "12", + "name": "GeneralInfo - Open Incidents", + "styleSettings": { + "maxWidth": "12" + } + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let TotalAlertsCount = SecurityIncident\r\n| where TimeGenerated {TimeRange:query}\r\n| summarize hint.strategy = shuffle arg_max(LastModifiedTime, *) by IncidentNumber\r\n| where Status == \"New\" or Status == \"Active\"\r\n| mv-expand AlertIds\r\n| extend AlertId = tostring(AlertIds)\r\n| join kind= innerunique ( \r\nSecurityAlert | where TimeGenerated {TimeRange:query}) on $left.AlertId == $right.SystemAlertId\r\n| where Status != \"Resolved\" or Status != \"Dismissed\" \r\n| summarize hint.strategy = shuffle arg_max(TimeGenerated,*), NumberOfUpdates = count() by SystemAlertId\r\n| summarize AlertCount=count()\r\n| project \"New or active alerts\",AlertCount;\r\nTotalAlertsCount\r\n", + "size": 4, + "timeContextFromParameter": "TimeRange", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Column1", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "AlertCount", + "formatter": 12, + "formatOptions": { + "palette": "redDark" + } + }, + "showBorder": false, + "size": "auto" + } + }, + "customWidth": "12", + "name": "GeneralInfo - Alert Count", + "styleSettings": { + "maxWidth": "12" + } + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "Anomalies\r\n| where TimeGenerated {TimeRange:query}\r\n| summarize AnomalyCount=count()\r\n| project \"Anomaly Count\", AnomalyCount", + "size": 4, + "timeContextFromParameter": "TimeRange", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Column1", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "AnomalyCount", + "formatter": 12, + "formatOptions": { + "palette": "redDark" + } + }, + "showBorder": false, + "size": "auto" + } + }, + "customWidth": "12", + "name": "GeneralInfo - Alert Count", + "styleSettings": { + "maxWidth": "12" + } + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let TotalAnomaliesCount = Anomalies\r\n| summarize by TenantId, TimeGenerated\r\n| make-series count() default=0 on TimeGenerated from {TimeRange:start} to {TimeRange:end} step 1d\r\n| extend series = \"Anomalies Trend\"\r\n| project series, count_, TimeGenerated ;\r\nlet TotalAlertsCount = SecurityIncident\r\n| where TimeGenerated {TimeRange:query}\r\n| summarize hint.strategy = shuffle arg_max(LastModifiedTime, *) by IncidentNumber\r\n| where Status == \"New\" or Status == \"Active\"\r\n| mv-expand AlertIds\r\n| extend AlertId = tostring(AlertIds)\r\n| join kind= innerunique ( \r\nSecurityAlert | where TimeGenerated {TimeRange:query}\r\n) on $left.AlertId == $right.SystemAlertId\r\n| summarize hint.strategy = shuffle arg_max(TimeGenerated,*), NumberOfUpdates = count() by SystemAlertId\r\n| make-series count() default=0 on TimeGenerated from {TimeRange:start} to {TimeRange:end} step 1d\r\n| extend series = \"Alerts Trend\"\r\n| project series, count_, TimeGenerated ;\r\nlet TotalIncidentsCount=SecurityIncident\r\n| summarize hint.strategy = shuffle arg_max(LastModifiedTime, *) by IncidentNumber\r\n| where Status == \"New\" or Status == \"Active\"\r\n| make-series count() default=0 on TimeGenerated from {TimeRange:start} to {TimeRange:end} step 1d \r\n| extend series = \"Incidents Trend\"\r\n| project series, count_, TimeGenerated;\r\nTotalIncidentsCount | union TotalAlertsCount, TotalAnomaliesCount\r\n\r\n\r\n", + "size": 1, + "timeContextFromParameter": "TimeRange", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Incidents Trend", + "label": "Incidents", + "color": "red" + }, + { + "seriesName": "Alerts Trend", + "label": "Alerts", + "color": "orange" + }, + { + "seriesName": "Anomalies Trend", + "label": "Anomalies", + "color": "blueDark" + } + ] + } + }, + "customWidth": "60", + "name": "GeneralInfo - TimeSeries", + "styleSettings": { + "maxWidth": "60" + } + } + ] + }, + "customWidth": "100", + "name": "General Incident Summary", + "styleSettings": { + "maxWidth": "100" + } + }, { - "seriesName": "Incidents Trend", - "label": "Incidents Counts", - "color": "blue" + "type": 1, + "content": { + "json": "Below you will find the total number of anomalies, plus how many of those have an account or an IP entity. Note that we are also counting anomalies that involve known hosts, but as are currently not mapped as entities. The query for \"Anomalies with hosts\" counts the hosts that were parsed out of the following entity enrichments: \"DeviceUncommonlyUsedByUser\", \"DeviceUncommonlyUsedAmongPeers\", \"DeviceUncommonlyUsedInTenant\". See more about these [here](https://learn.microsoft.com/en-us/azure/sentinel/ueba-reference#device-used-to-connect).\r\n", + "style": "info" + }, + "conditionalVisibility": { + "parameterName": "Help", + "comparison": "isEqualTo", + "value": "Yes" + }, + "name": "Anomalies help" }, { - "seriesName": "Alerts Trend", - "label": "Alerts Counts", - "color": "redBright" + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "title": "Anomaly Summary", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "Anomalies\r\n| where TimeGenerated {TimeRange:query}\r\n| count", + "size": 4, + "title": "Total anomalies", + "timeContextFromParameter": "TimeRange", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "palette": "blue" + } + }, + "showBorder": false + } + }, + "customWidth": "20", + "name": "AnomalyInfo - Anomalies" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "Anomalies\r\n| where TimeGenerated {TimeRange:query}\r\n| where tostring(Entities) contains '\"Type\":\"account\"'\r\n| count", + "size": 4, + "title": "Anomalies with account entity", + "timeContextFromParameter": "TimeRange", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "visualization": "tiles", + "tileSettings": { + "titleContent": {}, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "palette": "blue" + } + }, + "showBorder": false + } + }, + "customWidth": "20", + "name": "AnomalyInfo - Account Anomaly" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "Anomalies\r\n| where TimeGenerated {TimeRange:query}\r\n| where tostring(Entities) contains '\"Type\":\"ip\"'\r\n| count", + "size": 4, + "title": "Anomalies with IP entity", + "timeContextFromParameter": "TimeRange", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "visualization": "tiles", + "tileSettings": { + "titleContent": {}, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "palette": "blue" + } + }, + "showBorder": false + } + }, + "customWidth": "20", + "name": "AnomalyInfo - IP Anomaly" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Currently there is no mapping with hosts\r\n//We know that in the following anomalies there is a host present: \"FirstTimeUserConnectedFromDevice\", \"DeviceUncommonlyUsedByUser\", \"DeviceUncommonlyUsedAmongPeers\", \"FirstTimeDeviceObservedInTenant\", \"DeviceUncommonlyUsedInTenant\"\r\n//We only look for \"DeviceUncommonlyUsedByUser\", \"DeviceUncommonlyUsedAmongPeers\", \"DeviceUncommonlyUsedInTenant\" though since the other two only state PII instead of the host itself\r\nlet Name = dynamic([\"DeviceUncommonlyUsedByUser\", \"DeviceUncommonlyUsedAmongPeers\", \"DeviceUncommonlyUsedInTenant\"]) ;\r\nAnomalies\r\n| where TimeGenerated {TimeRange:query}\r\n| mv-expand AnomalyReasons\r\n| where tostring(AnomalyReasons.Name) in (Name)\r\n| count", + "size": 4, + "title": "Anomalies with a host", + "timeContextFromParameter": "TimeRange", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "visualization": "tiles", + "tileSettings": { + "titleContent": {}, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "palette": "blue" + } + }, + "showBorder": false + } + }, + "customWidth": "20", + "name": "AnomalyInfo - Host Anomaly" + } + ] + }, + "name": "Anomaly Summary" } ] - } - }, - "customWidth": "70", - "name": "query - 19" - }, - { - "type": 1, - "content": { - "json": "## Top users to investigate - by Incidents, alerts & anomalies\r\n---\r\n" - }, - "name": "text - 3" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "let AnomalousSigninActivity = BehaviorAnalytics\n| where TimeGenerated {TimeRange:query}\n| where ActionType == \"Sign-in\"\n| where (UsersInsights.NewAccount == True or UsersInsights.DormantAccount == True) and (\n ActivityInsights.FirstTimeUserAccessedResource == True and ActivityInsights.ResourceUncommonlyAccessedAmongPeers == True\nor ActivityInsights.FirstTimeUserUsedApp == True and ActivityInsights.AppUncommonlyUsedAmongPeers == False)\n| join (\nSigninLogs | where TimeGenerated {TimeRange:query} | where Status.errorCode == 0 or Status.errorCode == 0 and RiskDetail != \"none\"\n) on $left.SourceRecordId == $right._ItemId\n| extend UserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName)\n| extend AnomalyName = \"Anomalous Successful Logon\",\n Tactic = \"Persistence\",\n Technique = \"Valid Accounts\",\n SubTechnique = \"\",\n Description = \"Successful Sign-in with one or more of the following indications: sign by new or recently dormant accounts and sign in with resource for the first time (while none of their peers did) or to an app for the first time (while none of their peers did) or performed by a user with Risk indicaiton from AAD\"\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights, ResourceDisplayName,AppDisplayName,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \nlet critical = dynamic(['9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3','c4e39bd9-1100-46d3-8c65-fb160da0071f','158c047a-c907-4556-b7ef-446551a6b5f7','62e90394-69f5-4237-9190-012177145e10','d29b2b05-8046-44ba-8758-1e26182fcf32','729827e3-9c14-49f7-bb1b-9608f156bbb8','966707d0-3269-4727-9be2-8c3a10f19b9d','194ae4cb-b126-40b2-bd5b-6091b380977d','fe930be7-5e62-47db-91af-98c3a49a38b1']);\nlet high = dynamic(['cf1c38e5-3621-4004-a7cb-879624dced7c','7495fdc4-34c4-4d15-a289-98788ce399fd','aaf43236-0c0d-4d5f-883a-6955382ac081','3edaf663-341e-4475-9f94-5c398ef6c070','7698a772-787b-4ac8-901f-60d6b08affd2','b1be1c3e-b65d-4f19-8427-f6fa0d97feb9','9f06204d-73c1-4d4c-880a-6edb90606fd8','29232cdf-9323-42fd-ade2-1d097af3e4de','be2f45a1-457d-42af-a067-6ec1fa63bc45','7be44c8a-adaf-4e2a-84d6-ab2649e08a13','e8611ab8-c189-46e8-94e1-60213ab1f814']);\nlet AnomalousRoleAssignment = AuditLogs\n| where TimeGenerated {TimeRange:query}\n| where OperationName == \"Add member to role\"\n| mv-expand TargetResources\n| extend RoleId = tostring(TargetResources.modifiedProperties[0].newValue)\n| where isnotempty(RoleId) and RoleId in (critical,high)\n| extend RoleName = tostring(TargetResources.modifiedProperties[1].newValue)\n| where isnotempty(RoleName)\n| extend TargetId = tostring(TargetResources.id)\n| extend Target = tostring(TargetResources.userPrincipalName)\n| join kind=inner ( BehaviorAnalytics\n | where TimeGenerated {TimeRange:query}\n | where ActionType == \"Add member to role\"\n | where UsersInsights.BlasrRadius == \"High\" or ActivityInsights.FirstTimeUserPerformedAction == true\n) on $left._ItemId == $right.SourceRecordId\n| extend AnomalyName = \"Anomalous Role Assignemt\",\n Tactic = \"Persistence\",\n Technique = \"Account Manipulation\",\n SubTechnique = \"\",\n Description = \"Adversaries may manipulate accounts to maintain access to victim systems. These actions include adding new accounts to high privilleged groups. Dragonfly 2.0, for example, added newly created accounts to the administrators group to maintain elevated access. The query below generates an output of all high Blast Radius users performing Add member to priveleged role, or ones that add users for the first time.\"\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType, [\"TargetUser\"]=Target,RoleName,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority;let LogOns=materialize(\nBehaviorAnalytics\n| where TimeGenerated {TimeRange:query}\n| where ActivityType == \"LogOn\");\nlet AnomalousResourceAccess = LogOns\n| where ActionType == \"ResourceAccess\"\n| where ActivityInsights.FirstTimeUserLoggedOnToDevice == true\n| extend AnomalyName = \"Anomalous Resource Access\",\n Tactic = \"Lateral Movement\",\n Technique = \"\",\n SubTechnique = \"\",\n Description = \"Adversary may be trying to move through the environment. APT29 and APT32, for example, has used PtH & PtT techniques to lateral move around the network. The query below generates an output of all users performing an resource access (4624:3) to devices for the first time.\"\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \nlet AnomalousRDPActivity = LogOns\n| where ActionType == \"RemoteInteractiveLogon\"\n| where ActivityInsights.FirstTimeUserLoggedOnToDevice == true\n| extend AnomalyName = \"Anomalous RDP Activity\",\n Tactic = \"Lateral Movement\",\n Technique = \"\",\n SubTechnique = \"\",\n Description = \"Adversaries may use Valid Accounts to log into a computer using the Remote Desktop Protocol (RDP). The adversary may then perform actions as the logged-on user. FIN10, for example, has used RDP to move laterally to systems in the victim environment. The query below generates an output of all users performing a remote interactive logon (4624:10) to a device for the first time.\"\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \nlet AnomalousLogintoDevices = LogOns\n| where ActionType == \"InteractiveLogon\"\n| where ActivityInsights.FirstTimeUserLoggedOnToDevice == true\n| where UsersInsights.DormantAccount == true or DevicesInsights.LocalAdmin == true\n| extend AnomalyName = \"Anomalous Login To Devices\",\n Tactic = \"Privilege Escalation\",\n Technique = \"Valid Accounts\",\n SubTechnique = \"\",\n Description = \"Adversaries may steal the credentials of a specific user or service account using Credential Access techniques or capture credentials earlier in their reconnaissance process through social engineering for means of gaining Initial Access. APT33, for example, has used valid accounts for initial access and privilege escalation. The query below generates an output of all administator users performing an interactive logon (4624:2) to a device for the first time.\"\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \nlet AnomalousPasswordReset = BehaviorAnalytics\n| where TimeGenerated {TimeRange:query}\n| where ActionType == \"Reset user password\"\n| where ActivityInsights.FirstTimeUserPerformedAction == \"True\"\n| join (\nAuditLogs\n | where TimeGenerated {TimeRange:query}\n | where OperationName == \"Reset user password\"\n) on $left.SourceRecordId == $right._ItemId\n| mv-expand TargetResources\n| extend Target = iff(tostring(TargetResources.userPrincipalName) contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(TargetResources.userPrincipalName, \"#\")[0])),TargetResources.userPrincipalName),tostring(TargetResources.userPrincipalName)\n| extend UserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName)\n| extend AnomalyName = \"Anomalous Password Reset\",\n Tactic = \"Impact\",\n Technique = \"Account Access Removal\",\n SubTechnique = \"\",\n Description = \"Adversaries may interrupt availability of system and network resources by inhibiting access to accounts utilized by legitimate users. Accounts may be deleted, locked, or manipulated (ex: changed credentials) to remove access to accounts. LockerGoga, for example, has been observed changing account passwords and logging off current users. The query below generates an output of all users performing Reset user password for the first time.\"\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType, [\"TargetUser\"]=Target,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority\n| sort by TimeGenerated desc;\nlet AnomalousGeoLocationLogon = BehaviorAnalytics\n| where TimeGenerated {TimeRange:query}\n| where ActionType == \"Sign-in\"\n| where ActivityInsights.FirstTimeUserConnectedFromCountry == True and (ActivityInsights.FirstTimeConnectionFromCountryObservedInTenant == True or ActivityInsights.CountryUncommonlyConnectedFromAmongPeers == True)\n| join (\nSigninLogs\n | where TimeGenerated {TimeRange:query}\n) on $left.SourceRecordId == $right._ItemId\n| extend UserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName)\n| extend AnomalyName = \"Anomalous Successful Logon\",\n Tactic = \"Initial Access\",\n Technique = \"Valid Accounts\",\n SubTechnique = \"\",\n Description = \"Adversaries may steal the credentials of a specific user or service account using Credential Access techniques or capture credentials earlier in their reconnaissance process through social engineering for means of gaining Initial Access. APT33, for example, has used valid accounts for initial access. The query below generates an output of successful Sign-in performed by a user from a new geo location he has never connected from before, and none of his peers as well.\"\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights, ResourceDisplayName,AppDisplayName ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \nlet AnomalousFailedLogon = BehaviorAnalytics\n| where TimeGenerated {TimeRange:query}\n| where ActivityType == \"LogOn\"\n| where UsersInsights.BlastRadius == \"High\"\n| join (\n SigninLogs \n | where TimeGenerated {TimeRange:query}\n | where Status.errorCode == 50126\n) on $left.SourceRecordId == $right._ItemId\n| extend UserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName)\n| extend AnomalyName = \"Anomalous Failed Logon\",\n Tactic = \"Credential Access\",\n Technique = \"Brute Force\",\n SubTechnique = \"Password Guessing\",\n Description = \"Adversaries with no prior knowledge of legitimate credentials within the system or environment may guess passwords to attempt access to accounts. Emotet, for example, has been observed using a hard coded list of passwords to brute force user accounts. The query below generates an output of all users with 'High' BlastRadius that perform failed Sign-in:Invalid username or password.\"\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights, ResourceDisplayName,AppDisplayName ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \nlet AnomalousAADAccountManipulation = AuditLogs\n| where TimeGenerated {TimeRange:query}\n| where OperationName == \"Update user\"\n| mv-expand AdditionalDetails\n| where AdditionalDetails.key == \"UserPrincipalName\"\n| mv-expand TargetResources\n| extend RoleId = tostring(TargetResources.modifiedProperties[0].newValue)\n| where isnotempty(RoleId) and RoleId in (critical,high)\n| extend RoleName = tostring(TargetResources.modifiedProperties[1].newValue)\n| where isnotempty(RoleName)\n| extend TargetId = tostring(TargetResources.id)\n| extend Target = iff(tostring(TargetResources.userPrincipalName) contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(TargetResources.userPrincipalName, \"#\")[0])),TargetResources.userPrincipalName),tostring(TargetResources.userPrincipalName)\n| join kind=inner ( \n BehaviorAnalytics\n | where TimeGenerated {TimeRange:query}\n | where ActionType == \"Update user\"\n | where UsersInsights.BlasrRadius == \"High\" or ActivityInsights.FirstTimeUserPerformedAction == true\n) on $left._ItemId == $right.SourceRecordId\n| extend UserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName) \n| extend AnomalyName = \"Anomalous Account Manipulation\",\n Tactic = \"Persistence\",\n Technique = \"Account Manipulation\",\n SubTechnique = \"\",\n Description = \"Adversaries may manipulate accounts to maintain access to victim systems. These actions include adding new accounts to high privilleged groups. Dragonfly 2.0, for example, added newly created accounts to the administrators group to maintain elevated access. The query below generates an output of all high Blast Radius users performing 'Update user' (name change) to priveleged role, or ones that changed users for the first time.\"\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType, [\"TargetUser\"]=Target,RoleName,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; let AnomalousAADAccountCreation = BehaviorAnalytics\n| where TimeGenerated {TimeRange:query}\n| where ActionType == \"Add user\"\n| where ActivityInsights.FirstTimeUserPerformedAction == True or ActivityInsights.FirstTimeActionPerformedInTenant == True or ActivityInsights.ActionUncommonlyPerformedAmongPeers == true\n| join(\nAuditLogs\n | where TimeGenerated {TimeRange:query} \n | where OperationName == \"Add user\"\n) on $left.SourceRecordId == $right._ItemId\n| mv-expand TargetResources\n| extend Target = iff(tostring(TargetResources.userPrincipalName) contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(TargetResources.userPrincipalName, \"#\")[0])),TargetResources.userPrincipalName),tostring(TargetResources.userPrincipalName)\n| extend DisplayName = tostring(UsersInsights.AccountDisplayName),\nUserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName)\n| extend AnomalyName = \"Anomalous Account Creation\",\n Tactic = \"Persistence\",\n Technique = \"Create Account\",\n SubTechnique = \"Cloud Account\",\n Description = \"Adversaries may create a cloud account to maintain access to victim systems. With a sufficient level of access, such accounts may be used to establish secondary credentialed access that does not require persistent remote access tools to be deployed on the system. The query below generates an output of all the users performing user creation for the first time and the target users that were created.\"\t\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType, [\"TargetUser\"]=Target,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority\n| sort by TimeGenerated desc;\nlet AnomalyTable = union kind=outer AnomalousSigninActivity, AnomalousRoleAssignment, AnomalousResourceAccess, AnomalousRDPActivity, AnomalousPasswordReset, AnomalousLogintoDevices, AnomalousGeoLocationLogon, AnomalousAADAccountManipulation, AnomalousAADAccountCreation, AnomalousFailedLogon;\nlet TopUsersByAnomalies = AnomalyTable\n| summarize hint.strategy = shuffle AnomalyCount=count() by UserName, UserPrincipalName, tostring(UsersInsights.OnPremSid), tostring(UsersInsights.AccountObjectId)\n| project Name=tolower(UserName),UPN=tolower(UserPrincipalName), AadUserId=UsersInsights_AccountObjectId, Sid=UsersInsights_OnPremSid, AnomalyCount\n| sort by AnomalyCount desc;\nlet TopUsersByIncidents = SecurityIncident\n| where TimeGenerated {TimeRange:query} \n| summarize hint.strategy = shuffle arg_max(LastModifiedTime, *) by IncidentNumber\n| where Status == \"New\" or Status == \"Active\"\n| mv-expand AlertIds\n| extend AlertId = tostring(AlertIds)\n| join kind= innerunique ( \nSecurityAlert | where TimeGenerated {TimeRange:query} \n) on $left.AlertId == $right.SystemAlertId\n| summarize hint.strategy = shuffle arg_max(TimeGenerated,*), NumberOfUpdates = count() by SystemAlertId\n| mv-expand todynamic(Entities)\n| where Entities[\"Type\"] =~ \"account\"\n| extend Name = tostring(tolower(Entities[\"Name\"])), NTDomain = tostring(Entities[\"NTDomain\"]), UPNSuffix = tostring(Entities[\"UPNSuffix\"]), AadUserId = tostring(Entities[\"AadUserId\"]), AadTenantId = tostring(Entities[\"AadTenantId\"]), \n Sid = tostring(Entities[\"Sid\"]), IsDomainJoined = tobool(Entities[\"IsDomainJoined\"]) , Host = tostring(Entities[\"Host\"])\n| extend UPN = iff(Name != \"\" and UPNSuffix != \"\", strcat(Name, \"@\", UPNSuffix), \"\")\n| union TopUsersByAnomalies\n| extend \n AadPivot = iff(isempty(AadUserId),iff(isempty(Sid),Name,Sid),AadUserId),\n SidPivot = iff(isempty(Sid),iff(isempty(AadUserId),Name,AadUserId),Sid),\n UPNExists = iff(isempty(UPN), false,true),\n NameExists = iff(isempty(Name), false,true),\n SidExists = iff(isempty(Sid), false,true),\n AADExists = iff(isempty(AadUserId), false,true)\n| summarize hint.strategy = shuffle IncidentCount=dcount(IncidentNumber,4),AlertCount=dcountif(AlertId,isnotempty(AlertId),4),AnomalyCount=sum(AnomalyCount),any(Title, Severity, Status, StartTime, IncidentNumber, IncidentUrl, Owner), UPNAnchor=anyif(UPN, UPNExists == true),NameAnchor=anyif(Name, NameExists == true),AadAnchor=anyif(AadUserId, AADExists == true), SidAnchor=anyif(Sid, SidExists == true) , any(SidPivot) by AadPivot\n| summarize hint.strategy = shuffle IncidentCount=sum(IncidentCount),AlertCount=sum(AlertCount),AnomalyCount=sum(AnomalyCount), UPNAnchor=anyif(UPNAnchor, isempty(UPNAnchor) == false),NameAnchor=anyif(NameAnchor, isempty(NameAnchor) == false),AadAnchor=anyif(AadAnchor, isempty(AadAnchor) == false), SidAnchor=anyif(SidAnchor, isempty(SidAnchor) == false), any(any_Title,any_Severity,any_StartTime, any_IncidentNumber, any_IncidentUrl) by any_SidPivot\n| summarize hint.strategy = shuffle IncidentCount=sum(IncidentCount), AlertCount=sum(AlertCount),AnomalyCount=sum(AnomalyCount), UPNAnchor=anyif(UPNAnchor, isempty(UPNAnchor) == false),AadAnchor=anyif(AadAnchor, isempty(AadAnchor) == false), SidAnchor=anyif(SidAnchor, isempty(SidAnchor) == false), any(any_any_Title, any_any_Severity,any_any_StartTime, any_any_IncidentNumber, any_any_IncidentUrl) by NameAnchor\n| project [\"UserName\"]=NameAnchor,IncidentCount, AlertCount,AnomalyCount, [\"AadUserId\"]=AadAnchor,[\"OnPremSid\"]=SidAnchor , [\"UserPrincipalName\"]=UPNAnchor;\nTopUsersByIncidents\n| sort by IncidentCount, AlertCount, AnomalyCount desc\n", - "size": 1, - "showAnalytics": true, - "timeContext": { - "durationMs": 2419200000 }, - "timeContextFromParameter": "TimeRange", - "exportedParameters": [ - { - "fieldName": "UserPrincipalName", - "parameterName": "SelectedUser", - "parameterType": 1 - }, - { - "fieldName": "UserName", - "parameterName": "UserName", - "parameterType": 1, - "defaultValue": "None" - }, - { - "fieldName": "AadUserId", - "parameterName": "UserObjectId", - "parameterType": 1 - }, - { - "fieldName": "OnPremSid", - "parameterName": "UserSid", - "parameterType": 1 - }, - { - "fieldName": "AnomalyCount", - "parameterName": "AnomalyCount", - "parameterType": 1, - "defaultValue": "0" - } - ], - "queryType": 0, - "resourceType": "microsoft.operationalinsights/workspaces", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "IncidentCount", - "formatter": 8, - "formatOptions": { - "palette": "redDark" + "name": "General Info" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "Below you will find incidents that have entities involved in anomalies created up to 3 days prior to the incident creation.
Expand each entity to find the anomalies. When you click on the anomalies, you will visualize them on the right-hand side.
Finally, click on each of the anomalies to see anomaly reasons and device insights. Note that device insights are empty when there is no relevant information to show.", + "style": "info" + }, + "conditionalVisibility": { + "parameterName": "Help", + "comparison": "isEqualTo", + "value": "Yes" + }, + "name": "Help text for incidents with entities" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let TopUsersByAnomalies = Anomalies\r\n | mv-expand Entities\r\n | where tostring(Entities) contains '\"Type\":\"account\"'\r\n | project\r\n TimeGenerated,\r\n AnomalyID = Id,\r\n AadUserId=tostring(Entities.AadUserId),\r\n DisplayName=tostring(Entities.DisplayName),\r\n OriginalName=tostring(Entities.Name),\r\n AnomalyUPNSuffix=tostring(Entities.AnomalyUPNSuffix),\r\n OriginalUPNSuffix=tostring(Entities.UPNSuffix)\r\n | extend\r\n Name = iff(OriginalName contains '@', extract('(.*)@', 1, OriginalName), OriginalName),\r\n UPNSuffix = iff(OriginalUPNSuffix != \"\", OriginalUPNSuffix, extract('(.*)@(.*)', 2, OriginalName))\r\n | project-away OriginalName; \r\nlet TopIPsByAnomalies= Anomalies\r\n | mv-expand Entities\r\n | where tostring(Entities) contains '\"Type\":\"ip\"'\r\n | project TimeGenerated, IPentity=tostring(Entities.Address), AnomalyID = Id;\r\nlet DeviceAnomalyName = dynamic([\"DeviceUncommonlyUsedByUser\", \"DeviceUncommonlyUsedAmongPeers\", \"DeviceUncommonlyUsedInTenant\"]);\r\nlet TopHostsByAnomalies =Anomalies\r\n | mv-expand AnomalyReasons\r\n | where tostring(AnomalyReasons.Name) in (DeviceAnomalyName)\r\n | extend DeviceRegex = tostring(extract(\"with ([A-Z0-9-]+) device\", 1, Description))\r\n | extend DeviceName = tolower(DeviceRegex)\r\n | project-rename AnomalyID = Id;\r\nlet IncidentsWithEntities = SecurityIncident\r\n | summarize TimeGenerated=max(TimeGenerated), AlertIds=make_set(AlertIds) by IncidentNumber, IncidentUrl, Title\r\n | mv-expand AlertIds\r\n | project IncidentNumber, AlertId = tostring(AlertIds), TimeGenerated, IncidentUrl, Title \r\n | join kind = inner ( \r\n SecurityAlert\r\n | distinct SystemAlertId, Entities\r\n | mv-expand todynamic(Entities)\r\n | where Entities[\"Type\"] =~ \"account\"\r\n or Entities[\"Type\"] =~ \"ip\"\r\n or Entities[\"Type\"] =~ \"host\"\r\n | project\r\n SystemAlertId,\r\n IPentity = tostring(tolower(Entities.Address)),\r\n DeviceName = tostring(tolower(Entities.HostName)),\r\n OriginalName = tostring(tolower(Entities.Name)),\r\n OriginalUPNSuffix = tostring(Entities.UPNSuffix),\r\n AadUserId = tostring(Entities.AadUserId)\r\n | extend\r\n Name = iff(OriginalName contains '@', extract('(.*)@', 1, OriginalName), OriginalName),\r\n UPNSuffix = iff(OriginalUPNSuffix != \"\", OriginalUPNSuffix, extract('(.*)@(.*)', 2, OriginalName))\r\n | project-away OriginalName, OriginalUPNSuffix\r\n )\r\n on $left.AlertId == $right.SystemAlertId\r\n | distinct\r\n TimeGenerated,\r\n IncidentNumber,\r\n IPentity,\r\n Name,\r\n AadUserId,\r\n DeviceName,\r\n UPNSuffix,\r\n IncidentUrl,\r\n Title\r\n;\r\nlet TopUserIncidents = IncidentsWithEntities\r\n | join kind= inner (TopUsersByAnomalies) on $left.Name == $right.Name\r\n | where datetime_diff('day', TimeGenerated, TimeGenerated1) < 3 and datetime_diff('day', TimeGenerated, TimeGenerated1) > 0\r\n | summarize listOfAnomalyID = makelist(AnomalyID)\r\n by\r\n AadUserId= coalesce(Name, Name1),\r\n DisplayName,\r\n Name= coalesce(Name, Name1),\r\n AnomalyUPNSuffix,\r\n UPNSuffix = coalesce(UPNSuffix, UPNSuffix1),\r\n TimeGenerated,\r\n IncidentNumber,\r\n Title,\r\n IncidentUrl;\r\nlet TopIPIncidents = IncidentsWithEntities\r\n | join kind= inner (TopIPsByAnomalies) on $left.IPentity == $right.IPentity\r\n | where datetime_diff('day', TimeGenerated, TimeGenerated1) < 3 and datetime_diff('day', TimeGenerated, TimeGenerated1) > 0\r\n | summarize listOfAnomalyID = makelist(AnomalyID)\r\n by\r\n IPentity = coalesce(IPentity, IPentity1),\r\n TimeGenerated,\r\n IncidentNumber,\r\n Title,\r\n IncidentUrl;\r\nlet TopHostsIncidents = IncidentsWithEntities\r\n | join kind= inner (TopHostsByAnomalies) on $left.DeviceName == $right.DeviceName\r\n | where datetime_diff('day', TimeGenerated, TimeGenerated1) < 3 and datetime_diff('day', TimeGenerated, TimeGenerated1) > 0\r\n | summarize listOfAnomalyID = makelist(AnomalyID)\r\n by\r\n DeviceName = coalesce(DeviceName, DeviceName1),\r\n TimeGenerated,\r\n IncidentNumber,\r\n Title,\r\n IncidentUrl;\r\nTopUserIncidents\r\n| union TopIPIncidents, TopHostsIncidents\r\n| extend Entity1 = coalesce(Name, AadUserId, IPentity, DeviceName)\r\n| project\r\n TimeGenerated,\r\n IncidentNumber1 = strcat('📝', IncidentNumber),\r\n Title,\r\n IncidentUrl,\r\n IPentity,\r\n DeviceName,\r\n AadUserId,\r\n Name, \r\n UPNSuffix,\r\n DisplayName,\r\n Entity = strcat('Entity 🔎', Entity1),\r\n listOfAnomalyID\r\n| sort by TimeGenerated desc", + "size": 0, + "title": "Incidents with entities present in anomalies created in the 3 preceding days", + "timeContextFromParameter": "TimeRange", + "exportFieldName": "listOfAnomalyID", + "exportParameterName": "listOfAnomalyID", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "TimeGenerated", + "formatter": 5 + }, + { + "columnMatch": "IncidentNumber", + "formatter": 5, + "formatOptions": { + "linkTarget": "Url" + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "IncidentUrl", + "formatter": 7, + "formatOptions": { + "linkTarget": "Url" + } + }, + { + "columnMatch": "IPentity", + "formatter": 5, + "formatOptions": { + "linkTarget": "GenericDetails", + "linkIsContextBlade": true + } + }, + { + "columnMatch": "DeviceName", + "formatter": 5 + }, + { + "columnMatch": "AadUserId", + "formatter": 5 + }, + { + "columnMatch": "Name", + "formatter": 5, + "formatOptions": { + "linkTarget": "GenericDetails", + "linkIsContextBlade": true + } + }, + { + "columnMatch": "UPNSuffix", + "formatter": 5 + }, + { + "columnMatch": "DisplayName", + "formatter": 5 + }, + { + "columnMatch": "Entity", + "formatter": 5 + }, + { + "columnMatch": "listOfAnomalyID", + "formatter": 7, + "formatOptions": { + "linkTarget": "CellDetails", + "linkIsContextBlade": true + } + }, + { + "columnMatch": "Entity1", + "formatter": 1 + }, + { + "columnMatch": "AnomalyCount", + "formatter": 5, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + } + ], + "rowLimit": 500, + "hierarchySettings": { + "treeType": 1, + "groupBy": [ + "IncidentNumber1", + "Entity" + ], + "expandTopLevel": true, + "finalBy": "TimeGenerated" + }, + "labelSettings": [ + { + "columnId": "TimeGenerated", + "label": "Time Generated" + }, + { + "columnId": "IncidentNumber1", + "label": "Incident number" + }, + { + "columnId": "Title", + "label": "Incident name" + }, + { + "columnId": "IncidentUrl", + "label": "Link to incident" + }, + { + "columnId": "IPentity", + "label": "IPentity" + }, + { + "columnId": "DeviceName", + "label": "DeviceName" + }, + { + "columnId": "AadUserId", + "label": "AadUserId" + }, + { + "columnId": "Name", + "label": "Name" + }, + { + "columnId": "UPNSuffix", + "label": "UPNSuffix" + }, + { + "columnId": "DisplayName", + "label": "DisplayName" + }, + { + "columnId": "Entity", + "label": "Matching entity" + }, + { + "columnId": "listOfAnomalyID", + "label": "List of Anomaly IDs" + } + ] + }, + "sortBy": [] + }, + "customWidth": "40", + "name": "Incidents with entities present in anomalies", + "styleSettings": { + "maxWidth": "40" } - } - ], - "filter": true, - "sortBy": [ + }, { - "itemKey": "AnomalyCount", - "sortOrder": 2 + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "Anomalies\r\n| where '{listOfAnomalyID}' contains Id\r\n| project Description, AnomalyTemplateName, RuleStatus, RuleName, Score, AnomalyReasons, DeviceInsights", + "size": 1, + "title": "Anomalies of selected incident", + "timeContextFromParameter": "TimeRange", + "exportedParameters": [ + { + "fieldName": "AnomalyReasons", + "parameterName": "AnomalyReasonsP", + "parameterType": 1 + }, + { + "fieldName": "DeviceInsights", + "parameterName": "DeviceInsightsP", + "parameterType": 1 + } + ], + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Description", + "formatter": 7, + "formatOptions": { + "linkTarget": "GenericDetails", + "linkIsContextBlade": true, + "customColumnWidthSetting": "90%" + } + }, + { + "columnMatch": "AnomalyTemplateName", + "formatter": 5, + "formatOptions": { + "linkTarget": "GenericDetails", + "linkIsContextBlade": true + } + }, + { + "columnMatch": "RuleStatus", + "formatter": 5 + }, + { + "columnMatch": "RuleName", + "formatter": 5 + }, + { + "columnMatch": "Score", + "formatter": 5 + }, + { + "columnMatch": "AnomalyReasons", + "formatter": 5 + }, + { + "columnMatch": "DeviceInsights", + "formatter": 5 + } + ] + }, + "sortBy": [] + }, + "customWidth": "100", + "name": "Anomalies of selected incident", + "styleSettings": { + "maxWidth": "60" + } + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "{\"version\":\"1.0.0\",\"content\":\"{AnomalyReasonsP}\",\"transformers\":null}", + "size": 4, + "title": "Anomaly Reasons", + "queryType": 8, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Value", + "formatter": 1 + }, + { + "columnMatch": "Type", + "formatter": 5 + }, + { + "columnMatch": "IsAnomalous", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "True", + "representation": "3", + "text": "Yes" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "success", + "text": "No" + } + ] + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "TypicalObservations", + "formatter": 5 + }, + { + "columnMatch": "Anomalous?", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "True", + "representation": "3", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "success", + "text": "{0}{1}" + } + ] + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + } + ], + "sortBy": [ + { + "itemKey": "Name", + "sortOrder": 1 + } + ] + }, + "sortBy": [ + { + "itemKey": "Name", + "sortOrder": 1 + } + ] + }, + "customWidth": "50", + "name": "User Anomalies - AnomalyReasons" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "{\"version\":\"1.0.0\",\"content\":\"{DeviceInsights}\",\"transformers\":null}", + "size": 4, + "title": "DeviceInsights", + "noDataMessage": "None available", + "queryType": 8 + }, + "customWidth": "50", + "name": "DeviceInsights" + } + ] + }, + "customWidth": "60", + "name": "InsideGroupForSelectedEntity", + "styleSettings": { + "maxWidth": "60" + } } ] }, - "sortBy": [ - { - "itemKey": "AnomalyCount", - "sortOrder": 2 - } - ] - }, - "name": "query - 2" - }, - { - "type": 1, - "content": { - "json": "Select a user to view Incidents & Alerts & Anomalies breakdown", - "style": "upsell" - }, - "conditionalVisibility": { - "parameterName": "UserName", - "comparison": "isEqualTo", - "value": "None" + "name": "Incidents with anomalies" }, - "name": "text - 6" - }, - { - "type": 1, - "content": { - "json": "## Incidents Breakdown: [{SelectedUser}]()\r\n---\r\n" - }, - "conditionalVisibility": { - "parameterName": "UserName", - "comparison": "isNotEqualTo", - "value": "None" + { + "type": 1, + "content": { + "json": "#### Use the tabs below to see users, IPs and hosts involved in incidents, alerts and anomalies. By selecting one user, IP or host from the list, you will visualize incidents and anomaly details from each one.", + "style": "info" + }, + "conditionalVisibility": { + "parameterName": "Help", + "comparison": "isEqualTo", + "value": "Yes" + }, + "name": "Tabs help" }, - "name": "text - 4" - }, - { - "type": 9, - "content": { - "version": "KqlParameterItem/1.0", - "parameters": [ - { - "id": "f3097a1b-3aad-4a82-8a8a-19e2725b4ecb", - "version": "KqlParameterItem/1.0", - "name": "Severity", - "type": 2, - "multiSelect": true, - "quote": "'", - "delimiter": ",", - "value": [ - "value::all" - ], - "typeSettings": { - "additionalResourceOptions": [ - "value::all" - ], - "selectAllValue": "All" + { + "type": 11, + "content": { + "version": "LinkItem/1.0", + "style": "tabs", + "links": [ + { + "id": "3242e20b-3930-4c10-9c08-864eee8921b9", + "cellValue": "rankingTab", + "linkTarget": "parameter", + "linkLabel": "Users", + "subTarget": "Users", + "style": "link" }, - "jsonData": "[\"Low\",\"Medium\",\"High\"]", - "timeContext": { - "durationMs": 86400000 - } - }, - { - "id": "994e7321-0462-4367-aae3-a69c6d61bf26", - "version": "KqlParameterItem/1.0", - "name": "Status", - "type": 2, - "multiSelect": true, - "quote": "'", - "delimiter": ",", - "value": [ - "value::all" - ], - "typeSettings": { - "additionalResourceOptions": [ - "value::all" - ], - "selectAllValue": "All" + { + "id": "07d94953-ab1a-4d94-a1ac-a49c56370cc7", + "cellValue": "rankingTab", + "linkTarget": "parameter", + "linkLabel": "IPs", + "subTarget": "IPs", + "style": "link" }, - "jsonData": "[\"New\",\"Active\"]", - "timeContext": { - "durationMs": 86400000 + { + "id": "910b02fc-54d3-462a-a27b-dc5bdf2c3302", + "cellValue": "rankingTab", + "linkTarget": "parameter", + "linkLabel": "Hosts", + "subTarget": "Hosts", + "style": "link" } - }, - { - "id": "774bfc35-07c1-4680-b305-a65606439a53", - "version": "KqlParameterItem/1.0", - "name": "Owner", - "type": 2, - "multiSelect": true, - "quote": "'", - "delimiter": ",", - "query": "SecurityIncident\r\n| summarize arg_max(LastModifiedTime, *) by IncidentNumber\r\n| where Status == \"New\" or Status == \"Active\"\r\n| where isnotempty(Owner.assignedTo) \r\n| distinct tostring(Owner.assignedTo)\r\n", - "value": [ - "value::all" - ], - "typeSettings": { - "additionalResourceOptions": [ - "value::all" - ], - "selectAllValue": "All" - }, - "timeContext": { - "durationMs": 5184000000 - }, - "timeContextFromParameter": "TimeRange", - "queryType": 0, - "resourceType": "microsoft.operationalinsights/workspaces" - } - ], - "style": "pills", - "queryType": 0, - "resourceType": "microsoft.operationalinsights/workspaces" - }, - "conditionalVisibility": { - "parameterName": "UserName", - "comparison": "isNotEqualTo", - "value": "None" - }, - "name": "parameters - 14" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "let GetUserAlert = SecurityAlert\r\n| where TimeGenerated {TimeRange:query}\r\n| summarize arg_max(TimeGenerated,*) by SystemAlertId\r\n| where Entities contains \"account\"\r\n| extend SelectedAccountUPN = tolower(tostring('{SelectedUser}')),\r\n SelectedName = tolower(tostring('{UserName}')),\r\n SelectAAD = tolower(tostring('{UserObjectId}')),\r\n SelectSID = tolower(tostring('{UserSid}'))\r\n| mv-expand todynamic(Entities)\r\n| where Entities[\"Type\"] =~ \"account\"\r\n| extend Name = tostring(tolower(Entities[\"Name\"])), NTDomain = tostring(Entities[\"NTDomain\"]), UPNSuffix = tostring(Entities[\"UPNSuffix\"]), AadUserId = tostring(Entities[\"AadUserId\"]), AadTenantId = tostring(Entities[\"AadTenantId\"]), \r\n Sid = tostring(Entities[\"Sid\"]), IsDomainJoined = tobool(Entities[\"IsDomainJoined\"]) , Host = tostring(Entities[\"Host\"])\r\n| extend UPN = iff(Name != \"\" and UPNSuffix != \"\", strcat(Name, \"@\", UPNSuffix), \"\")\r\n| where (Name == SelectedName and SelectedName != \"\" ) or (UPN == SelectedAccountUPN and SelectedAccountUPN != \"\") or (AadUserId == SelectAAD and SelectAAD != \"\") or (Sid == SelectSID and SelectSID != \"\")\r\n| serialize Id = tostring(row_number())\r\n| project TimeGenerated, Title=DisplayName, Sid,Severity=AlertSeverity, Description, ProviderName, ProductName, SystemAlertId, Id;\r\nlet MapAlertsToIncidents = SecurityIncident\r\n| where TimeGenerated {TimeRange:query}\r\n| summarize arg_max(LastModifiedTime, *) by IncidentNumber\r\n| where Status == \"New\" or Status == \"Active\"\r\n| serialize Id = tostring(IncidentNumber)\r\n| mv-expand AlertIds\r\n| extend AlertId = tostring(AlertIds)\r\n| join kind=innerunique (GetUserAlert) on $left.AlertId == $right.SystemAlertId\r\n| project TimeGenerated=TimeGenerated1, Title=Title1, Severity=Severity1,Description=Description1, ProviderName, ProductName, SystemAlertId,Id=Id1,ParentId=Id, IncidentNumber;\r\nlet IncidentAlertsCount = MapAlertsToIncidents\r\n| summarize AlertCount=count() by IncidentNumber\r\n| join kind=innerunique (SecurityIncident \r\n| where TimeGenerated {TimeRange:query}\r\n| summarize arg_max(LastModifiedTime, *) by IncidentNumber\r\n) on $left.IncidentNumber == $right.IncidentNumber\r\n| extend SecOpsOwner = Owner.assignedTo\r\n| project TimeGenerated, Title,Severity,Description,AlertCount,Status,Owner=SecOpsOwner,BookmarkIds,Comments,Labels,IncidentUrl,Id=tostring(IncidentNumber),ParentId=\"root\";\r\nlet IncidentsAndAlertsForUser = MapAlertsToIncidents \r\n| union IncidentAlertsCount;\r\nIncidentsAndAlertsForUser\r\n| where (Severity == {Severity:value} or {Severity:value} == 'All') and (Status == {Status:value} or {Status:value} == 'All') and (Owner == {Owner:value} or {Owner:value} == 'All')\r\n| sort by AlertCount desc\r\n| project TimeGenerated, Title, AlertCount, Description, Severity, Status, Owner, BookmarkIds, Comments, Labels, IncidentUrl, Id, ParentId\r\n\r\n\r\n\r\n", - "size": 1, - "showAnalytics": true, - "noDataMessage": "No incidents associated with this user", - "noDataMessageStyle": 3, - "timeContext": { - "durationMs": 2419200000 + ] }, - "timeContextFromParameter": "TimeRange", - "queryType": 0, - "resourceType": "microsoft.operationalinsights/workspaces", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "AlertCount", - "formatter": 8, - "formatOptions": { - "palette": "grayBlue" - } + "name": "RankingTabParameterDefinition" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## Top users to investigate - by Incidents, alerts & anomalies" + }, + "conditionalVisibility": { + "parameterName": "rankingTab", + "comparison": "isEqualTo", + "value": "Users" + }, + "name": "UserGroupTopIncidents - Title Text" }, { - "columnMatch": "Severity", - "formatter": 18, - "formatOptions": { - "thresholdsOptions": "colors", - "thresholdsGrid": [ + "type": 1, + "content": { + "json": "Click on a user from the list below to view incidents and anomalies where the user is present", + "style": "info" + }, + "conditionalVisibilities": [ + { + "parameterName": "rankingTab", + "comparison": "isEqualTo", + "value": "Users" + }, + { + "parameterName": "Help", + "comparison": "isEqualTo", + "value": "Yes" + } + ], + "name": "UserGroupTopIncidents - Intro Text " + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let TopUsersByAnomalies = Anomalies\r\n| mv-expand Entities\r\n| where tostring(Entities) contains '\"Type\":\"account\"'\r\n| project AadUserId=tostring(Entities.AadUserId), DisplayName=tostring(Entities.DisplayName), OriginalName=tostring(Entities.Name), AnomalyUPNSuffix=tostring(Entities.AnomalyUPNSuffix), OriginalUPNSuffix=tostring(Entities.UPNSuffix)\r\n| extend Name = iff(OriginalName contains '@', extract('(.*)@', 1, OriginalName), OriginalName), UPNSuffix = iff(OriginalUPNSuffix != \"\", OriginalUPNSuffix, extract('(.*)@(.*)', 2, OriginalName))\r\n| summarize hint.strategy = shuffle AnomalyCount=count() by AadUserId, DisplayName, Name, AnomalyUPNSuffix, UPNSuffix;\r\nlet TopUsers = SecurityIncident\r\n| summarize hint.strategy = shuffle arg_max(LastModifiedTime, *) by IncidentNumber\r\n| mv-expand AlertIds\r\n| project IncidentNumber, AlertId = tostring(AlertIds), TimeGenerated\r\n| join kind= innerunique ( \r\nSecurityAlert\r\n| mv-expand todynamic(Entities)\r\n| where Entities[\"Type\"] =~ \"account\"\r\n| project SystemAlertId, OriginalName = tostring(tolower(Entities.Name)), OriginalUPNSuffix = tostring(Entities.UPNSuffix), AadUserId = tostring(Entities.AadUserId)\r\n | extend Name = iff(OriginalName contains '@', extract('(.*)@', 1, OriginalName), OriginalName), UPNSuffix = iff(OriginalUPNSuffix != \"\", OriginalUPNSuffix, extract('(.*)@(.*)', 2, OriginalName))\r\n | project-away OriginalName, OriginalUPNSuffix\r\n) on $left.AlertId == $right.SystemAlertId\r\n| union TopUsersByAnomalies\r\n| summarize hint.strategy = shuffle IncidentCount=dcount(IncidentNumber), AlertCount=dcount(AlertId), AnomalyCount=sum(AnomalyCount), AadUserId = make_set_if(AadUserId, AadUserId != \"\") by Name, UPNSuffix;\r\nTopUsers\r\n| sort by IncidentCount, AlertCount, AnomalyCount desc", + "size": 0, + "title": "Top users by incidents, alerts and anomalies", + "timeContextFromParameter": "TimeRange", + "exportedParameters": [ { - "operator": "==", - "thresholdValue": "Low", - "representation": "yellow", - "text": "{0}{1}" + "fieldName": "Name", + "parameterName": "UserName", + "parameterType": 1 }, { - "operator": "==", - "thresholdValue": "Medium", - "representation": "orange", - "text": "{0}{1}" + "fieldName": "AadUserId", + "parameterName": "UserObjectId", + "parameterType": 1 }, { - "operator": "==", - "thresholdValue": "High", - "representation": "redBright", - "text": "{0}{1}" + "fieldName": "UPNSuffix", + "parameterName": "UserUPN", + "parameterType": 1 + } + ], + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "gridSettings": { + "formatters": [ + { + "columnMatch": "IncidentCount", + "formatter": 8, + "formatOptions": { + "min": 1, + "palette": "redDark" + } + }, + { + "columnMatch": "AlertCount", + "formatter": 8, + "formatOptions": { + "palette": "redDark" + } + }, + { + "columnMatch": "AnomalyCount", + "formatter": 8, + "formatOptions": { + "palette": "redDark" + } + }, + { + "columnMatch": "AadUserId", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + } + } + ], + "rowLimit": 1000, + "filter": true, + "sortBy": [ + { + "itemKey": "$gen_heatmap_AnomalyCount_4", + "sortOrder": 2 + } + ] + }, + "sortBy": [ + { + "itemKey": "$gen_heatmap_AnomalyCount_4", + "sortOrder": 2 + } + ] + }, + "conditionalVisibility": { + "parameterName": "rankingTab", + "comparison": "isEqualTo", + "value": "Users" + }, + "name": "UserGroupTopIncidents - Overview Query" + }, + { + "type": 1, + "content": { + "json": "Select a user to view Incidents & Alerts & Anomalies breakdown", + "style": "upsell" + }, + "conditionalVisibility": { + "parameterName": "UserName", + "comparison": "isEqualTo", + "value": "None" + }, + "name": "UserGroupTopIncidents - Select user text" + }, + { + "type": 1, + "content": { + "json": "## Incidents Breakdown: {UserName}\r\n---\r\n" + }, + "conditionalVisibility": { + "parameterName": "UserName", + "comparison": "isNotEqualTo", + "value": "None" + }, + "name": "UserGroupTopIncidents - Selected User Text Incident" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "f3097a1b-3aad-4a82-8a8a-19e2725b4ecb", + "version": "KqlParameterItem/1.0", + "name": "Severity", + "type": 2, + "isRequired": true, + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "jsonData": "[\"Low\",\"Medium\",\"High\", \"All\"]", + "timeContext": { + "durationMs": 86400000 + }, + "value": "All" }, { - "operator": "Default", - "thresholdValue": null, - "representation": "blue", - "text": "{0}{1}" + "id": "994e7321-0462-4367-aae3-a69c6d61bf26", + "version": "KqlParameterItem/1.0", + "name": "Status", + "type": 2, + "isRequired": true, + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "jsonData": "[\"New\",\"Active\", \"All\"]", + "timeContext": { + "durationMs": 86400000 + }, + "value": "All" + } + ], + "style": "pills", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces" + }, + "conditionalVisibility": { + "parameterName": "UserName", + "comparison": "isNotEqualTo", + "value": "None" + }, + "name": "UserGroupTopIncidents - Parameter Incident Selection" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let IncidentUser = SecurityIncident\r\n| summarize hint.strategy = shuffle arg_max(LastModifiedTime, *) by IncidentNumber\r\n| mv-expand AlertIds\r\n| extend AlertId = tostring(AlertIds), SecOpsOwner=tostring(Owner.assignedTo)\r\n| join kind= innerunique ( \r\nSecurityAlert\r\n| mv-expand todynamic(Entities)\r\n| where Entities[\"Type\"] =~ \"account\"\r\n| project SystemAlertId, OriginalName = tostring(tolower(Entities.Name)), OriginalUPNSuffix = tostring(Entities.UPNSuffix), AadUserId = tostring(Entities.AadUserId)\r\n| extend Name = iff(OriginalName contains '@', extract('(.*)@', 1, OriginalName), OriginalName), UPNSuffix = iff(OriginalUPNSuffix != \"\", OriginalUPNSuffix, extract('(.*)@(.*)', 2, OriginalName))\r\n| project-away OriginalName, OriginalUPNSuffix\r\n) on $left.AlertId == $right.SystemAlertId\r\n| where (Name == '{UserName}' and Name != \"\" and UPNSuffix == '{UserUPN}') or (AadUserId == '{UserObjectId}')\r\n| where (Severity == '{Severity:value}' or '{Severity:value}' == \"All\") and (Status == '{Status:value}' or '{Status:value}' == \"All\");\r\nIncidentUser\r\n| summarize AlertCount=count(SystemAlertId) by TimeGenerated, Title, Description, Severity, Status, SecOpsOwner, IncidentUrl, IncidentNumber", + "size": 0, + "timeContextFromParameter": "TimeRange", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Severity", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "colors", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "Low", + "representation": "yellow", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Medium", + "representation": "orange", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "High", + "representation": "red", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Informational", + "representation": "gray", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "lightBlue", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "Status", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "New", + "representation": "2", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Active", + "representation": "pending", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Closed", + "representation": "stopped", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "success", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "Owner", + "formatter": 5 + }, + { + "columnMatch": "IncidentUrl", + "formatter": 7, + "formatOptions": { + "linkTarget": "Url", + "linkIsContextBlade": false + } + }, + { + "columnMatch": "AlertCount", + "formatter": 8, + "formatOptions": { + "min": 1, + "palette": "orangeDark" + } + }, + { + "columnMatch": "Comments", + "formatter": 7, + "formatOptions": { + "linkIsContextBlade": true + } + }, + { + "columnMatch": "Labels", + "formatter": 7, + "formatOptions": { + "linkIsContextBlade": true + } + } + ], + "sortBy": [ + { + "itemKey": "TimeGenerated", + "sortOrder": 1 + } + ] + }, + "sortBy": [ + { + "itemKey": "TimeGenerated", + "sortOrder": 1 } ] - } + }, + "conditionalVisibility": { + "parameterName": "UserName", + "comparison": "isNotEqualTo", + "value": "None" + }, + "name": "UserGroupTopIncidents - User Incident Close Up" }, { - "columnMatch": "Id", - "formatter": 5 + "type": 1, + "content": { + "json": "## Anomalies Breakdown: {UserName}\r\n---\r\n" + }, + "conditionalVisibility": { + "parameterName": "UserName", + "comparison": "isNotEqualTo", + "value": "None" + }, + "name": "UserGroupTopIncidents - Selected User Text Anomaly" }, { - "columnMatch": "Comments", - "formatter": 7, - "formatOptions": { - "linkTarget": "CellDetails", - "linkIsContextBlade": true - } + "type": 1, + "content": { + "json": "Select an anomaly to view all the related details below", + "style": "info" + }, + "conditionalVisibilities": [ + { + "parameterName": "Help", + "comparison": "isEqualTo", + "value": "Yes" + }, + { + "parameterName": "rankingTab", + "comparison": "isEqualTo", + "value": "Users" + } + ], + "name": "Anomalies help" }, { - "columnMatch": "Labels", - "formatter": 7, - "formatOptions": { - "linkTarget": "CellDetails", - "linkIsContextBlade": true - } + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "Anomalies\r\n| mv-expand Entities\r\n| where tostring(Entities) contains '\"Type\":\"account\"'\r\n| extend AadUserId=tostring(Entities.AadUserId), DisplayName=tostring(Entities.DisplayName), OriginalName=tostring(Entities.Name), AnomalyUPNSuffix=tostring(Entities.AnomalyUPNSuffix), OriginalUPNSuffix=tostring(Entities.UPNSuffix)\r\n| extend Name = iff(OriginalName contains '@', extract('(.*)@', 1, OriginalName), OriginalName), UPNSuffix = iff(OriginalUPNSuffix != \"\", OriginalUPNSuffix, extract('(.*)@(.*)', 2, OriginalName))\r\n| where (Name == '{UserName}' and Name != \"\" and UPNSuffix == '{UserUPN}') or (AadUserId == '{UserObjectId}')\r\n| project TimeGenerated, AnomalyRule=AnomalyTemplateName, Description, Score, RuleStatus, Tactics, Techniques, Entities, AnomalyReasons, AnomalyDetails, ExtendedProperties, ActivityInsights, DeviceInsights, UserInsights, ExtendedLinks\r\n", + "size": 1, + "noDataMessage": "No anomalies associated with this user", + "timeContextFromParameter": "TimeRange", + "exportedParameters": [ + { + "fieldName": "AnomalyReasons", + "parameterName": "AnomalyReasons", + "parameterType": 1 + }, + { + "fieldName": "AnomalyDetails", + "parameterName": "AnomalyDetails", + "parameterType": 1 + }, + { + "fieldName": "ActivityInsights", + "parameterName": "ActivityInsights", + "parameterType": 1 + }, + { + "fieldName": "ExtendedProperties", + "parameterName": "ExtendedProperties", + "parameterType": 1 + }, + { + "fieldName": "DeviceInsights", + "parameterName": "DeviceInsights", + "parameterType": 1 + }, + { + "fieldName": "UserInsights", + "parameterName": "UserInsights", + "parameterType": 1 + }, + { + "fieldName": "ExtendedLinks", + "parameterName": "ExtendedLinks", + "parameterType": 1 + } + ], + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Description", + "formatter": 7, + "formatOptions": { + "linkTarget": "CellDetails", + "linkIsContextBlade": true + } + }, + { + "columnMatch": "Score", + "formatter": 8, + "formatOptions": { + "min": 0, + "max": 1, + "palette": "purpleDark" + } + }, + { + "columnMatch": "RuleStatus", + "formatter": 1, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Techniques", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "AnomalyDetails", + "formatter": 7, + "formatOptions": { + "linkTarget": "CellDetails", + "linkIsContextBlade": true + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + }, + "tooltipFormat": { + "tooltip": "JSON object containing general information about the rule and algorithm that generated the anomaly as well as explanations for the anomaly." + } + }, + { + "columnMatch": "AnomalyReasons", + "formatter": 7, + "formatOptions": { + "linkTarget": "CellDetails", + "linkIsContextBlade": true + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + }, + "tooltipFormat": { + "tooltip": "The detailed explanation of the generated anomaly as JSON." + } + }, + { + "columnMatch": "ExtendedProperties", + "formatter": 7, + "formatOptions": { + "linkTarget": "CellDetails", + "linkIsContextBlade": true + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + }, + "tooltipFormat": { + "tooltip": "JSON object with additional data on the anomaly as key-value pairs." + } + }, + { + "columnMatch": "ActivityInsights", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + }, + "tooltipFormat": { + "tooltip": "Insights about the activites corresponding to the generated anomaly as JSON." + } + }, + { + "columnMatch": "DeviceInsights", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + }, + "tooltipFormat": { + "tooltip": "Insights about the devices corresponding to the generated anomaly as JSON." + } + }, + { + "columnMatch": "UserInsights", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + }, + "tooltipFormat": { + "tooltip": "Insights about the users corresponding to the generated anomaly as JSON." + } + }, + { + "columnMatch": "ExtendedLinks", + "formatter": 7, + "formatOptions": { + "linkTarget": "CellDetails", + "linkIsContextBlade": true + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + }, + "tooltipFormat": { + "tooltip": "List of links pointing to the data that generated the anomaly." + } + }, + { + "columnMatch": "TenantId", + "formatter": 5 + }, + { + "columnMatch": "Id", + "formatter": 5 + }, + { + "columnMatch": "WorkspaceId", + "formatter": 5 + }, + { + "columnMatch": "VendorName", + "formatter": 5 + }, + { + "columnMatch": "AnomalyTemplateId", + "formatter": 5 + }, + { + "columnMatch": "AnomalyTemplateVersion", + "formatter": 5 + }, + { + "columnMatch": "RuleId", + "formatter": 5 + }, + { + "columnMatch": "RuleName", + "formatter": 5 + }, + { + "columnMatch": "RuleConfigVersion", + "formatter": 5 + }, + { + "columnMatch": "StartTime", + "formatter": 5 + }, + { + "columnMatch": "EndTime", + "formatter": 5 + }, + { + "columnMatch": "UserPrincipalName", + "formatter": 5 + }, + { + "columnMatch": "SourceIpAddress", + "formatter": 5 + }, + { + "columnMatch": "SourceLocation", + "formatter": 5 + }, + { + "columnMatch": "SourceDevice", + "formatter": 5 + }, + { + "columnMatch": "DestinationIpAddress", + "formatter": 5 + }, + { + "columnMatch": "DestinationLocation", + "formatter": 5 + }, + { + "columnMatch": "DestinationDevice", + "formatter": 5 + }, + { + "columnMatch": "Type", + "formatter": 5 + }, + { + "columnMatch": "DisplayName", + "formatter": 1 + }, + { + "columnMatch": "OriginalName", + "formatter": 5 + }, + { + "columnMatch": "AnomalyUPNSuffix", + "formatter": 5 + }, + { + "columnMatch": "OriginalUPNSuffix", + "formatter": 5 + }, + { + "columnMatch": "Name", + "formatter": 5 + }, + { + "columnMatch": "UPNSuffix", + "formatter": 5 + } + ] + } + }, + "conditionalVisibility": { + "parameterName": "UserName", + "comparison": "isNotEqualTo", + "value": "None" + }, + "name": "UserGroupTopIncidents - User Anomaly Close Up " }, { - "columnMatch": "IncidentUrl", - "formatter": 7, - "formatOptions": { - "linkTarget": "Url" - } + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "{\"version\":\"1.0.0\",\"content\":\"{AnomalyReasons}\",\"transformers\":null}", + "size": 4, + "title": "User Anomalies - AnomalyReasons", + "queryType": 8, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Value", + "formatter": 1 + }, + { + "columnMatch": "Type", + "formatter": 5 + }, + { + "columnMatch": "IsAnomalous", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "True", + "representation": "3", + "text": "Yes" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "success", + "text": "No" + } + ] + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "TypicalObservations", + "formatter": 5 + }, + { + "columnMatch": "Anomalous?", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "True", + "representation": "3", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "success", + "text": "{0}{1}" + } + ] + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + } + ], + "sortBy": [ + { + "itemKey": "Name", + "sortOrder": 1 + } + ] + }, + "sortBy": [ + { + "itemKey": "Name", + "sortOrder": 1 + } + ] + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "rankingTab", + "comparison": "isEqualTo", + "value": "Users" + }, + "name": "User Anomalies - AnomalyReasons" }, { - "columnMatch": "ParentId", - "formatter": 5 + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "{\"version\":\"1.0.0\",\"content\":\"{DeviceInsights}\",\"transformers\":null}", + "size": 4, + "title": "User anomalies - DeviceInsights", + "noDataMessage": "None available", + "queryType": 8 + }, + "customWidth": "50", + "name": "User anomalies - DeviceInsights" } - ], - "rowLimit": 500, - "filter": true, - "hierarchySettings": { - "idColumn": "Id", - "parentColumn": "ParentId", - "treeType": 0, - "expanderColumn": "Title" - } + ] }, - "sortBy": [] - }, - "conditionalVisibility": { - "parameterName": "UserName", - "comparison": "isNotEqualTo", - "value": "None" - }, - "name": "query - 6 - Copy" - }, - { - "type": 1, - "content": { - "json": "## Anomalies Breakdown: [{SelectedUser}]()\r\n---\r\n" - }, - "conditionalVisibility": { - "parameterName": "UserName", - "comparison": "isNotEqualTo", - "value": "None" + "conditionalVisibility": { + "parameterName": "rankingTab", + "comparison": "isEqualTo", + "value": "Users" + }, + "name": "UserGroupTopIncidents" }, - "name": "text - 4 - Copy" - }, - { - "type": 9, - "content": { - "version": "KqlParameterItem/1.0", - "parameters": [ - { - "id": "98f0e009-27e3-451d-a105-5c40bc269c52", - "version": "KqlParameterItem/1.0", - "name": "AnomalyName", - "label": " Anoamly Name", - "type": 2, - "isRequired": true, - "multiSelect": true, - "quote": "'", - "delimiter": ",", - "value": [ - "value::all" - ], - "typeSettings": { - "additionalResourceOptions": [ - "value::all" - ], - "selectAllValue": "All" - }, - "jsonData": "[\"Anomalous Account Creation\",\r\n\"Anomalous Account Manipulation\",\r\n\"Anomalous Failed Logon\",\r\n\"Anomalous Geo Location Logon\",\r\n\"Anomalous Login to Devices\",\r\n\"Anomalous Password Reset\",\r\n\"Anomalous RDP Activity\",\r\n\"Anomalous Resource Access\",\r\n\"Anomalous Role Assignment\",\r\n\"Anomalous Sign-in Activity\"\r\n]", - "timeContext": { - "durationMs": 1209600000 - }, - "timeContextFromParameter": "TimeRange" - }, - { - "id": "d3c089ab-a356-40e6-af42-d33759981503", - "version": "KqlParameterItem/1.0", - "name": "Tactic", - "type": 2, - "isRequired": true, - "multiSelect": true, - "quote": "'", - "delimiter": ",", - "value": [ - "value::all" - ], - "typeSettings": { - "additionalResourceOptions": [ - "value::all" + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## Top hosts to investigate - by Incidents, alerts & anomalies\r\n---\r\n" + }, + "conditionalVisibility": { + "parameterName": "rankingTab", + "comparison": "isEqualTo", + "value": "Hosts" + }, + "name": "UserGroupTopIncidents - Title Text" + }, + { + "type": 1, + "content": { + "json": "Clicking on an entity should load anomalies and incidents where the entity is present", + "style": "info" + }, + "conditionalVisibilities": [ + { + "parameterName": "rankingTab", + "comparison": "isEqualTo", + "value": "Hosts" + }, + { + "parameterName": "help", + "comparison": "isEqualTo", + "value": "yes" + } ], - "selectAllValue": "All" - }, - "jsonData": "[\"Initial Access\",\"Execution\",\"Persistence\",\"Privilege Escalation\",\"Defense Evasion\",\"Credential Access\",\"Discovery\",\"Lateral Movement\",\"Collection\", \"Command and Control\", \"Exfiltration\",\"Impact\"]\r\n\r\n\r\n", - "timeContext": { - "durationMs": 1209600000 - }, - "timeContextFromParameter": "TimeRange" - }, - { - "id": "f84c4293-3f2b-44aa-9b0e-402d449e8b6c", - "version": "KqlParameterItem/1.0", - "name": "AnomalyScore", - "label": "Anomaly Score", - "type": 2, - "isRequired": true, - "multiSelect": true, - "quote": "'", - "delimiter": ",", - "value": [ - "value::all" - ], - "typeSettings": { - "additionalResourceOptions": [ - "value::all" + "name": "UserGroupTopIncidents - Intro Text" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Currently there is no mapping for hosts\r\n//We know that in the following anomalies there is a host present: \"FirstTimeUserConnectedFromDevice\", \"DeviceUncommonlyUsedByUser\", \"DeviceUncommonlyUsedAmongPeers\", \"FirstTimeDeviceObservedInTenant\", \"DeviceUncommonlyUsedInTenant\"\r\n//We only look for \"DeviceUncommonlyUsedByUser\", \"DeviceUncommonlyUsedAmongPeers\", \"DeviceUncommonlyUsedInTenant\" though since the other two only state PII instead of the host itself\r\nlet Name = dynamic([\"DeviceUncommonlyUsedByUser\", \"DeviceUncommonlyUsedAmongPeers\", \"DeviceUncommonlyUsedInTenant\"]) ;\r\nlet TopHostsByAnomalies =\r\nAnomalies\r\n| mv-expand AnomalyReasons\r\n| where tostring(AnomalyReasons.Name) in (Name)\r\n| extend DeviceRegex = tostring(extract(\"with ([A-Z0-9-]+) device\", 1, Description))\r\n| extend DeviceName = tolower(DeviceRegex)\r\n| summarize hint.strategy = shuffle AnomalyCount=count() by DeviceName;\r\nlet TopHostsIncidents = SecurityIncident\r\n| summarize hint.strategy = shuffle arg_max(LastModifiedTime, *) by IncidentNumber\r\n| mv-expand AlertIds\r\n| project IncidentNumber, AlertId = tostring(AlertIds), TimeGenerated\r\n| join kind= innerunique ( \r\nSecurityAlert\r\n| mv-expand todynamic(Entities)\r\n| where Entities[\"Type\"] =~ \"host\"\r\n| project SystemAlertId, DeviceName = tostring(tolower(Entities.HostName))\r\n) on $left.AlertId == $right.SystemAlertId\r\n| union TopHostsByAnomalies\r\n| summarize IncidentCount=dcount(IncidentNumber), AlertCount=dcount(AlertId), AnomalyCount=sum(AnomalyCount) by DeviceName;\r\nTopHostsIncidents\r\n| where isnotempty(DeviceName)\r\n| sort by IncidentCount, AlertCount, AnomalyCount, DeviceName desc", + "size": 0, + "title": "Top hosts by incidents, alerts and anomalies", + "timeContextFromParameter": "TimeRange", + "exportFieldName": "DeviceName", + "exportParameterName": "Host", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "gridSettings": { + "formatters": [ + { + "columnMatch": "IncidentCount", + "formatter": 8, + "formatOptions": { + "min": 1, + "palette": "redDark" + } + }, + { + "columnMatch": "AlertCount", + "formatter": 8, + "formatOptions": { + "palette": "redDark" + } + }, + { + "columnMatch": "AnomalyCount", + "formatter": 8, + "formatOptions": { + "palette": "redDark" + } + }, + { + "columnMatch": "AadUserId", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + } + } + ], + "filter": true, + "sortBy": [ + { + "itemKey": "$gen_heatmap_AnomalyCount_3", + "sortOrder": 2 + } + ] + }, + "sortBy": [ + { + "itemKey": "$gen_heatmap_AnomalyCount_3", + "sortOrder": 2 + } + ] + }, + "conditionalVisibility": { + "parameterName": "rankingTab", + "comparison": "isEqualTo", + "value": "Hosts" + }, + "name": "HostsGroupTopIncidents - Overview Query" + }, + { + "type": 1, + "content": { + "json": "Select a host to view Incidents & Alerts & Anomalies breakdown", + "style": "upsell" + }, + "conditionalVisibility": { + "parameterName": "Host", + "comparison": "isEqualTo", + "value": "None" + }, + "name": "UserGroupTopIncidents - Select user text" + }, + { + "type": 1, + "content": { + "json": "## Incidents Breakdown: {UserName}\r\n---\r\n" + }, + "conditionalVisibility": { + "parameterName": "UserName", + "comparison": "isNotEqualTo", + "value": "None" + }, + "name": "UserGroupTopIncidents - Selected User Text Incident" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "f3097a1b-3aad-4a82-8a8a-19e2725b4ecb", + "version": "KqlParameterItem/1.0", + "name": "Severity", + "type": 2, + "isRequired": true, + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "jsonData": "[\"Low\",\"Medium\",\"High\", \"All\"]", + "timeContext": { + "durationMs": 86400000 + }, + "value": "All" + }, + { + "id": "994e7321-0462-4367-aae3-a69c6d61bf26", + "version": "KqlParameterItem/1.0", + "name": "Status", + "type": 2, + "isRequired": true, + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "jsonData": "[\"New\",\"Active\", \"All\"]", + "timeContext": { + "durationMs": 86400000 + }, + "value": "All" + } + ], + "style": "pills", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces" + }, + "conditionalVisibility": { + "parameterName": "UserName", + "comparison": "isNotEqualTo", + "value": "None" + }, + "name": "UserGroupTopIncidents - Parameter Incident Selection" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let IncidentswithHosts = SecurityIncident\r\n| summarize hint.strategy = shuffle arg_max(LastModifiedTime, *) by IncidentNumber\r\n| mv-expand AlertIds\r\n| extend AlertId = tostring(AlertIds), SecOpsOwner=tostring(Owner.assignedTo)\r\n| join kind= innerunique ( \r\nSecurityAlert\r\n| mv-expand todynamic(Entities)\r\n| where Entities[\"Type\"] =~ \"host\"\r\n| project SystemAlertId, HostEntity = tostring(tolower(Entities.HostName))\r\n) on $left.AlertId == $right.SystemAlertId\r\n| where (HostEntity == '{Host}' and HostEntity != \"\")\r\n| where (Severity == '{Severity:value}' or '{Severity:value}' == \"All\") and (Status == '{Status:value}' or '{Status:value}' == \"All\");\r\nIncidentswithHosts\r\n| summarize AlertCount=count(SystemAlertId) by TimeGenerated, Title, Description, Severity, Status, SecOpsOwner, IncidentUrl, IncidentNumber", + "size": 0, + "timeContextFromParameter": "TimeRange", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Severity", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "colors", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "Low", + "representation": "yellow", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Medium", + "representation": "orange", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "High", + "representation": "red", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Informational", + "representation": "gray", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "lightBlue", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "Status", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "New", + "representation": "2", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Active", + "representation": "pending", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Closed", + "representation": "stopped", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "success", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "Owner", + "formatter": 5 + }, + { + "columnMatch": "IncidentUrl", + "formatter": 7, + "formatOptions": { + "linkTarget": "Url", + "linkIsContextBlade": false + } + }, + { + "columnMatch": "AlertCount", + "formatter": 8, + "formatOptions": { + "min": 1, + "palette": "orangeDark" + } + }, + { + "columnMatch": "Comments", + "formatter": 7, + "formatOptions": { + "linkIsContextBlade": true + } + }, + { + "columnMatch": "Labels", + "formatter": 7, + "formatOptions": { + "linkIsContextBlade": true + } + } + ], + "sortBy": [ + { + "itemKey": "$gen_heatmap_AlertCount_8", + "sortOrder": 2 + } + ] + }, + "sortBy": [ + { + "itemKey": "$gen_heatmap_AlertCount_8", + "sortOrder": 2 + } + ] + }, + "conditionalVisibility": { + "parameterName": "Host", + "comparison": "isNotEqualTo", + "value": "None" + }, + "name": "HostTopIncidents - Host Incident Close Up" + }, + { + "type": 1, + "content": { + "json": "## Anomalies Breakdown: {UserName}\r\n---\r\n" + }, + "conditionalVisibility": { + "parameterName": "UserName", + "comparison": "isNotEqualTo", + "value": "None" + }, + "name": "UserGroupTopIncidents - Selected User Text Anomaly" + }, + { + "type": 1, + "content": { + "json": "Currently, hosts are not mapped as entities in anomalies. In this workbook, they are being extracted from the Anomaly description.", + "style": "warning" + }, + "conditionalVisibility": { + "parameterName": "rankingTab", + "comparison": "isEqualTo", + "value": "Hosts" + }, + "name": "Host anomalies warning" + }, + { + "type": 1, + "content": { + "json": "Hover over each field on the anomalies below to see what it means", + "style": "info" + }, + "conditionalVisibilities": [ + { + "parameterName": "Help", + "comparison": "isEqualTo", + "value": "Yes" + }, + { + "parameterName": "rankingTab", + "comparison": "isEqualTo", + "value": "Hosts" + } ], - "selectAllValue": "All" - }, - "jsonData": "[\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\",\"10\"]", - "timeContext": { - "durationMs": 7776000000 - }, - "timeContextFromParameter": "TimeRange" - } - ], - "style": "pills", - "queryType": 0, - "resourceType": "microsoft.operationalinsights/workspaces" - }, - "conditionalVisibility": { - "parameterName": "UserName", - "comparison": "isNotEqualTo", - "value": "None" - }, - "name": "parameters - 15" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "let AnomalousSigninActivity = BehaviorAnalytics\r\n| where TimeGenerated {TimeRange:query}\r\n| where ActionType == \"Sign-in\"\r\n| where (UsersInsights.NewAccount == True or UsersInsights.DormantAccount == True) and (\r\n ActivityInsights.FirstTimeUserAccessedResource == True and ActivityInsights.ResourceUncommonlyAccessedAmongPeers == True\r\nor ActivityInsights.FirstTimeUserUsedApp == True and ActivityInsights.AppUncommonlyUsedAmongPeers == False)\r\n| join (\r\nSigninLogs | where TimeGenerated {TimeRange:query} | where Status.errorCode == 0 or Status.errorCode == 0 and RiskDetail != \"none\"\r\n) on $left.SourceRecordId == $right._ItemId\r\n| extend UserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\r\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName)\r\n| extend AnomalyName = \"Anomalous Successful Logon\",\r\n Tactic = \"Persistence\",\r\n Technique = \"Valid Accounts\",\r\n SubTechnique = \"\",\r\n Description = \"Successful Sign-in with one or more of the following indications: sign by new or recently dormant accounts and sign in with resource for the first time (while none of their peers did) or to an app for the first time (while none of their peers did) or performed by a user with Risk indicaiton from AAD\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights, ResourceDisplayName,AppDisplayName,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \r\nlet critical = dynamic(['9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3','c4e39bd9-1100-46d3-8c65-fb160da0071f','158c047a-c907-4556-b7ef-446551a6b5f7','62e90394-69f5-4237-9190-012177145e10','d29b2b05-8046-44ba-8758-1e26182fcf32','729827e3-9c14-49f7-bb1b-9608f156bbb8','966707d0-3269-4727-9be2-8c3a10f19b9d','194ae4cb-b126-40b2-bd5b-6091b380977d','fe930be7-5e62-47db-91af-98c3a49a38b1']);\r\nlet high = dynamic(['cf1c38e5-3621-4004-a7cb-879624dced7c','7495fdc4-34c4-4d15-a289-98788ce399fd','aaf43236-0c0d-4d5f-883a-6955382ac081','3edaf663-341e-4475-9f94-5c398ef6c070','7698a772-787b-4ac8-901f-60d6b08affd2','b1be1c3e-b65d-4f19-8427-f6fa0d97feb9','9f06204d-73c1-4d4c-880a-6edb90606fd8','29232cdf-9323-42fd-ade2-1d097af3e4de','be2f45a1-457d-42af-a067-6ec1fa63bc45','7be44c8a-adaf-4e2a-84d6-ab2649e08a13','e8611ab8-c189-46e8-94e1-60213ab1f814']);\r\nlet AnomalousRoleAssignment = AuditLogs\r\n| where TimeGenerated {TimeRange:query}\r\n| where OperationName == \"Add member to role\"\r\n| mv-expand TargetResources\r\n| extend RoleId = tostring(TargetResources.modifiedProperties[0].newValue)\r\n| where isnotempty(RoleId) and RoleId in (critical,high)\r\n| extend RoleName = tostring(TargetResources.modifiedProperties[1].newValue)\r\n| where isnotempty(RoleName)\r\n| extend TargetId = tostring(TargetResources.id)\r\n| extend Target = tostring(TargetResources.userPrincipalName)\r\n| join kind=inner ( BehaviorAnalytics\r\n | where TimeGenerated {TimeRange:query}\r\n | where ActionType == \"Add member to role\"\r\n | where UsersInsights.BlasrRadius == \"High\" or ActivityInsights.FirstTimeUserPerformedAction == true\r\n) on $left._ItemId == $right.SourceRecordId\r\n| extend AnomalyName = \"Anomalous Role Assignemt\",\r\n Tactic = \"Persistence\",\r\n Technique = \"Account Manipulation\",\r\n SubTechnique = \"\",\r\n Description = \"Adversaries may manipulate accounts to maintain access to victim systems. These actions include adding new accounts to high privilleged groups. Dragonfly 2.0, for example, added newly created accounts to the administrators group to maintain elevated access. The query below generates an output of all high Blast Radius users performing Add member to priveleged role, or ones that add users for the first time.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType, [\"TargetUser\"]=Target,RoleName,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority;let LogOns=materialize(\r\nBehaviorAnalytics\r\n| where TimeGenerated {TimeRange:query}\r\n| where ActivityType == \"LogOn\");\r\nlet AnomalousResourceAccess = LogOns\r\n| where ActionType == \"ResourceAccess\"\r\n| where ActivityInsights.FirstTimeUserLoggedOnToDevice == true\r\n| extend AnomalyName = \"Anomalous Resource Access\",\r\n Tactic = \"Lateral Movement\",\r\n Technique = \"\",\r\n SubTechnique = \"\",\r\n Description = \"Adversary may be trying to move through the environment. APT29 and APT32, for example, has used PtH & PtT techniques to lateral move around the network. The query below generates an output of all users performing an resource access (4624:3) to devices for the first time.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \r\nlet AnomalousRDPActivity = LogOns\r\n| where ActionType == \"RemoteInteractiveLogon\"\r\n| where ActivityInsights.FirstTimeUserLoggedOnToDevice == true\r\n| extend AnomalyName = \"Anomalous RDP Activity\",\r\n Tactic = \"Lateral Movement\",\r\n Technique = \"\",\r\n SubTechnique = \"\",\r\n Description = \"Adversaries may use Valid Accounts to log into a computer using the Remote Desktop Protocol (RDP). The adversary may then perform actions as the logged-on user. FIN10, for example, has used RDP to move laterally to systems in the victim environment. The query below generates an output of all users performing a remote interactive logon (4624:10) to a device for the first time.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \r\nlet AnomalousLogintoDevices = LogOns\r\n| where ActionType == \"InteractiveLogon\"\r\n| where ActivityInsights.FirstTimeUserLoggedOnToDevice == true\r\n| where UsersInsights.DormantAccount == true or DevicesInsights.LocalAdmin == true\r\n| extend AnomalyName = \"Anomalous Login To Devices\",\r\n Tactic = \"Privilege Escalation\",\r\n Technique = \"Valid Accounts\",\r\n SubTechnique = \"\",\r\n Description = \"Adversaries may steal the credentials of a specific user or service account using Credential Access techniques or capture credentials earlier in their reconnaissance process through social engineering for means of gaining Initial Access. APT33, for example, has used valid accounts for initial access and privilege escalation. The query below generates an output of all administator users performing an interactive logon (4624:2) to a device for the first time.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \r\nlet AnomalousPasswordReset = BehaviorAnalytics\r\n| where TimeGenerated {TimeRange:query}\r\n| where ActionType == \"Reset user password\"\r\n| where ActivityInsights.FirstTimeUserPerformedAction == \"True\"\r\n| join (\r\nAuditLogs\r\n | where TimeGenerated {TimeRange:query}\r\n | where OperationName == \"Reset user password\"\r\n) on $left.SourceRecordId == $right._ItemId\r\n| mv-expand TargetResources\r\n| extend Target = iff(tostring(TargetResources.userPrincipalName) contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(TargetResources.userPrincipalName, \"#\")[0])),TargetResources.userPrincipalName),tostring(TargetResources.userPrincipalName)\r\n| extend UserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\r\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName)\r\n| extend AnomalyName = \"Anomalous Password Reset\",\r\n Tactic = \"Impact\",\r\n Technique = \"Account Access Removal\",\r\n SubTechnique = \"\",\r\n Description = \"Adversaries may interrupt availability of system and network resources by inhibiting access to accounts utilized by legitimate users. Accounts may be deleted, locked, or manipulated (ex: changed credentials) to remove access to accounts. LockerGoga, for example, has been observed changing account passwords and logging off current users. The query below generates an output of all users performing Reset user password for the first time.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType, [\"TargetUser\"]=Target,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority\r\n| sort by TimeGenerated desc;\r\nlet AnomalousGeoLocationLogon = BehaviorAnalytics\r\n| where TimeGenerated {TimeRange:query}\r\n| where ActionType == \"Sign-in\"\r\n| where ActivityInsights.FirstTimeUserConnectedFromCountry == True and (ActivityInsights.FirstTimeConnectionFromCountryObservedInTenant == True or ActivityInsights.CountryUncommonlyConnectedFromAmongPeers == True)\r\n| join (\r\nSigninLogs\r\n | where TimeGenerated {TimeRange:query}\r\n) on $left.SourceRecordId == $right._ItemId\r\n| extend UserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\r\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName)\r\n| extend AnomalyName = \"Anomalous Successful Logon\",\r\n Tactic = \"Initial Access\",\r\n Technique = \"Valid Accounts\",\r\n SubTechnique = \"\",\r\n Description = \"Adversaries may steal the credentials of a specific user or service account using Credential Access techniques or capture credentials earlier in their reconnaissance process through social engineering for means of gaining Initial Access. APT33, for example, has used valid accounts for initial access. The query below generates an output of successful Sign-in performed by a user from a new geo location he has never connected from before, and none of his peers as well.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights, ResourceDisplayName,AppDisplayName ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \r\nlet AnomalousFailedLogon = BehaviorAnalytics\r\n| where TimeGenerated {TimeRange:query}\r\n| where ActivityType == \"LogOn\"\r\n| where UsersInsights.BlastRadius == \"High\"\r\n| join (\r\n SigninLogs \r\n | where TimeGenerated {TimeRange:query}\r\n | where Status.errorCode == 50126\r\n) on $left.SourceRecordId == $right._ItemId\r\n| extend UserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\r\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName)\r\n| extend AnomalyName = \"Anomalous Failed Logon\",\r\n Tactic = \"Credential Access\",\r\n Technique = \"Brute Force\",\r\n SubTechnique = \"Password Guessing\",\r\n Description = \"Adversaries with no prior knowledge of legitimate credentials within the system or environment may guess passwords to attempt access to accounts. Emotet, for example, has been observed using a hard coded list of passwords to brute force user accounts. The query below generates an output of all users with 'High' BlastRadius that perform failed Sign-in:Invalid username or password.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType,[\"Evidence\"]=ActivityInsights, ResourceDisplayName,AppDisplayName ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; \r\nlet AnomalousAADAccountManipulation = AuditLogs\r\n| where TimeGenerated {TimeRange:query}\r\n| where OperationName == \"Update user\"\r\n| mv-expand AdditionalDetails\r\n| where AdditionalDetails.key == \"UserPrincipalName\"\r\n| mv-expand TargetResources\r\n| extend RoleId = tostring(TargetResources.modifiedProperties[0].newValue)\r\n| where isnotempty(RoleId) and RoleId in (critical,high)\r\n| extend RoleName = tostring(TargetResources.modifiedProperties[1].newValue)\r\n| where isnotempty(RoleName)\r\n| extend TargetId = tostring(TargetResources.id)\r\n| extend Target = iff(tostring(TargetResources.userPrincipalName) contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(TargetResources.userPrincipalName, \"#\")[0])),TargetResources.userPrincipalName),tostring(TargetResources.userPrincipalName)\r\n| join kind=inner ( \r\n BehaviorAnalytics\r\n | where TimeGenerated {TimeRange:query}\r\n | where ActionType == \"Update user\"\r\n | where UsersInsights.BlasrRadius == \"High\" or ActivityInsights.FirstTimeUserPerformedAction == true\r\n) on $left._ItemId == $right.SourceRecordId\r\n| extend UserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\r\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName) \r\n| extend AnomalyName = \"Anomalous Account Manipulation\",\r\n Tactic = \"Persistence\",\r\n Technique = \"Account Manipulation\",\r\n SubTechnique = \"\",\r\n Description = \"Adversaries may manipulate accounts to maintain access to victim systems. These actions include adding new accounts to high privilleged groups. Dragonfly 2.0, for example, added newly created accounts to the administrators group to maintain elevated access. The query below generates an output of all high Blast Radius users performing 'Update user' (name change) to priveleged role, or ones that changed users for the first time.\"\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType, [\"TargetUser\"]=Target,RoleName,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority; let AnomalousAADAccountCreation = BehaviorAnalytics\r\n| where TimeGenerated {TimeRange:query}\r\n| where ActionType == \"Add user\"\r\n| where ActivityInsights.FirstTimeUserPerformedAction == True or ActivityInsights.FirstTimeActionPerformedInTenant == True or ActivityInsights.ActionUncommonlyPerformedAmongPeers == true\r\n| join(\r\nAuditLogs\r\n | where TimeGenerated {TimeRange:query} \r\n | where OperationName == \"Add user\"\r\n) on $left.SourceRecordId == $right._ItemId\r\n| mv-expand TargetResources\r\n| extend Target = iff(tostring(TargetResources.userPrincipalName) contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(TargetResources.userPrincipalName, \"#\")[0])),TargetResources.userPrincipalName),tostring(TargetResources.userPrincipalName)\r\n| extend DisplayName = tostring(UsersInsights.AccountDisplayName),\r\nUserPrincipalName = iff(UserPrincipalName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserPrincipalName),\r\nUserName = iff(UserName contains \"#EXT#\",replace(\"_\",\"@\",tostring(split(UserPrincipalName, \"#\")[0])),UserName)\r\n| extend AnomalyName = \"Anomalous Account Creation\",\r\n Tactic = \"Persistence\",\r\n Technique = \"Create Account\",\r\n SubTechnique = \"Cloud Account\",\r\n Description = \"Adversaries may create a cloud account to maintain access to victim systems. With a sufficient level of access, such accounts may be used to establish secondary credentialed access that does not require persistent remote access tools to be deployed on the system. The query below generates an output of all the users performing user creation for the first time and the target users that were created.\"\t\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType, [\"TargetUser\"]=Target,[\"Evidence\"]=ActivityInsights ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights,[\"Anomaly Score\"]=InvestigationPriority\r\n| sort by TimeGenerated desc;\r\nlet AnomalyTable = union kind=outer AnomalousSigninActivity, AnomalousRoleAssignment, AnomalousResourceAccess, AnomalousRDPActivity, AnomalousPasswordReset, AnomalousLogintoDevices, AnomalousGeoLocationLogon, AnomalousAADAccountManipulation, AnomalousAADAccountCreation, AnomalousFailedLogon;\r\n\r\n\r\nlet GetUserAnomalies = AnomalyTable\r\n| extend SelectedAccountUPN = tolower(tostring('{SelectedUser}')),\r\n SelectedName = tolower(tostring('{UserName}')),\r\n SelectAAD = tolower(tostring('{UserObjectId}')),\r\n SelectSID = tolower(tostring('{UserSid}'))\r\n| where (tolower(UserName) == tolower(SelectedName) and SelectedName != \"\" ) or (tolower(UserPrincipalName) == tolower(SelectedAccountUPN) and SelectedAccountUPN != \"\") or (UsersInsights.AccountObjectId == SelectAAD and SelectAAD != \"\") or (UsersInsights.OnPremSid == SelectSID and SelectSID != \"\")\r\n| project TimeGenerated, AnomalyName,Tactic,Technique,SubTechnique, Description, UserName, UserPrincipalName, UsersInsights, ActivityType, ActionType, TargetUser,Evidence ,SourceIPAddress, SourceIPLocation, SourceDevice, DevicesInsights, [\"Anomaly Score\"], AccountObjectId=UsersInsights.AccountObjectId;\r\nGetUserAnomalies\r\n| where \"{AnomalyName:label}\" == 'All' or AnomalyName in ({AnomalyName})\r\n| where \"{Tactic:label}\" == 'All' or Tactic in ({Tactic})\r\n| where \"{AnomalyScore:label}\" == 'All' or [\"Anomaly Score\"] in ({AnomalyScore})\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n", - "size": 1, - "showAnalytics": true, - "noDataMessage": "No anomalies associated with this user", - "noDataMessageStyle": 3, - "timeContext": { - "durationMs": 0 - }, - "timeContextFromParameter": "TimeRange", - "exportFieldName": "Tactic", - "exportParameterName": "TacticM", - "exportDefaultValue": "None", - "queryType": 0, - "resourceType": "microsoft.operationalinsights/workspaces", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Description", - "formatter": 7, - "formatOptions": { - "linkTarget": "CellDetails", - "linkIsContextBlade": true - } + "name": "Host anomalies help" }, { - "columnMatch": "Id", - "formatter": 5 + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Currently there is no mapping for hosts\r\n//We know that in the following anomalies there is a host present: \"FirstTimeUserConnectedFromDevice\", \"DeviceUncommonlyUsedByUser\", \"DeviceUncommonlyUsedAmongPeers\", \"FirstTimeDeviceObservedInTenant\", \"DeviceUncommonlyUsedInTenant\"\r\n//We only look for \"DeviceUncommonlyUsedByUser\", \"DeviceUncommonlyUsedAmongPeers\", \"DeviceUncommonlyUsedInTenant\" though since the other two only state PII instead of the host itself\r\nlet Name = dynamic([\"DeviceUncommonlyUsedByUser\", \"DeviceUncommonlyUsedAmongPeers\", \"DeviceUncommonlyUsedInTenant\"]) ;\r\nAnomalies\r\n| mv-expand AnomalyReasons\r\n| where tostring(AnomalyReasons.Name) in (Name)\r\n| extend DeviceName = tostring(extract(\"with ([A-Z0-9-]+) device\", 1, Description))\r\n| project TimeGenerated, Anomaly=Description, Score, RuleStatus, Tactics, Techniques, Entities, AnomalyDetails, AnomalyReasons, ExtendedProperties, ActivityInsights, DeviceInsights, UserInsights, ExtendedLinks\r\n", + "size": 1, + "noDataMessage": "No anomalies associated with this host", + "timeContextFromParameter": "TimeRange", + "exportedParameters": [ + { + "fieldName": "AnomalyReasons", + "parameterName": "AnomalyReasons", + "parameterType": 1 + }, + { + "fieldName": "DeviceInsights", + "parameterName": "DeviceInsights", + "parameterType": 1 + } + ], + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Score", + "formatter": 8, + "formatOptions": { + "min": 0, + "max": 1, + "palette": "purpleDark" + } + }, + { + "columnMatch": "Techniques", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "AnomalyDetails", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + }, + "tooltipFormat": { + "tooltip": "JSON object containing general information about the rule and algorithm that generated the anomaly as well as explanations for the anomaly." + } + }, + { + "columnMatch": "AnomalyReasons", + "formatter": 7, + "formatOptions": { + "linkTarget": "CellDetails", + "linkIsContextBlade": true + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + }, + "tooltipFormat": { + "tooltip": "The detailed explanation of the generated anomaly as JSON." + } + }, + { + "columnMatch": "ExtendedProperties", + "formatter": 7, + "formatOptions": { + "linkTarget": "CellDetails", + "linkIsContextBlade": true + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + }, + "tooltipFormat": { + "tooltip": "JSON object with additional data on the anomaly as key-value pairs." + } + }, + { + "columnMatch": "ExtendedLinks", + "formatter": 7, + "formatOptions": { + "linkTarget": "CellDetails", + "linkIsContextBlade": true + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + }, + "tooltipFormat": { + "tooltip": "List of links pointing to the data that generated the anomaly." + } + }, + { + "columnMatch": "ActivityInsights", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + }, + "tooltipFormat": { + "tooltip": "Insights about the activites corresponding to the generated anomaly as JSON." + } + }, + { + "columnMatch": "DeviceInsights", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + }, + "tooltipFormat": { + "tooltip": "Insights about the devices corresponding to the generated anomaly as JSON." + } + }, + { + "columnMatch": "UserInsights", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + }, + "tooltipFormat": { + "tooltip": "Insights about the users corresponding to the generated anomaly as JSON." + } + }, + { + "columnMatch": "TenantId", + "formatter": 5 + }, + { + "columnMatch": "Id", + "formatter": 5 + }, + { + "columnMatch": "WorkspaceId", + "formatter": 5 + }, + { + "columnMatch": "VendorName", + "formatter": 5 + }, + { + "columnMatch": "AnomalyTemplateId", + "formatter": 5 + }, + { + "columnMatch": "AnomalyTemplateVersion", + "formatter": 5 + }, + { + "columnMatch": "RuleId", + "formatter": 5 + }, + { + "columnMatch": "RuleName", + "formatter": 5 + }, + { + "columnMatch": "RuleConfigVersion", + "formatter": 5 + }, + { + "columnMatch": "Description", + "formatter": 7, + "formatOptions": { + "linkTarget": "CellDetails", + "linkIsContextBlade": true + } + }, + { + "columnMatch": "StartTime", + "formatter": 5 + }, + { + "columnMatch": "EndTime", + "formatter": 5 + }, + { + "columnMatch": "UserPrincipalName", + "formatter": 5 + }, + { + "columnMatch": "SourceIpAddress", + "formatter": 5 + }, + { + "columnMatch": "SourceLocation", + "formatter": 5 + }, + { + "columnMatch": "SourceDevice", + "formatter": 5 + }, + { + "columnMatch": "DestinationIpAddress", + "formatter": 5 + }, + { + "columnMatch": "DestinationLocation", + "formatter": 5 + }, + { + "columnMatch": "DestinationDevice", + "formatter": 5 + }, + { + "columnMatch": "Type", + "formatter": 5 + }, + { + "columnMatch": "DisplayName", + "formatter": 5 + }, + { + "columnMatch": "OriginalName", + "formatter": 5 + }, + { + "columnMatch": "AnomalyUPNSuffix", + "formatter": 5 + }, + { + "columnMatch": "OriginalUPNSuffix", + "formatter": 5 + }, + { + "columnMatch": "Name", + "formatter": 5 + }, + { + "columnMatch": "UPNSuffix", + "formatter": 5 + } + ] + } + }, + "conditionalVisibility": { + "parameterName": "UserName", + "comparison": "isNotEqualTo", + "value": "None" + }, + "name": "UserGroupTopIncidents - User Anomaly Close Up " }, { - "columnMatch": "IncidentUrl", - "formatter": 7, - "formatOptions": { - "linkTarget": "Url" - } + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "{\"version\":\"1.0.0\",\"content\":\"{AnomalyReasons}\",\"transformers\":null}", + "size": 4, + "title": "Host Anomalies - AnomalyReasons", + "queryType": 8, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Value", + "formatter": 1 + }, + { + "columnMatch": "Type", + "formatter": 5 + }, + { + "columnMatch": "IsAnomalous", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "True", + "representation": "3", + "text": "Yes" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "success", + "text": "No" + } + ] + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "TypicalObservations", + "formatter": 5 + }, + { + "columnMatch": "Anomalous?", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "True", + "representation": "3", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "success", + "text": "{0}{1}" + } + ] + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + } + ], + "sortBy": [ + { + "itemKey": "Name", + "sortOrder": 1 + } + ] + }, + "sortBy": [ + { + "itemKey": "Name", + "sortOrder": 1 + } + ] + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "rankingTab", + "comparison": "isEqualTo", + "value": "Hosts" + }, + "name": "Host Anomalies - AnomalyReasons" }, { - "columnMatch": "ParentId", - "formatter": 5 + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "{\"version\":\"1.0.0\",\"content\":\"{DeviceInsights}\",\"transformers\":null}", + "size": 4, + "title": "Host anomalies - DeviceInsights", + "noDataMessage": "None available", + "queryType": 8 + }, + "customWidth": "50", + "name": "Host anomalies - DeviceInsights" } - ], - "filter": true + ] }, - "sortBy": [] - }, - "conditionalVisibility": { - "parameterName": "UserName", - "comparison": "isNotEqualTo", - "value": "None" - }, - "customWidth": "70", - "name": "query - 6 - Copy - Copy" - }, - { - "type": 1, - "content": { - "json": "### Lateral Movement\r\n\r\nThe adversary is trying to move through your environment.\r\n\r\nLateral Movement consists of techniques that adversaries use to enter and control remote systems on a network. Following through on their primary objective often requires exploring the network to find their target and subsequently gaining access to it. Reaching their objective often involves pivoting through multiple systems and accounts to gain. Adversaries might install their own remote access tools to accomplish Lateral Movement or use legitimate credentials with native network and operating system tools, which may be stealthier.\r\n\r\n[Learn More Here](https://attack.mitre.org/tactics/TA0008/)" - }, - "conditionalVisibility": { - "parameterName": "TacticM", - "comparison": "isEqualTo", - "value": "Lateral Movement" - }, - "customWidth": "30", - "name": "text - 13 - Copy" - }, - { - "type": 1, - "content": { - "json": "### Mitre Tactic Information\r\nClick on one of the anomalies to presents an overview of ATT&CK\r\n" - }, - "conditionalVisibility": { - "parameterName": "TacticM", - "comparison": "isEqualTo", - "value": "None" - }, - "customWidth": "30", - "name": "text - 13 - Copy - Copy" - }, - { - "type": 1, - "content": { - "json": "### Initial Access\r\n\r\nThe adversary is trying to get into your network.\r\n\r\nInitial Access consists of techniques that use various entry vectors to gain their initial foothold within a network. Techniques used to gain a foothold include targeted spearphishing and exploiting weaknesses on public-facing web servers. Footholds gained through initial access may allow for continued access, like valid accounts and use of external remote services, or may be limited-use due to changing passwords.\r\n\r\n[Learn More Here](https://attack.mitre.org/tactics/TA0001/)" - }, - "conditionalVisibility": { - "parameterName": "TacticM", - "comparison": "isEqualTo", - "value": "Initial Access" - }, - "customWidth": "30", - "name": "text - 13" - }, - { - "type": 1, - "content": { - "json": "### Persistence\r\n\r\nThe adversary is trying to maintain their foothold.\r\n\r\nPersistence consists of techniques that adversaries use to keep access to systems across restarts, changed credentials, and other interruptions that could cut off their access. Techniques used for persistence include any access, action, or configuration changes that let them maintain their foothold on systems, such as replacing or hijacking legitimate code or adding startup code.\r\n\r\n[Learn More Here](https://attack.mitre.org/tactics/TA0003/)" - }, - "conditionalVisibility": { - "parameterName": "TacticM", - "comparison": "isEqualTo", - "value": "Persistence" - }, - "customWidth": "30", - "name": "text - 13 - Copy" - }, - { - "type": 1, - "content": { - "json": "### Discovery\r\n\r\nThe adversary is trying to figure out your environment.\r\n\r\nDiscovery consists of techniques an adversary may use to gain knowledge about the system and internal network. These techniques help adversaries observe the environment and orient themselves before deciding how to act. They also allow adversaries to explore what they can control and what’s around their entry point in order to discover how it could benefit their current objective. Native operating system tools are often used toward this post-compromise information-gathering objective.\r\n\r\n[Learn More Here](https://attack.mitre.org/tactics/TA0007/)" - }, - "conditionalVisibility": { - "parameterName": "TacticM", - "comparison": "isEqualTo", - "value": "Discovery" - }, - "customWidth": "30", - "name": "text - 13 - Copy - Copy - Copy - Copy" - }, - { - "type": 1, - "content": { - "json": "### Collection\r\n\r\nThe adversary is trying to gather data of interest to their goal.\r\n\r\nCollection consists of techniques adversaries may use to gather information and the sources information is collected from that are relevant to following through on the adversary's objectives. Frequently, the next goal after collecting data is to steal (exfiltrate) the data. Common target sources include various drive types, browsers, audio, video, and email. Common collection methods include capturing screenshots and keyboard input.\r\n\r\n[Learn More Here](https://attack.mitre.org/tactics/TA0009/)" - }, - "conditionalVisibility": { - "parameterName": "TacticM", - "comparison": "isEqualTo", - "value": "Collection" + "conditionalVisibility": { + "parameterName": "rankingTab", + "comparison": "isEqualTo", + "value": "Hosts" + }, + "name": "HostsGroupTopIncidents" }, - "customWidth": "30", - "name": "text - 13 - Copy - Copy" - } - ], - "fromTemplateId": "sentinel-UserAndEntityBehaviorAnalytics", - "$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json" -} + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "## Top IPs to investigate - by Incidents, alerts & anomalies\r\n---\r\n" + }, + "conditionalVisibility": { + "parameterName": "rankingTab", + "comparison": "isEqualTo", + "value": "IPs" + }, + "name": "IPGroupTopIncidents - Title Text" + }, + { + "type": 1, + "content": { + "json": "Clicking on an entity should load anomalies and incidents where the entity is present", + "style": "info" + }, + "conditionalVisibilities": [ + { + "parameterName": "rankingTab", + "comparison": "isEqualTo", + "value": "IPs" + }, + { + "parameterName": "Help", + "comparison": "isEqualTo", + "value": "Yes" + } + ], + "name": "IPGroupTopIncidents - Intro Text" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let TopIPsByAnomalies= Anomalies\r\n| mv-expand Entities\r\n| where tostring(Entities) contains '\"Type\":\"ip\"'\r\n| project IPentity=tostring(Entities.Address)\r\n| summarize hint.strategy = shuffle AnomalyCount=count() by IPentity;\r\nlet TopIPs = SecurityIncident\r\n| summarize hint.strategy = shuffle arg_max(LastModifiedTime, *) by IncidentNumber\r\n| mv-expand AlertIds\r\n| project IncidentNumber, AlertId = tostring(AlertIds), TimeGenerated\r\n| join kind = innerunique ( \r\nSecurityAlert\r\n| mv-expand todynamic(Entities)\r\n| where Entities[\"Type\"] =~ \"ip\"\r\n| project SystemAlertId, IPentity = tostring(tolower(Entities.Address))\r\n) on $left.AlertId == $right.SystemAlertId\r\n| union TopIPsByAnomalies\r\n| summarize IncidentCount=dcount(IncidentNumber), AlertCount=dcount(AlertId), AnomalyCount=sum(AnomalyCount) by IPentity;\r\nTopIPs\r\n| sort by IncidentCount, AlertCount, AnomalyCount, IPentity desc", + "size": 0, + "title": "Top IPs by incidents, alerts and anomalies", + "timeContextFromParameter": "TimeRange", + "exportFieldName": "IPentity", + "exportParameterName": "IP", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "gridSettings": { + "formatters": [ + { + "columnMatch": "IncidentCount", + "formatter": 8, + "formatOptions": { + "min": 0, + "palette": "redDark" + } + }, + { + "columnMatch": "AlertCount", + "formatter": 8, + "formatOptions": { + "min": 0, + "palette": "redDark" + } + }, + { + "columnMatch": "AnomalyCount", + "formatter": 8, + "formatOptions": { + "min": 0, + "palette": "redDark" + } + }, + { + "columnMatch": "AadUserId", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + } + } + ], + "rowLimit": 1000, + "filter": true + }, + "sortBy": [] + }, + "conditionalVisibility": { + "parameterName": "rankingTab", + "comparison": "isEqualTo", + "value": "IPs" + }, + "name": "IPGroupTopIncidents - Overview Query" + }, + { + "type": 1, + "content": { + "json": "Select an IP to view Incidents & Alerts & Anomalies breakdown", + "style": "upsell" + }, + "conditionalVisibility": { + "parameterName": "IP", + "comparison": "isEqualTo", + "value": "None" + }, + "name": "IPGroupTopIncidents - Select IP text" + }, + { + "type": 1, + "content": { + "json": "## Incidents Breakdown: {UserName}\r\n---\r\n" + }, + "conditionalVisibility": { + "parameterName": "UserName", + "comparison": "isNotEqualTo", + "value": "None" + }, + "name": "UserGroupTopIncidents - Selected User Text Incident" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "f3097a1b-3aad-4a82-8a8a-19e2725b4ecb", + "version": "KqlParameterItem/1.0", + "name": "Severity", + "type": 2, + "isRequired": true, + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "jsonData": "[\"Low\",\"Medium\",\"High\", \"All\"]", + "timeContext": { + "durationMs": 86400000 + }, + "value": "All" + }, + { + "id": "994e7321-0462-4367-aae3-a69c6d61bf26", + "version": "KqlParameterItem/1.0", + "name": "Status", + "type": 2, + "isRequired": true, + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "jsonData": "[\"New\",\"Active\", \"All\"]", + "timeContext": { + "durationMs": 86400000 + }, + "value": "All" + } + ], + "style": "pills", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces" + }, + "conditionalVisibility": { + "parameterName": "UserName", + "comparison": "isNotEqualTo", + "value": "None" + }, + "name": "UserGroupTopIncidents - Parameter Incident Selection" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let IncidentIP = SecurityIncident\r\n| summarize hint.strategy = shuffle arg_max(LastModifiedTime, *) by IncidentNumber\r\n| mv-expand AlertIds\r\n| extend AlertId = tostring(AlertIds), SecOpsOwner=tostring(Owner.assignedTo)\r\n| join kind= innerunique ( \r\nSecurityAlert\r\n| mv-expand todynamic(Entities)\r\n| where Entities[\"Type\"] =~ \"ip\"\r\n| project SystemAlertId, IPEntity = tostring(tolower(Entities.Address))\r\n) on $left.AlertId == $right.SystemAlertId\r\n| where (IPEntity == '{IP}' and IPEntity != \"\")\r\n| where (Severity == '{Severity:value}' or '{Severity:value}' == \"All\") and (Status == '{Status:value}' or '{Status:value}' == \"All\");\r\nIncidentIP\r\n| summarize AlertCount=count(SystemAlertId) by TimeGenerated, Title, Description, Severity, Status, SecOpsOwner, IncidentUrl, IncidentNumber", + "size": 0, + "timeContextFromParameter": "TimeRange", + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Severity", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "colors", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "Low", + "representation": "yellow", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Medium", + "representation": "orange", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "High", + "representation": "red", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Informational", + "representation": "gray", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "lightBlue", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "Status", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "New", + "representation": "2", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Active", + "representation": "pending", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Closed", + "representation": "stopped", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "success", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "Owner", + "formatter": 5 + }, + { + "columnMatch": "IncidentUrl", + "formatter": 7, + "formatOptions": { + "linkTarget": "Url", + "linkIsContextBlade": false + } + }, + { + "columnMatch": "AlertCount", + "formatter": 8, + "formatOptions": { + "min": 1, + "palette": "orangeDark" + } + }, + { + "columnMatch": "Comments", + "formatter": 7, + "formatOptions": { + "linkIsContextBlade": true + } + }, + { + "columnMatch": "Labels", + "formatter": 7, + "formatOptions": { + "linkIsContextBlade": true + } + } + ], + "sortBy": [ + { + "itemKey": "$gen_heatmap_AlertCount_8", + "sortOrder": 2 + } + ] + }, + "sortBy": [ + { + "itemKey": "$gen_heatmap_AlertCount_8", + "sortOrder": 2 + } + ] + }, + "conditionalVisibility": { + "parameterName": "UserName", + "comparison": "isNotEqualTo", + "value": "None" + }, + "name": "UserGroupTopIncidents - User Incident Close Up" + }, + { + "type": 1, + "content": { + "json": "## Anomalies Breakdown: {UserName}\r\n---\r\n" + }, + "conditionalVisibility": { + "parameterName": "UserName", + "comparison": "isNotEqualTo", + "value": "None" + }, + "name": "UserGroupTopIncidents - Selected User Text Anomaly" + }, + { + "type": 1, + "content": { + "json": "Hover over each field on the anomalies below to see what it means", + "style": "info" + }, + "conditionalVisibilities": [ + { + "parameterName": "Help", + "comparison": "isEqualTo", + "value": "Yes" + }, + { + "parameterName": "rankingTab", + "comparison": "isEqualTo", + "value": "IPs" + } + ], + "name": "IP anomalies help" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "Anomalies\r\n| mv-expand Entities\r\n| where tostring(Entities) contains '\"Type\":\"ip\"'\r\n| extend IPentity=tostring(Entities.Address)\r\n| where (IPentity == '{IP}' and IPentity != \"\" )\r\n| project TimeGenerated, AnomalyRule=AnomalyTemplateName, Description, Score, RuleStatus, Tactics, Techniques, Entities, AnomalyDetails, AnomalyReasons, ExtendedProperties, ActivityInsights, DeviceInsights, UserInsights, ExtendedLinks\r\n", + "size": 1, + "noDataMessage": "No anomalies associated with this IP", + "timeContextFromParameter": "TimeRange", + "exportedParameters": [ + { + "fieldName": "AnomalyReasons", + "parameterName": "AnomalyReasons", + "parameterType": 1 + }, + { + "fieldName": "DeviceInsights", + "parameterName": "DeviceInsights", + "parameterType": 1 + } + ], + "queryType": 0, + "resourceType": "microsoft.operationalinsights/workspaces", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Score", + "formatter": 8, + "formatOptions": { + "min": 0, + "max": 1, + "palette": "purpleDark" + } + }, + { + "columnMatch": "Techniques", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "AnomalyDetails", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + }, + "tooltipFormat": { + "tooltip": "JSON object containing general information about the rule and algorithm that generated the anomaly as well as explanations for the anomaly." + } + }, + { + "columnMatch": "AnomalyReasons", + "formatter": 7, + "formatOptions": { + "linkTarget": "CellDetails", + "linkIsContextBlade": true + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + }, + "tooltipFormat": { + "tooltip": "The detailed explanation of the generated anomaly as JSON." + } + }, + { + "columnMatch": "ExtendedProperties", + "formatter": 7, + "formatOptions": { + "linkTarget": "CellDetails", + "linkIsContextBlade": true + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + }, + "tooltipFormat": { + "tooltip": "JSON object with additional data on the anomaly as key-value pairs." + } + }, + { + "columnMatch": "ExtendedLinks", + "formatter": 7, + "formatOptions": { + "linkTarget": "CellDetails", + "linkIsContextBlade": true + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + }, + "tooltipFormat": { + "tooltip": "List of links pointing to the data that generated the anomaly." + } + }, + { + "columnMatch": "ActivityInsights", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + }, + "tooltipFormat": { + "tooltip": "Insights about the activites corresponding to the generated anomaly as JSON." + } + }, + { + "columnMatch": "DeviceInsights", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + }, + "tooltipFormat": { + "tooltip": "Insights about the devices corresponding to the generated anomaly as JSON." + } + }, + { + "columnMatch": "UserInsights", + "formatter": 0, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + }, + "emptyValCustomText": "None available" + }, + "tooltipFormat": { + "tooltip": "Insights about the users corresponding to the generated anomaly as JSON." + } + }, + { + "columnMatch": "TenantId", + "formatter": 5 + }, + { + "columnMatch": "Id", + "formatter": 5 + }, + { + "columnMatch": "WorkspaceId", + "formatter": 5 + }, + { + "columnMatch": "VendorName", + "formatter": 5 + }, + { + "columnMatch": "AnomalyTemplateId", + "formatter": 5 + }, + { + "columnMatch": "AnomalyTemplateVersion", + "formatter": 5 + }, + { + "columnMatch": "RuleId", + "formatter": 5 + }, + { + "columnMatch": "RuleName", + "formatter": 5 + }, + { + "columnMatch": "RuleConfigVersion", + "formatter": 5 + }, + { + "columnMatch": "Description", + "formatter": 7, + "formatOptions": { + "linkTarget": "CellDetails", + "linkIsContextBlade": true + } + }, + { + "columnMatch": "StartTime", + "formatter": 5 + }, + { + "columnMatch": "EndTime", + "formatter": 5 + }, + { + "columnMatch": "UserPrincipalName", + "formatter": 5 + }, + { + "columnMatch": "SourceIpAddress", + "formatter": 5 + }, + { + "columnMatch": "SourceLocation", + "formatter": 5 + }, + { + "columnMatch": "SourceDevice", + "formatter": 5 + }, + { + "columnMatch": "DestinationIpAddress", + "formatter": 5 + }, + { + "columnMatch": "DestinationLocation", + "formatter": 5 + }, + { + "columnMatch": "DestinationDevice", + "formatter": 5 + }, + { + "columnMatch": "Type", + "formatter": 5 + }, + { + "columnMatch": "DisplayName", + "formatter": 5 + }, + { + "columnMatch": "OriginalName", + "formatter": 5 + }, + { + "columnMatch": "AnomalyUPNSuffix", + "formatter": 5 + }, + { + "columnMatch": "OriginalUPNSuffix", + "formatter": 5 + }, + { + "columnMatch": "Name", + "formatter": 5 + }, + { + "columnMatch": "UPNSuffix", + "formatter": 5 + } + ] + } + }, + "conditionalVisibility": { + "parameterName": "IP", + "comparison": "isNotEqualTo", + "value": "None" + }, + "name": "UserGroupTopIncidents - User Anomaly Close Up " + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "{\"version\":\"1.0.0\",\"content\":\"{AnomalyReasons}\",\"transformers\":null}", + "size": 4, + "title": "IP Anomalies - AnomalyReasons", + "queryType": 8, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Value", + "formatter": 1 + }, + { + "columnMatch": "Type", + "formatter": 5 + }, + { + "columnMatch": "IsAnomalous", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "True", + "representation": "3", + "text": "Yes" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "success", + "text": "No" + } + ] + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "TypicalObservations", + "formatter": 5 + }, + { + "columnMatch": "Anomalous?", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "True", + "representation": "3", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "success", + "text": "{0}{1}" + } + ] + }, + "numberFormat": { + "unit": 0, + "options": { + "style": "decimal" + } + } + } + ], + "sortBy": [ + { + "itemKey": "Name", + "sortOrder": 1 + } + ] + }, + "sortBy": [ + { + "itemKey": "Name", + "sortOrder": 1 + } + ] + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "rankingTab", + "comparison": "isEqualTo", + "value": "IPs" + }, + "name": "User Anomalies - AnomalyReasons" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "{\"version\":\"1.0.0\",\"content\":\"{DeviceInsights}\",\"transformers\":null}", + "size": 4, + "title": "User anomalies - DeviceInsights", + "noDataMessage": "None available", + "queryType": 8 + }, + "customWidth": "50", + "name": "IP anomalies - DeviceInsights" + } + ] + }, + "conditionalVisibility": { + "parameterName": "rankingTab", + "comparison": "isEqualTo", + "value": "IPs" + }, + "name": "UserGroupTopIncidentsIP " + } + ], + "fromTemplateId": "https://sentinelus.hosting.portal.azure.net/sentinelus/Content/1.0.02484.3403-231021-003920/Scenarios/Ecosystem/Content/Workbooks/CustomWorkbook.json", + "$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json" + } diff --git a/Workbooks/WorkbooksMetadata.json b/Workbooks/WorkbooksMetadata.json index b3554ad9ceb..430d0fd277d 100644 --- a/Workbooks/WorkbooksMetadata.json +++ b/Workbooks/WorkbooksMetadata.json @@ -1810,14 +1810,14 @@ "logoFileName": "Azure_Sentinel.svg", "description": "Identify compromised users and insider threats using User and Entity Behavior Analytics. Gain insights into anomalous user behavior from baselines learned from behavior patterns", "dataTypesDependencies": [ - "BehaviorAnalytics" + "Anomalies" ], "dataConnectorsDependencies": [], "previewImagesFileNames": [ - "UserEntityBehaviorAnalyticsBlack1.png", - "UserEntityBehaviorAnalyticsWhite1.png" + "UserEntityBehaviorAnalyticsBlack2.png", + "UserEntityBehaviorAnalyticsWhite2.png" ], - "version": "1.2.0", + "version": "2.0", "title": "User And Entity Behavior Analytics", "templateRelativePath": "UserEntityBehaviorAnalytics.json", "subtitle": "",