From e01d4a80b8e5c5c43634d63d0cd1dacbefee3cca Mon Sep 17 00:00:00 2001 From: kingwil <5839248+kingwil@users.noreply.github.com> Date: Wed, 14 Oct 2026 20:56:22 +0100 Subject: [PATCH 1/6] Microsoft Defender for Office 365: add XDR workbook alongside Sentinel content Preserve existing connector, workbook and playbook selections; generate additive 3.2.0 review candidate. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- ...olution_MicrosoftDefenderforOffice365.json | 7 +- .../Package/3.2.0.zip | Bin 0 -> 39011 bytes .../Package/createUiDefinition.json | 42 +- .../Package/mainTemplate.json | 3379 +++++- .../Package/testParameters.json | 28 + .../ReleaseNotes.md | 1 + .../SolutionMetadata.json | 5 +- .../MicrosoftDefenderForOffice365.json | 9270 +++++++++++++++++ 8 files changed, 12705 insertions(+), 27 deletions(-) create mode 100644 Solutions/Microsoft Defender for Office 365/Package/3.2.0.zip create mode 100644 Solutions/Microsoft Defender for Office 365/XDR Workbooks/MicrosoftDefenderForOffice365.json diff --git a/Solutions/Microsoft Defender for Office 365/Data/Solution_MicrosoftDefenderforOffice365.json b/Solutions/Microsoft Defender for Office 365/Data/Solution_MicrosoftDefenderforOffice365.json index 6f2c144597c..b2f1408ca46 100644 --- a/Solutions/Microsoft Defender for Office 365/Data/Solution_MicrosoftDefenderforOffice365.json +++ b/Solutions/Microsoft Defender for Office 365/Data/Solution_MicrosoftDefenderforOffice365.json @@ -18,10 +18,13 @@ "Solutions/Microsoft Defender for Office 365/Playbooks/O365DefenderPlaybooks/o365-DeleteMaliciousInboxRule/azuredeploy.json" ], "BasePath": "C:\\GitHub\\Azure-Sentinel\\", - "Version": "3.0.3", + "Version": "3.2.0", "Metadata": "SolutionMetadata.json", "TemplateSpec": true, "StaticDataConnectorIds": [ "OfficeATP" + ], + "XDR Workbooks": [ + "XDR Workbooks/MicrosoftDefenderForOffice365.json" ] -} \ No newline at end of file +} diff --git a/Solutions/Microsoft Defender for Office 365/Package/3.2.0.zip b/Solutions/Microsoft Defender for Office 365/Package/3.2.0.zip new file mode 100644 index 0000000000000000000000000000000000000000..e3034385c30968dd484a5cd17f6bd23c7482685e GIT binary patch literal 39011 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 literal 0 HcmV?d00001 diff --git a/Solutions/Microsoft Defender for Office 365/Package/createUiDefinition.json b/Solutions/Microsoft Defender for Office 365/Package/createUiDefinition.json index d3dc0252186..b228c65b18f 100644 --- a/Solutions/Microsoft Defender for Office 365/Package/createUiDefinition.json +++ b/Solutions/Microsoft Defender for Office 365/Package/createUiDefinition.json @@ -6,7 +6,7 @@ "config": { "isWizard": false, "basics": { - "description": "\n\n**Note:** Please refer to the following before installing the solution: \n\n• Review the solution [Release Notes](https://github.com/Azure/Azure-Sentinel/tree/master/Solutions/Microsoft%20Defender%20for%20Office%20365/ReleaseNotes.md)\n\n • There may be [known issues](https://aka.ms/sentinelsolutionsknownissues) pertaining to this Solution, please refer to them before installing.\n\nThe [Microsoft Defender for Office 365](https://www.microsoft.com/security/business/threat-protection/office-365-defender) solution for Microsoft Sentinel enables you to ingest security alerts from the Defender for Office 365 platform, providing visibility into threats within email messages, links (URLs) and collaboration tools.\n\n**Underlying Microsoft Technologies used:**\n\nThis solution is dependent on the following technologies, and some of these dependencies either may be in [Preview](https://azure.microsoft.com/support/legal/preview-supplemental-terms/) state or might result in additional ingestion or operational costs:\n\na. [Codeless Connector Platform/Native Microsoft Sentinel Polling](https://docs.microsoft.com/azure/sentinel/create-codeless-connector?tabs=deploy-via-arm-template%2Cconnect-via-the-azure-portal)\n\n**Data Connectors:** 1, **Workbooks:** 1, **Function Apps:** 1, **Playbooks:** 5\n\n[Learn more about Microsoft Sentinel](https://aka.ms/azuresentinel) | [Learn more about Solutions](https://aka.ms/azuresentinelsolutionsdoc)", + "description": "\n\n**Note:** Please refer to the following before installing the solution: \n\n• Review the solution [Release Notes](https://github.com/Azure/Azure-Sentinel/tree/master/Solutions/Microsoft%20Defender%20for%20Office%20365/ReleaseNotes.md)\n\n • There may be [known issues](https://aka.ms/sentinelsolutionsknownissues) pertaining to this Solution, please refer to them before installing.\n\nThe [Microsoft Defender for Office 365](https://www.microsoft.com/security/business/threat-protection/office-365-defender) solution for Microsoft Sentinel enables you to ingest security alerts from the Defender for Office 365 platform, providing visibility into threats within email messages, links (URLs) and collaboration tools.\n\n**Underlying Microsoft Technologies used:**\n\nThis solution is dependent on the following technologies, and some of these dependencies either may be in [Preview](https://azure.microsoft.com/support/legal/preview-supplemental-terms/) state or might result in additional ingestion or operational costs:\n\na. [Codeless Connector Platform/Native Microsoft Sentinel Polling](https://docs.microsoft.com/azure/sentinel/create-codeless-connector?tabs=deploy-via-arm-template%2Cconnect-via-the-azure-portal)\n\n**Data Connectors:** 1, **Workbooks:** 1, **Function Apps:** 1, **Playbooks:** 5, **XDR Workbooks:** 1\n\n[Learn more about Microsoft Sentinel](https://aka.ms/azuresentinel) | [Learn more about Solutions](https://aka.ms/azuresentinelsolutionsdoc)", "subscription": { "resourceProviders": [ "Microsoft.OperationsManagement/solutions", @@ -51,6 +51,40 @@ } ], "steps": [ + { + "name": "contentSelection", + "label": "Content selection", + "elements": [ + { + "name": "DeployPlaybook", + "type": "Microsoft.Common.CheckBox", + "label": "DeployPlaybook", + "defaultValue": true, + "toolTip": "Deploy the playbooks carried by this solution and the automation assets they depend on (PlaybookTemplate, AzureFunction, LogicAppsCustomConnector). These are never shipped independently of the playbook they serve." + }, + { + "name": "DeployWorkbook", + "type": "Microsoft.Common.CheckBox", + "label": "DeployWorkbook", + "defaultValue": true, + "toolTip": "Deploy the Microsoft Sentinel workbook content and its Content Hub registration carried by this solution (ContentKind Workbook and WorkbookTemplate)." + }, + { + "name": "DeployDefenderWorkbook", + "type": "Microsoft.Common.CheckBox", + "label": "DeployDefenderWorkbook", + "defaultValue": false, + "toolTip": "Deploy Defender Workbooks and their Content Hub registrations independently of Microsoft Sentinel DeployWorkbook. Candidate provider contract requires approved lab installation, readback and update verification." + }, + { + "name": "DeployDataConnector", + "type": "Microsoft.Common.CheckBox", + "label": "DeployDataConnector", + "defaultValue": true, + "toolTip": "Deploy the data connectors carried by this solution, together with their metadata and catalog entries (ContentKind DataConnector, ResourceDataConnector and DataType)." + } + ] + }, { "name": "dataconnectors", "label": "Data Connectors", @@ -149,7 +183,11 @@ "outputs": { "workspace-location": "[first(map(filter(basics('getLAWorkspace').value, (filter) => and(contains(toLower(filter.id), toLower(resourceGroup().name)),equals(filter.name,basics('workspace')))), (item) => item.location))]", "location": "[location()]", - "workspace": "[basics('workspace')]" + "workspace": "[basics('workspace')]", + "DeployPlaybook": "[steps('contentSelection').DeployPlaybook]", + "DeployWorkbook": "[steps('contentSelection').DeployWorkbook]", + "DeployDefenderWorkbook": "[steps('contentSelection').DeployDefenderWorkbook]", + "DeployDataConnector": "[steps('contentSelection').DeployDataConnector]" } } } diff --git a/Solutions/Microsoft Defender for Office 365/Package/mainTemplate.json b/Solutions/Microsoft Defender for Office 365/Package/mainTemplate.json index 7e4995b65b0..6c71a85b353 100644 --- a/Solutions/Microsoft Defender for Office 365/Package/mainTemplate.json +++ b/Solutions/Microsoft Defender for Office 365/Package/mainTemplate.json @@ -35,13 +35,41 @@ "metadata": { "description": "Name for the workbook" } + }, + "DeployPlaybook": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Deploy the playbooks carried by this solution and the automation assets they depend on (PlaybookTemplate, AzureFunction, LogicAppsCustomConnector). These are never shipped independently of the playbook they serve." + } + }, + "DeployWorkbook": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Deploy the Microsoft Sentinel workbook content and its Content Hub registration carried by this solution (ContentKind Workbook and WorkbookTemplate)." + } + }, + "DeployDefenderWorkbook": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Deploy Defender Workbooks and their Content Hub registrations independently of Microsoft Sentinel DeployWorkbook. Candidate provider contract requires approved lab installation, readback and update verification." + } + }, + "DeployDataConnector": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Deploy the data connectors carried by this solution, together with their metadata and catalog entries (ContentKind DataConnector, ResourceDataConnector and DataType)." + } } }, "variables": { "email": "support@microsoft.com", "_email": "[variables('email')]", "_solutionName": "Microsoft Defender for Office 365", - "_solutionVersion": "3.0.3", + "_solutionVersion": "3.2.0", "solutionId": "azuresentinel.azure-sentinel-solution-microsoftdefenderforo365", "_solutionId": "[variables('solutionId')]", "uiConfigId1": "OfficeATP", @@ -121,7 +149,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "Microsoft Defender for Office 365 data connector with template version 3.0.3", + "description": "Microsoft Defender for Office 365 data connector with template version 3.2.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('dataConnectorVersion1')]", @@ -203,7 +231,8 @@ "contentProductId": "[variables('_dataConnectorcontentProductId1')]", "id": "[variables('_dataConnectorcontentProductId1')]", "version": "[variables('dataConnectorVersion1')]" - } + }, + "condition": "[parameters('DeployDataConnector')]" }, { "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", @@ -233,7 +262,8 @@ "email": "support@microsoft.com", "link": "https://support.microsoft.com/" } - } + }, + "condition": "[parameters('DeployDataConnector')]" }, { "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId1'))]", @@ -269,7 +299,8 @@ ], "id": "[variables('_uiConfigId1')]" } - } + }, + "condition": "[parameters('DeployDataConnector')]" }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", @@ -280,7 +311,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "MicrosoftDefenderForOffice365 Workbook with template version 3.0.3", + "description": "MicrosoftDefenderForOffice365 Workbook with template version 3.2.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('workbookVersion1')]", @@ -361,7 +392,8 @@ "contentProductId": "[variables('_workbookcontentProductId1')]", "id": "[variables('_workbookcontentProductId1')]", "version": "[variables('workbookVersion1')]" - } + }, + "condition": "[parameters('DeployWorkbook')]" }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", @@ -372,7 +404,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "O365_Defender_FunctionAppConnector Playbook with template version 3.0.3", + "description": "O365_Defender_FunctionAppConnector Playbook with template version 3.2.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('playbookVersion1')]", @@ -536,7 +568,8 @@ "contentProductId": "[variables('_playbookcontentProductId1')]", "id": "[variables('_playbookcontentProductId1')]", "version": "[variables('playbookVersion1')]" - } + }, + "condition": "[parameters('DeployPlaybook')]" }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", @@ -547,7 +580,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "o365-BlockMalwareFileExtension Playbook with template version 3.0.3", + "description": "o365-BlockMalwareFileExtension Playbook with template version 3.2.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('playbookVersion2')]", @@ -1241,7 +1274,8 @@ "contentProductId": "[variables('_playbookcontentProductId2')]", "id": "[variables('_playbookcontentProductId2')]", "version": "[variables('playbookVersion2')]" - } + }, + "condition": "[parameters('DeployPlaybook')]" }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", @@ -1252,7 +1286,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "o365-BlockSender Playbook with template version 3.0.3", + "description": "o365-BlockSender Playbook with template version 3.2.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('playbookVersion3')]", @@ -1872,7 +1906,8 @@ "contentProductId": "[variables('_playbookcontentProductId3')]", "id": "[variables('_playbookcontentProductId3')]", "version": "[variables('playbookVersion3')]" - } + }, + "condition": "[parameters('DeployPlaybook')]" }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", @@ -1883,7 +1918,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "o365-BlockSender-EntityTrigger Playbook with template version 3.0.3", + "description": "o365-BlockSender-EntityTrigger Playbook with template version 3.2.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('playbookVersion4')]", @@ -2379,7 +2414,8 @@ "contentProductId": "[variables('_playbookcontentProductId4')]", "id": "[variables('_playbookcontentProductId4')]", "version": "[variables('playbookVersion4')]" - } + }, + "condition": "[parameters('DeployPlaybook')]" }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", @@ -2390,7 +2426,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "o365-BlockSpamDomain Playbook with template version 3.0.3", + "description": "o365-BlockSpamDomain Playbook with template version 3.2.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('playbookVersion5')]", @@ -3285,7 +3321,8 @@ "contentProductId": "[variables('_playbookcontentProductId5')]", "id": "[variables('_playbookcontentProductId5')]", "version": "[variables('playbookVersion5')]" - } + }, + "condition": "[parameters('DeployPlaybook')]" }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", @@ -3296,7 +3333,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "o365-DeleteMaliciousInboxRule Playbook with template version 3.0.3", + "description": "o365-DeleteMaliciousInboxRule Playbook with template version 3.2.0", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('playbookVersion6')]", @@ -4034,19 +4071,20 @@ "contentProductId": "[variables('_playbookcontentProductId6')]", "id": "[variables('_playbookcontentProductId6')]", "version": "[variables('playbookVersion6')]" - } + }, + "condition": "[parameters('DeployPlaybook')]" }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentPackages", "apiVersion": "2023-04-01-preview", "location": "[parameters('workspace-location')]", "properties": { - "version": "3.0.3", + "version": "3.2.0", "kind": "Solution", "contentSchemaVersion": "3.0.0", "displayName": "Microsoft Defender for Office 365", "publisherDisplayName": "Microsoft Sentinel, Microsoft Corporation", - "descriptionHtml": "

Note: Please refer to the following before installing the solution:

\n

• Review the solution Release Notes

\n

• There may be known issues pertaining to this Solution, please refer to them before installing.

\n

The Microsoft Defender for Office 365 solution for Microsoft Sentinel enables you to ingest security alerts from the Defender for Office 365 platform, providing visibility into threats within email messages, links (URLs) and collaboration tools.

\n

Underlying Microsoft Technologies used:

\n

This solution is dependent on the following technologies, and some of these dependencies either may be in Preview state or might result in additional ingestion or operational costs:

\n
    \n
  1. Codeless Connector Platform/Native Microsoft Sentinel Polling
  2. \n
\n

Data Connectors: 1, Workbooks: 1, Function Apps: 1, Playbooks: 5

\n

Learn more about Microsoft Sentinel | Learn more about Solutions

\n", + "descriptionHtml": "

Note: Please refer to the following before installing the solution:

\n

• Review the solution Release Notes

\n

• There may be known issues pertaining to this Solution, please refer to them before installing.

\n

The Microsoft Defender for Office 365 solution for Microsoft Sentinel enables you to ingest security alerts from the Defender for Office 365 platform, providing visibility into threats within email messages, links (URLs) and collaboration tools.

\n

Underlying Microsoft Technologies used:

\n

This solution is dependent on the following technologies, and some of these dependencies either may be in Preview state or might result in additional ingestion or operational costs:

\n
    \n
  1. Codeless Connector Platform/Native Microsoft Sentinel Polling
  2. \n
\n

Data Connectors: 1, Workbooks: 1, Function Apps: 1, Playbooks: 5, XDR Workbooks: 1

\n

Learn more about Microsoft Sentinel | Learn more about Solutions

\n", "contentKind": "Solution", "contentProductId": "[variables('_solutioncontentProductId')]", "id": "[variables('_solutioncontentProductId')]", @@ -4110,6 +4148,11 @@ "kind": "Playbook", "contentId": "[variables('_o365-DeleteMaliciousInboxRule')]", "version": "[variables('playbookVersion6')]" + }, + { + "kind": "DefenderWorkbook", + "contentId": "3b0f3eee-3047-526b-aae0-e259182d264d", + "version": "3.2.0" } ] }, @@ -4124,6 +4167,3300 @@ } }, "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/', variables('_solutionId'))]" + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2025-04-01", + "name": "DefenderWorkbook-33c60364c58ae6575ab89f793617a040", + "dependsOn": [ + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" + ], + "properties": { + "mode": "Incremental", + "expressionEvaluationOptions": { + "scope": "inner" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "imports": { + "MicrosoftSecurity": { + "provider": "MicrosoftSecurity", + "version": "1.0.0" + } + }, + "resources": { + "workbook": { + "import": "MicrosoftSecurity", + "type": "Microsoft.Security/workbooks@2026-06-01-preview", + "properties": { + "id": "e3cfc632-a943-5434-a5f9-471b080254ba", + "name": "MicrosoftDefenderForOffice365", + "content": { + "version": "Notebook/1.0", + "items": [ + { + "type": 1, + "content": { + "json": "## Microsoft Defender for Office 365\n---\n" + }, + "name": "text - 2" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "2e238f92-709c-410b-93e0-60eab6150a75", + "version": "KqlParameterItem/1.0", + "name": "TimeRange", + "type": 4, + "isRequired": true, + "value": { + "durationMs": 604800000 + }, + "typeSettings": { + "selectableValues": [ + { + "durationMs": 1800000 + }, + { + "durationMs": 3600000 + }, + { + "durationMs": 14400000 + }, + { + "durationMs": 43200000 + }, + { + "durationMs": 86400000 + }, + { + "durationMs": 172800000 + }, + { + "durationMs": 259200000 + }, + { + "durationMs": 604800000 + }, + { + "durationMs": 1209600000 + }, + { + "durationMs": 2592000000 + }, + { + "durationMs": 5184000000 + }, + { + "durationMs": 7776000000 + } + ], + "allowCustom": true + }, + "timeContext": { + "durationMs": 86400000 + } + }, + { + "id": "ec13514a-7e54-4d41-86db-2805727a2fa7", + "version": "KqlParameterItem/1.0", + "name": "About", + "type": 10, + "description": "View release history for this workbook", + "isRequired": true, + "value": "Hide", + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "jsonData": "[[\r\n \"Show\",\r\n \"Hide\"\r\n]" + } + ], + "style": "pills" + }, + "name": "parameters - 1" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "### Email Event Analysis Workbook, version 0.2\r\n\r\nauthor: Brian Delaney, MSFT\r\n\r\nRelease Notes:\r\n\r\n1.0 - Oct 18, 2021\r\n- Initial Release\r\n", + "style": "info" + }, + "name": "text - 0" + } + ] + }, + "conditionalVisibility": { + "parameterName": "About", + "comparison": "isEqualTo", + "value": "Show" + }, + "name": "AboutGroup" + }, + { + "type": 11, + "content": { + "version": "LinkItem/1.0", + "style": "tabs", + "links": [ + { + "id": "48578fe1-da47-4a4c-b495-ce7fe24ce495", + "cellValue": "Nav", + "linkTarget": "parameter", + "linkLabel": "By Email", + "subTarget": "Email", + "style": "link" + }, + { + "id": "30e93159-8bf5-4006-820f-406ea10bcd17", + "cellValue": "Nav", + "linkTarget": "parameter", + "linkLabel": "By Attachment", + "subTarget": "Attachments", + "style": "link" + }, + { + "id": "c40f76ed-94be-40ff-b65b-3fda306f2c3d", + "cellValue": "Nav", + "linkTarget": "parameter", + "linkLabel": "By Url", + "subTarget": "Url", + "style": "link" + } + ] + }, + "name": "links - 8" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "d6592a34-1ae6-4128-9a72-b9aa6295a0c7", + "version": "KqlParameterItem/1.0", + "name": "EmailDirection", + "type": 2, + "isRequired": true, + "multiSelect": true, + "quote": "'", + "delimiter": ",", + "query": "EmailEvents\r\n| summarize Count=count() by EmailDirection\r\n| sort by Count desc\r\n| project EmailDirection, Label=strcat(EmailDirection, ' - ', Count, ' messages')", + "value": [ + "value::all" + ], + "typeSettings": { + "additionalResourceOptions": [ + "value::all" + ], + "showDefault": false + }, + "timeContext": { + "durationMs": 86400000 + }, + "timeContextFromParameter": "TimeRange", + "defaultValue": "value::all", + "queryType": "advancedHunting" + }, + { + "id": "e63f1a36-a44c-4936-8ad9-30bc7d8587d4", + "version": "KqlParameterItem/1.0", + "name": "Sender", + "label": "Sender Email", + "type": 1, + "timeContext": { + "durationMs": 86400000 + }, + "value": "" + }, + { + "id": "175b1a45-d1f0-4e23-b1dd-a19afab7ef7b", + "version": "KqlParameterItem/1.0", + "name": "Recipient", + "label": "Recipient Email", + "type": 1, + "value": "", + "timeContext": { + "durationMs": 86400000 + } + }, + { + "id": "08bf6816-f40b-46d3-b526-25c846728374", + "version": "KqlParameterItem/1.0", + "name": "RecipientDomain", + "type": 2, + "isRequired": true, + "multiSelect": true, + "quote": "'", + "delimiter": ",", + "query": "EmailEvents\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| summarize Messages=count() by RecipientDomain\r\n| sort by Messages desc\r\n| project RecipientDomain, strcat(RecipientDomain, ' - ', Messages, ' messages')", + "value": [ + "value::all" + ], + "typeSettings": { + "additionalResourceOptions": [ + "value::all" + ], + "selectAllValue": "*", + "showDefault": false + }, + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting" + }, + { + "id": "4046b6e4-7487-48e2-a99f-b74975c738e5", + "version": "KqlParameterItem/1.0", + "name": "SenderDomain", + "type": 2, + "isRequired": true, + "multiSelect": true, + "quote": "'", + "delimiter": ",", + "query": "EmailEvents\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n//| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| summarize Messages=count() by SenderMailFromDomain\r\n| sort by Messages desc\r\n| project SenderMailFromDomain, strcat(SenderMailFromDomain, ' - ', Messages, ' messages')", + "typeSettings": { + "additionalResourceOptions": [ + "value::all" + ], + "selectAllValue": "*", + "showDefault": false + }, + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "defaultValue": "value::all", + "queryType": "advancedHunting" + }, + { + "id": "86a41861-0346-4a1a-95f7-8e1b5db915c1", + "version": "KqlParameterItem/1.0", + "name": "Subject", + "type": 1, + "value": "", + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange" + }, + { + "id": "ae9bd4c6-f68a-486b-ba8b-1b8abf27e67d", + "version": "KqlParameterItem/1.0", + "name": "MinimumAttachmentCount", + "type": 2, + "description": "Only include messages that have at least this many attachments", + "isRequired": true, + "query": "range x from 0 to 10 step 1", + "value": "0", + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "timeContext": { + "durationMs": 86400000 + }, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting" + }, + { + "id": "a7bc4598-cf37-45b5-9049-ac62678f147b", + "version": "KqlParameterItem/1.0", + "name": "MinimumURLCount", + "type": 2, + "description": "Only include messages that have at least these many embedded URLs", + "isRequired": true, + "query": "range x from 0 to 20 step 1", + "value": "0", + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting" + } + ], + "style": "above" + }, + "name": "parameters - 1 - Copy" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize Count=count() by EmailDirection\r\n| sort by Count desc", + "size": 1, + "title": "Email Direction", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "EmailDirection", + "exportParameterName": "Direction", + "exportDefaultValue": "All", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "showBorder": false, + "titleContent": { + "columnMatch": "EmailDirection", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + } + }, + "customWidth": "45", + "conditionalVisibility": { + "parameterName": "Nav", + "comparison": "isNotEqualTo", + "value": "Attachments" + }, + "name": "query - 5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize Count=count() by DeliveryAction\r\n| sort by Count desc", + "size": 1, + "title": "Delivery Action", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "DeliveryAction", + "exportParameterName": "DeliveryAction", + "exportDefaultValue": "All", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "DeliveryAction", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + }, + "showBorder": false + } + }, + "customWidth": "25", + "conditionalVisibility": { + "parameterName": "Nav", + "comparison": "isNotEqualTo", + "value": "Attachments" + }, + "name": "query - 5 - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where \"{DeliveryAction}\" == \"All\" or DeliveryAction == \"{DeliveryAction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize Count=count() by bin(TimeGenerated, {TimeRange:grain}), EmailDirection", + "size": 1, + "title": "Email Timeline", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "EmailAction", + "exportParameterName": "Action", + "exportDefaultValue": "All", + "queryType": "advancedHunting", + "visualization": "timechart", + "tileSettings": { + "titleContent": { + "columnMatch": "DeliveryAction", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + }, + "showBorder": false + } + }, + "customWidth": "30", + "conditionalVisibility": { + "parameterName": "Nav", + "comparison": "isNotEqualTo", + "value": "Attachments" + }, + "name": "query - 5 - Copy - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where \"{DeliveryAction}\" == \"All\" or DeliveryAction == \"{DeliveryAction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize DistinctMessages=dcount(InternetMessageId), DistinctRecipients=dcount(RecipientEmailAddress), DistinctRecipientDomains=dcount(RecipientDomain), NetworkMessageIds=make_set(NetworkMessageId) by SenderMailFromAddress\r\n| sort by DistinctMessages desc", + "size": 0, + "title": "Top Senders", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportedParameters": [ + { + "fieldName": "SenderMailFromAddress", + "parameterName": "Sender2", + "defaultValue": "All" + }, + { + "fieldName": "NetworkMessageIds", + "parameterName": "NetworkMessageIdsSender", + "parameterType": 1, + "defaultValue": "[[]" + } + ], + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "SenderMailFromAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "29ch" + } + }, + { + "columnMatch": "DistinctMessages", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "20ch" + } + }, + { + "columnMatch": "DistinctRecipients", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "21ch" + } + }, + { + "columnMatch": "DistinctRecipientDomains", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "27ch" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "40", + "name": "query - 0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where \"{DeliveryAction}\" == \"All\" or DeliveryAction == \"{DeliveryAction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize DistinctMessages=dcount(InternetMessageId), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientEmailAddress\r\n| sort by DistinctMessages", + "size": 0, + "title": "Top Recipients", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIds", + "exportParameterName": "NetworkMessageIdsRecipient", + "exportDefaultValue": "[[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "RecipientEmailAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "28ch" + } + }, + { + "columnMatch": "DistinctMessages", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "143px" + } + }, + { + "columnMatch": "DistinctSenders", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "140px" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "30", + "name": "query - 0 - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where \"{DeliveryAction}\" == \"All\" or DeliveryAction == \"{DeliveryAction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize DistinctMessages=dcount(InternetMessageId), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientDomain\r\n| sort by DistinctMessages desc", + "size": 0, + "title": "Top Recipient Domains", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIds", + "exportParameterName": "NetworkMessageIdsDomain", + "exportDefaultValue": "[[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "RecipientDomain", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "25.8571ch" + } + }, + { + "columnMatch": "DistinctMessages", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "143px" + } + }, + { + "columnMatch": "DistinctSenders", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "140px" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "30", + "name": "query - 0 - Copy - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let ids = array_concat(dynamic({NetworkMessageIdsSender}),dynamic({NetworkMessageIdsRecipient}),dynamic({NetworkMessageIdsDomain}));\r\nEmailEvents\r\n| where NetworkMessageId in (ids) or array_length(ids) == 0\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where \"{DeliveryAction}\" == \"All\" or DeliveryAction == \"{DeliveryAction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| project TimeGenerated, SenderMailFromAddress, RecipientEmailAddress, Subject, EmailDirection, EmailLanguage, DeliveryAction, ConfidenceLevel, AttachmentCount, UrlCount, NetworkMessageId", + "size": 0, + "showAnalytics": true, + "title": "Message Details", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageId", + "exportParameterName": "NetworkMessageId", + "exportDefaultValue": "None", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "SenderMailFromAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + } + }, + { + "columnMatch": "RecipientEmailAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + } + }, + { + "columnMatch": "Subject", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "35ch" + } + }, + { + "columnMatch": "EmailDirection", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "Outbound", + "representation": "right", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Inbound", + "representation": "left", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Intra-org", + "representation": "Pending", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "DeliveryAction", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "Delivered", + "representation": "success", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Blocked", + "representation": "failed", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Junked", + "representation": "Disable", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "ConfidenceLevel", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "25ch" + } + }, + { + "columnMatch": "AttachmentCount", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "UrlCount", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "NetworkMessageId", + "formatter": 5 + } + ] + } + }, + "name": "query - 6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailAttachmentInfo\r\n| where NetworkMessageId == \"{NetworkMessageId}\"\r\n| project FileName, FileType, SHA256, ThreatTypes, ThreatNames, DetectionMethods", + "size": 0, + "title": "Attached Files", + "noDataMessage": "Either no message was selected or no attachments were present", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting" + }, + "customWidth": "50", + "name": "query - 7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailUrlInfo\r\n| where NetworkMessageId == \"{NetworkMessageId}\"\r\n| project Url, UrlDomain", + "size": 0, + "title": "Embedded URLs", + "noDataMessage": "Either no message was selected or no URLs were present", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting" + }, + "customWidth": "50", + "name": "query - 7 - Copy" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Nav", + "comparison": "isEqualTo", + "value": "Email" + }, + "name": "EmailGroup" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalAttachments=sum(AttachmentCount), DistinctRecipients=dcount(RecipientEmailAddress), DistinctRecipientDomains=dcount(RecipientDomain), NetworkMessageIds=make_set(NetworkMessageId) by SenderMailFromAddress\r\n| where TotalAttachments > 0\r\n| sort by TotalAttachments desc", + "size": 0, + "title": "Top Attachment Senders", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportedParameters": [ + { + "fieldName": "SenderMailFromAddress", + "parameterName": "Sender2", + "defaultValue": "All" + }, + { + "fieldName": "NetworkMessageIds", + "parameterName": "NetworkMessageIdsSender", + "parameterType": 1, + "defaultValue": "[[]" + } + ], + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "SenderMailFromAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "27ch" + } + }, + { + "columnMatch": "TotalAttachments", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "150px" + } + }, + { + "columnMatch": "DistinctRecipients", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "21ch" + } + }, + { + "columnMatch": "DistinctRecipientDomains", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "27ch" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "40", + "name": "query - 0 - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalAttachments=sum(AttachmentCount), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientEmailAddress\r\n| where TotalAttachments > 0\r\n| sort by TotalAttachments desc", + "size": 0, + "title": "Top Attachment Recipients", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIds", + "exportParameterName": "NetworkMessageIdsRecipient", + "exportDefaultValue": "[[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "RecipientEmailAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "28ch" + } + }, + { + "columnMatch": "TotalAttachments", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "20ch" + } + }, + { + "columnMatch": "DistinctSenders", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "140px" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "30", + "name": "query - 0 - Copy - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalAttachments=sum(AttachmentCount), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientDomain\r\n| where TotalAttachments > 0\r\n| sort by TotalAttachments desc", + "size": 0, + "title": "Top Attachment Recipient Domains", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIds", + "exportParameterName": "NetworkMessageIdsDomain", + "exportDefaultValue": "[[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "RecipientDomain", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "25.8571ch" + } + }, + { + "columnMatch": "TotalAttachments", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "22ch" + } + }, + { + "columnMatch": "DistinctSenders", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "140px" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "30", + "name": "query - 0 - Copy - Copy - Copy" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "16f2ef9f-f59b-4a34-87c7-561c4bbfa92e", + "version": "KqlParameterItem/1.0", + "name": "AttachmentName", + "type": 1, + "timeContext": { + "durationMs": 86400000 + }, + "timeContextFromParameter": "TimeRange", + "value": "" + }, + { + "id": "a64d4d00-7f7b-4fc0-991e-1b14e2f7ed1b", + "version": "KqlParameterItem/1.0", + "name": "AttachmentType", + "type": 2, + "isRequired": true, + "multiSelect": true, + "quote": "'", + "delimiter": ",", + "query": "EmailAttachmentInfo\r\n| summarize AttachmentCount=count() by FileType\r\n| sort by AttachmentCount desc\r\n| project FileType, strcat(FileType, ' - ', AttachmentCount, ' attachments')", + "value": [ + "value::all" + ], + "typeSettings": { + "additionalResourceOptions": [ + "value::all" + ], + "selectAllValue": "*", + "showDefault": false + }, + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "defaultValue": "value::all", + "queryType": "advancedHunting" + } + ], + "style": "above" + }, + "name": "parameters - 1" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let ids = array_concat(dynamic({NetworkMessageIdsSender}),dynamic({NetworkMessageIdsRecipient}),dynamic({NetworkMessageIdsDomain}));\r\nEmailAttachmentInfo\r\n| where NetworkMessageId in (ids) or array_length(ids) == 0\r\n| where FileName contains \"{AttachmentName}\"\r\n| where \"*\" in ({AttachmentType}) or FileType in ({AttachmentType})\r\n| summarize UniqueEmailsWithThisAttachment=dcount(NetworkMessageId), NetworkMessageIdWithFile=make_set(NetworkMessageId) by FileName, FileType, SHA256", + "size": 0, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIdWithFile", + "exportParameterName": "NetworkMessageIdWithFile", + "exportDefaultValue": "[[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "NetworkMessageIdWithFile", + "formatter": 5 + } + ], + "sortBy": [ + { + "itemKey": "FileName", + "sortOrder": 1 + } + ] + }, + "sortBy": [ + { + "itemKey": "FileName", + "sortOrder": 1 + } + ] + }, + "name": "query - 0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let ids = dynamic({NetworkMessageIdWithFile});\r\nEmailAttachmentInfo\r\n| where NetworkMessageId in (ids)\r\n| distinct NetworkMessageId\r\n| join kind=leftouter (EmailEvents) on NetworkMessageId\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| project TimeGenerated, SenderMailFromAddress, RecipientEmailAddress, Subject, EmailDirection, EmailLanguage, DeliveryAction, ConfidenceLevel, AttachmentCount, UrlCount, NetworkMessageId", + "size": 0, + "showAnalytics": true, + "title": "Message Details", + "noDataMessage": "No file attachments were selected", + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageId", + "exportParameterName": "NetworkMessageId", + "exportDefaultValue": "None", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "SenderMailFromAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + } + }, + { + "columnMatch": "RecipientEmailAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + } + }, + { + "columnMatch": "Subject", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "35ch" + } + }, + { + "columnMatch": "EmailDirection", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "Outbound", + "representation": "right", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Inbound", + "representation": "left", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Intra-org", + "representation": "Pending", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "DeliveryAction", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "Delivered", + "representation": "success", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Blocked", + "representation": "failed", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Junked", + "representation": "Disable", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "ConfidenceLevel", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "25ch" + } + }, + { + "columnMatch": "AttachmentCount", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "UrlCount", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "NetworkMessageId", + "formatter": 5 + } + ] + } + }, + "name": "query - 6 - Copy" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Nav", + "comparison": "isEqualTo", + "value": "Attachments" + }, + "name": "AttachmentGroup" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalUrls=sum(UrlCount), DistinctRecipients=dcount(RecipientEmailAddress), DistinctRecipientDomains=dcount(RecipientDomain), NetworkMessageIds=make_set(NetworkMessageId) by SenderMailFromAddress\r\n| where TotalUrls > 0\r\n| sort by TotalUrls desc", + "size": 0, + "title": "Top Url Senders", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportedParameters": [ + { + "fieldName": "SenderMailFromAddress", + "parameterName": "Sender2", + "defaultValue": "All" + }, + { + "fieldName": "NetworkMessageIds", + "parameterName": "NetworkMessageIdsSender", + "parameterType": 1, + "defaultValue": "[[]" + } + ], + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "SenderMailFromAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "27ch" + } + }, + { + "columnMatch": "TotalUrls", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "DistinctRecipients", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "21ch" + } + }, + { + "columnMatch": "DistinctRecipientDomains", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "27ch" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "40", + "name": "query - 0 - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalUrls=sum(UrlCount), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientEmailAddress\r\n| where TotalUrls > 0\r\n| sort by TotalUrls desc", + "size": 0, + "title": "Top Url Recipients", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIds", + "exportParameterName": "NetworkMessageIdsRecipient", + "exportDefaultValue": "[[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "RecipientEmailAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "28ch" + } + }, + { + "columnMatch": "TotalUrls", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "DistinctSenders", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "140px" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "30", + "name": "query - 0 - Copy - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalUrls=sum(UrlCount), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientDomain\r\n| where TotalUrls > 0\r\n| sort by TotalUrls desc", + "size": 0, + "title": "Top Url Recipient Domains", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIds", + "exportParameterName": "NetworkMessageIdsDomain", + "exportDefaultValue": "[[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "RecipientDomain", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "25.8571ch" + } + }, + { + "columnMatch": "TotalUrls", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "DistinctSenders", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "140px" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "30", + "name": "query - 0 - Copy - Copy - Copy" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "16f2ef9f-f59b-4a34-87c7-561c4bbfa92e", + "version": "KqlParameterItem/1.0", + "name": "Url", + "type": 1, + "timeContext": { + "durationMs": 86400000 + }, + "timeContextFromParameter": "TimeRange", + "value": "" + }, + { + "id": "a64d4d00-7f7b-4fc0-991e-1b14e2f7ed1b", + "version": "KqlParameterItem/1.0", + "name": "UrlDomain", + "type": 2, + "isRequired": true, + "multiSelect": true, + "quote": "'", + "delimiter": ",", + "query": "EmailUrlInfo\r\n| summarize UrlCount=count() by UrlDomain\r\n| sort by UrlCount desc\r\n| project UrlDomain, strcat(UrlDomain, ' - ', UrlCount, ' URLs')", + "value": [ + "value::all" + ], + "typeSettings": { + "additionalResourceOptions": [ + "value::all" + ], + "selectAllValue": "*", + "showDefault": false + }, + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "defaultValue": "value::all", + "queryType": "advancedHunting" + } + ], + "style": "above" + }, + "name": "parameters - 1" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let ids = array_concat(dynamic({NetworkMessageIdsSender}),dynamic({NetworkMessageIdsRecipient}),dynamic({NetworkMessageIdsDomain}));\r\nEmailUrlInfo\r\n| where NetworkMessageId in (ids) or array_length(ids) == 0\r\n| where Url contains \"{Url}\"\r\n| where \"*\" in ({UrlDomain}) or UrlDomain in ({UrlDomain})\r\n| summarize UniqueMessagesWithUrl=dcount(NetworkMessageId), NetworkMessageIdWithUrl=make_set(NetworkMessageId) by Url, UrlDomain", + "size": 0, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIdWithUrl", + "exportParameterName": "NetworkMessageIdWithUrl", + "exportDefaultValue": "[[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "NetworkMessageIdWithUrl", + "formatter": 5 + } + ] + } + }, + "name": "query - 0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let ids = dynamic({NetworkMessageIdWithUrl});\r\nEmailUrlInfo\r\n| where NetworkMessageId in (ids)\r\n| distinct NetworkMessageId\r\n| join kind=leftouter (EmailEvents) on NetworkMessageId\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| project TimeGenerated, SenderMailFromAddress, RecipientEmailAddress, Subject, EmailDirection, EmailLanguage, DeliveryAction, ConfidenceLevel, AttachmentCount, UrlCount, NetworkMessageId\r\n| sort by TimeGenerated desc", + "size": 0, + "showAnalytics": true, + "title": "Message Details", + "noDataMessage": "No URLs were selected", + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageId", + "exportParameterName": "NetworkMessageId", + "exportDefaultValue": "None", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "SenderMailFromAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + } + }, + { + "columnMatch": "RecipientEmailAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + } + }, + { + "columnMatch": "Subject", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "35ch" + } + }, + { + "columnMatch": "EmailDirection", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "Outbound", + "representation": "right", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Inbound", + "representation": "left", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Intra-org", + "representation": "Pending", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "DeliveryAction", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "Delivered", + "representation": "success", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Blocked", + "representation": "failed", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Junked", + "representation": "Disable", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "ConfidenceLevel", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "25ch" + } + }, + { + "columnMatch": "AttachmentCount", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "UrlCount", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "NetworkMessageId", + "formatter": 5 + } + ] + } + }, + "name": "query - 6 - Copy - Copy" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Nav", + "comparison": "isEqualTo", + "value": "Url" + }, + "name": "UrlGroup" + } + ], + "fromTemplateId": "Community-Workbooks/Microsoft Sentinel - Workbooks/Microsoft Defender for Office 365", + "$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json", + "contentProvenance": { + "packageId": "azuresentinel.azure-sentinel-solution-microsoftdefenderforo365", + "packageVersion": "3.2.0", + "contentId": "3b0f3eee-3047-526b-aae0-e259182d264d", + "contentVersion": "3.2.0" + } + } + } + } + } + } + }, + "condition": "[parameters('DeployDefenderWorkbook')]" + }, + { + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-dwb-',uniqueString('3b0f3eee-3047-526b-aae0-e259182d264d')))]", + "location": "[parameters('workspace-location')]", + "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', 'DefenderWorkbook-33c60364c58ae6575ab89f793617a040')]", + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" + ], + "properties": { + "description": "Defender Workbook: MicrosoftDefenderForOffice365", + "mainTemplate": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "imports": { + "MicrosoftSecurity": { + "provider": "MicrosoftSecurity", + "version": "1.0.0" + } + }, + "resources": { + "workbook": { + "import": "MicrosoftSecurity", + "type": "Microsoft.Security/workbooks@2026-06-01-preview", + "properties": { + "id": "e3cfc632-a943-5434-a5f9-471b080254ba", + "name": "MicrosoftDefenderForOffice365", + "content": { + "version": "Notebook/1.0", + "items": [ + { + "type": 1, + "content": { + "json": "## Microsoft Defender for Office 365\n---\n" + }, + "name": "text - 2" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "2e238f92-709c-410b-93e0-60eab6150a75", + "version": "KqlParameterItem/1.0", + "name": "TimeRange", + "type": 4, + "isRequired": true, + "value": { + "durationMs": 604800000 + }, + "typeSettings": { + "selectableValues": [ + { + "durationMs": 1800000 + }, + { + "durationMs": 3600000 + }, + { + "durationMs": 14400000 + }, + { + "durationMs": 43200000 + }, + { + "durationMs": 86400000 + }, + { + "durationMs": 172800000 + }, + { + "durationMs": 259200000 + }, + { + "durationMs": 604800000 + }, + { + "durationMs": 1209600000 + }, + { + "durationMs": 2592000000 + }, + { + "durationMs": 5184000000 + }, + { + "durationMs": 7776000000 + } + ], + "allowCustom": true + }, + "timeContext": { + "durationMs": 86400000 + } + }, + { + "id": "ec13514a-7e54-4d41-86db-2805727a2fa7", + "version": "KqlParameterItem/1.0", + "name": "About", + "type": 10, + "description": "View release history for this workbook", + "isRequired": true, + "value": "Hide", + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "jsonData": "[[\r\n \"Show\",\r\n \"Hide\"\r\n]" + } + ], + "style": "pills" + }, + "name": "parameters - 1" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "### Email Event Analysis Workbook, version 0.2\r\n\r\nauthor: Brian Delaney, MSFT\r\n\r\nRelease Notes:\r\n\r\n1.0 - Oct 18, 2021\r\n- Initial Release\r\n", + "style": "info" + }, + "name": "text - 0" + } + ] + }, + "conditionalVisibility": { + "parameterName": "About", + "comparison": "isEqualTo", + "value": "Show" + }, + "name": "AboutGroup" + }, + { + "type": 11, + "content": { + "version": "LinkItem/1.0", + "style": "tabs", + "links": [ + { + "id": "48578fe1-da47-4a4c-b495-ce7fe24ce495", + "cellValue": "Nav", + "linkTarget": "parameter", + "linkLabel": "By Email", + "subTarget": "Email", + "style": "link" + }, + { + "id": "30e93159-8bf5-4006-820f-406ea10bcd17", + "cellValue": "Nav", + "linkTarget": "parameter", + "linkLabel": "By Attachment", + "subTarget": "Attachments", + "style": "link" + }, + { + "id": "c40f76ed-94be-40ff-b65b-3fda306f2c3d", + "cellValue": "Nav", + "linkTarget": "parameter", + "linkLabel": "By Url", + "subTarget": "Url", + "style": "link" + } + ] + }, + "name": "links - 8" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "d6592a34-1ae6-4128-9a72-b9aa6295a0c7", + "version": "KqlParameterItem/1.0", + "name": "EmailDirection", + "type": 2, + "isRequired": true, + "multiSelect": true, + "quote": "'", + "delimiter": ",", + "query": "EmailEvents\r\n| summarize Count=count() by EmailDirection\r\n| sort by Count desc\r\n| project EmailDirection, Label=strcat(EmailDirection, ' - ', Count, ' messages')", + "value": [ + "value::all" + ], + "typeSettings": { + "additionalResourceOptions": [ + "value::all" + ], + "showDefault": false + }, + "timeContext": { + "durationMs": 86400000 + }, + "timeContextFromParameter": "TimeRange", + "defaultValue": "value::all", + "queryType": "advancedHunting" + }, + { + "id": "e63f1a36-a44c-4936-8ad9-30bc7d8587d4", + "version": "KqlParameterItem/1.0", + "name": "Sender", + "label": "Sender Email", + "type": 1, + "timeContext": { + "durationMs": 86400000 + }, + "value": "" + }, + { + "id": "175b1a45-d1f0-4e23-b1dd-a19afab7ef7b", + "version": "KqlParameterItem/1.0", + "name": "Recipient", + "label": "Recipient Email", + "type": 1, + "value": "", + "timeContext": { + "durationMs": 86400000 + } + }, + { + "id": "08bf6816-f40b-46d3-b526-25c846728374", + "version": "KqlParameterItem/1.0", + "name": "RecipientDomain", + "type": 2, + "isRequired": true, + "multiSelect": true, + "quote": "'", + "delimiter": ",", + "query": "EmailEvents\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| summarize Messages=count() by RecipientDomain\r\n| sort by Messages desc\r\n| project RecipientDomain, strcat(RecipientDomain, ' - ', Messages, ' messages')", + "value": [ + "value::all" + ], + "typeSettings": { + "additionalResourceOptions": [ + "value::all" + ], + "selectAllValue": "*", + "showDefault": false + }, + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting" + }, + { + "id": "4046b6e4-7487-48e2-a99f-b74975c738e5", + "version": "KqlParameterItem/1.0", + "name": "SenderDomain", + "type": 2, + "isRequired": true, + "multiSelect": true, + "quote": "'", + "delimiter": ",", + "query": "EmailEvents\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n//| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| summarize Messages=count() by SenderMailFromDomain\r\n| sort by Messages desc\r\n| project SenderMailFromDomain, strcat(SenderMailFromDomain, ' - ', Messages, ' messages')", + "typeSettings": { + "additionalResourceOptions": [ + "value::all" + ], + "selectAllValue": "*", + "showDefault": false + }, + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "defaultValue": "value::all", + "queryType": "advancedHunting" + }, + { + "id": "86a41861-0346-4a1a-95f7-8e1b5db915c1", + "version": "KqlParameterItem/1.0", + "name": "Subject", + "type": 1, + "value": "", + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange" + }, + { + "id": "ae9bd4c6-f68a-486b-ba8b-1b8abf27e67d", + "version": "KqlParameterItem/1.0", + "name": "MinimumAttachmentCount", + "type": 2, + "description": "Only include messages that have at least this many attachments", + "isRequired": true, + "query": "range x from 0 to 10 step 1", + "value": "0", + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "timeContext": { + "durationMs": 86400000 + }, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting" + }, + { + "id": "a7bc4598-cf37-45b5-9049-ac62678f147b", + "version": "KqlParameterItem/1.0", + "name": "MinimumURLCount", + "type": 2, + "description": "Only include messages that have at least these many embedded URLs", + "isRequired": true, + "query": "range x from 0 to 20 step 1", + "value": "0", + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting" + } + ], + "style": "above" + }, + "name": "parameters - 1 - Copy" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize Count=count() by EmailDirection\r\n| sort by Count desc", + "size": 1, + "title": "Email Direction", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "EmailDirection", + "exportParameterName": "Direction", + "exportDefaultValue": "All", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "showBorder": false, + "titleContent": { + "columnMatch": "EmailDirection", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + } + }, + "customWidth": "45", + "conditionalVisibility": { + "parameterName": "Nav", + "comparison": "isNotEqualTo", + "value": "Attachments" + }, + "name": "query - 5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize Count=count() by DeliveryAction\r\n| sort by Count desc", + "size": 1, + "title": "Delivery Action", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "DeliveryAction", + "exportParameterName": "DeliveryAction", + "exportDefaultValue": "All", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "DeliveryAction", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + }, + "showBorder": false + } + }, + "customWidth": "25", + "conditionalVisibility": { + "parameterName": "Nav", + "comparison": "isNotEqualTo", + "value": "Attachments" + }, + "name": "query - 5 - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where \"{DeliveryAction}\" == \"All\" or DeliveryAction == \"{DeliveryAction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize Count=count() by bin(TimeGenerated, {TimeRange:grain}), EmailDirection", + "size": 1, + "title": "Email Timeline", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "EmailAction", + "exportParameterName": "Action", + "exportDefaultValue": "All", + "queryType": "advancedHunting", + "visualization": "timechart", + "tileSettings": { + "titleContent": { + "columnMatch": "DeliveryAction", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + }, + "showBorder": false + } + }, + "customWidth": "30", + "conditionalVisibility": { + "parameterName": "Nav", + "comparison": "isNotEqualTo", + "value": "Attachments" + }, + "name": "query - 5 - Copy - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where \"{DeliveryAction}\" == \"All\" or DeliveryAction == \"{DeliveryAction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize DistinctMessages=dcount(InternetMessageId), DistinctRecipients=dcount(RecipientEmailAddress), DistinctRecipientDomains=dcount(RecipientDomain), NetworkMessageIds=make_set(NetworkMessageId) by SenderMailFromAddress\r\n| sort by DistinctMessages desc", + "size": 0, + "title": "Top Senders", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportedParameters": [ + { + "fieldName": "SenderMailFromAddress", + "parameterName": "Sender2", + "defaultValue": "All" + }, + { + "fieldName": "NetworkMessageIds", + "parameterName": "NetworkMessageIdsSender", + "parameterType": 1, + "defaultValue": "[[]" + } + ], + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "SenderMailFromAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "29ch" + } + }, + { + "columnMatch": "DistinctMessages", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "20ch" + } + }, + { + "columnMatch": "DistinctRecipients", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "21ch" + } + }, + { + "columnMatch": "DistinctRecipientDomains", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "27ch" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "40", + "name": "query - 0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where \"{DeliveryAction}\" == \"All\" or DeliveryAction == \"{DeliveryAction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize DistinctMessages=dcount(InternetMessageId), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientEmailAddress\r\n| sort by DistinctMessages", + "size": 0, + "title": "Top Recipients", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIds", + "exportParameterName": "NetworkMessageIdsRecipient", + "exportDefaultValue": "[[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "RecipientEmailAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "28ch" + } + }, + { + "columnMatch": "DistinctMessages", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "143px" + } + }, + { + "columnMatch": "DistinctSenders", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "140px" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "30", + "name": "query - 0 - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where \"{DeliveryAction}\" == \"All\" or DeliveryAction == \"{DeliveryAction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize DistinctMessages=dcount(InternetMessageId), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientDomain\r\n| sort by DistinctMessages desc", + "size": 0, + "title": "Top Recipient Domains", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIds", + "exportParameterName": "NetworkMessageIdsDomain", + "exportDefaultValue": "[[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "RecipientDomain", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "25.8571ch" + } + }, + { + "columnMatch": "DistinctMessages", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "143px" + } + }, + { + "columnMatch": "DistinctSenders", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "140px" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "30", + "name": "query - 0 - Copy - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let ids = array_concat(dynamic({NetworkMessageIdsSender}),dynamic({NetworkMessageIdsRecipient}),dynamic({NetworkMessageIdsDomain}));\r\nEmailEvents\r\n| where NetworkMessageId in (ids) or array_length(ids) == 0\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where \"{DeliveryAction}\" == \"All\" or DeliveryAction == \"{DeliveryAction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| project TimeGenerated, SenderMailFromAddress, RecipientEmailAddress, Subject, EmailDirection, EmailLanguage, DeliveryAction, ConfidenceLevel, AttachmentCount, UrlCount, NetworkMessageId", + "size": 0, + "showAnalytics": true, + "title": "Message Details", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageId", + "exportParameterName": "NetworkMessageId", + "exportDefaultValue": "None", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "SenderMailFromAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + } + }, + { + "columnMatch": "RecipientEmailAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + } + }, + { + "columnMatch": "Subject", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "35ch" + } + }, + { + "columnMatch": "EmailDirection", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "Outbound", + "representation": "right", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Inbound", + "representation": "left", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Intra-org", + "representation": "Pending", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "DeliveryAction", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "Delivered", + "representation": "success", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Blocked", + "representation": "failed", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Junked", + "representation": "Disable", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "ConfidenceLevel", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "25ch" + } + }, + { + "columnMatch": "AttachmentCount", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "UrlCount", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "NetworkMessageId", + "formatter": 5 + } + ] + } + }, + "name": "query - 6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailAttachmentInfo\r\n| where NetworkMessageId == \"{NetworkMessageId}\"\r\n| project FileName, FileType, SHA256, ThreatTypes, ThreatNames, DetectionMethods", + "size": 0, + "title": "Attached Files", + "noDataMessage": "Either no message was selected or no attachments were present", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting" + }, + "customWidth": "50", + "name": "query - 7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailUrlInfo\r\n| where NetworkMessageId == \"{NetworkMessageId}\"\r\n| project Url, UrlDomain", + "size": 0, + "title": "Embedded URLs", + "noDataMessage": "Either no message was selected or no URLs were present", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting" + }, + "customWidth": "50", + "name": "query - 7 - Copy" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Nav", + "comparison": "isEqualTo", + "value": "Email" + }, + "name": "EmailGroup" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalAttachments=sum(AttachmentCount), DistinctRecipients=dcount(RecipientEmailAddress), DistinctRecipientDomains=dcount(RecipientDomain), NetworkMessageIds=make_set(NetworkMessageId) by SenderMailFromAddress\r\n| where TotalAttachments > 0\r\n| sort by TotalAttachments desc", + "size": 0, + "title": "Top Attachment Senders", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportedParameters": [ + { + "fieldName": "SenderMailFromAddress", + "parameterName": "Sender2", + "defaultValue": "All" + }, + { + "fieldName": "NetworkMessageIds", + "parameterName": "NetworkMessageIdsSender", + "parameterType": 1, + "defaultValue": "[[]" + } + ], + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "SenderMailFromAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "27ch" + } + }, + { + "columnMatch": "TotalAttachments", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "150px" + } + }, + { + "columnMatch": "DistinctRecipients", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "21ch" + } + }, + { + "columnMatch": "DistinctRecipientDomains", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "27ch" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "40", + "name": "query - 0 - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalAttachments=sum(AttachmentCount), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientEmailAddress\r\n| where TotalAttachments > 0\r\n| sort by TotalAttachments desc", + "size": 0, + "title": "Top Attachment Recipients", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIds", + "exportParameterName": "NetworkMessageIdsRecipient", + "exportDefaultValue": "[[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "RecipientEmailAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "28ch" + } + }, + { + "columnMatch": "TotalAttachments", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "20ch" + } + }, + { + "columnMatch": "DistinctSenders", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "140px" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "30", + "name": "query - 0 - Copy - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalAttachments=sum(AttachmentCount), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientDomain\r\n| where TotalAttachments > 0\r\n| sort by TotalAttachments desc", + "size": 0, + "title": "Top Attachment Recipient Domains", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIds", + "exportParameterName": "NetworkMessageIdsDomain", + "exportDefaultValue": "[[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "RecipientDomain", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "25.8571ch" + } + }, + { + "columnMatch": "TotalAttachments", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "22ch" + } + }, + { + "columnMatch": "DistinctSenders", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "140px" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "30", + "name": "query - 0 - Copy - Copy - Copy" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "16f2ef9f-f59b-4a34-87c7-561c4bbfa92e", + "version": "KqlParameterItem/1.0", + "name": "AttachmentName", + "type": 1, + "timeContext": { + "durationMs": 86400000 + }, + "timeContextFromParameter": "TimeRange", + "value": "" + }, + { + "id": "a64d4d00-7f7b-4fc0-991e-1b14e2f7ed1b", + "version": "KqlParameterItem/1.0", + "name": "AttachmentType", + "type": 2, + "isRequired": true, + "multiSelect": true, + "quote": "'", + "delimiter": ",", + "query": "EmailAttachmentInfo\r\n| summarize AttachmentCount=count() by FileType\r\n| sort by AttachmentCount desc\r\n| project FileType, strcat(FileType, ' - ', AttachmentCount, ' attachments')", + "value": [ + "value::all" + ], + "typeSettings": { + "additionalResourceOptions": [ + "value::all" + ], + "selectAllValue": "*", + "showDefault": false + }, + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "defaultValue": "value::all", + "queryType": "advancedHunting" + } + ], + "style": "above" + }, + "name": "parameters - 1" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let ids = array_concat(dynamic({NetworkMessageIdsSender}),dynamic({NetworkMessageIdsRecipient}),dynamic({NetworkMessageIdsDomain}));\r\nEmailAttachmentInfo\r\n| where NetworkMessageId in (ids) or array_length(ids) == 0\r\n| where FileName contains \"{AttachmentName}\"\r\n| where \"*\" in ({AttachmentType}) or FileType in ({AttachmentType})\r\n| summarize UniqueEmailsWithThisAttachment=dcount(NetworkMessageId), NetworkMessageIdWithFile=make_set(NetworkMessageId) by FileName, FileType, SHA256", + "size": 0, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIdWithFile", + "exportParameterName": "NetworkMessageIdWithFile", + "exportDefaultValue": "[[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "NetworkMessageIdWithFile", + "formatter": 5 + } + ], + "sortBy": [ + { + "itemKey": "FileName", + "sortOrder": 1 + } + ] + }, + "sortBy": [ + { + "itemKey": "FileName", + "sortOrder": 1 + } + ] + }, + "name": "query - 0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let ids = dynamic({NetworkMessageIdWithFile});\r\nEmailAttachmentInfo\r\n| where NetworkMessageId in (ids)\r\n| distinct NetworkMessageId\r\n| join kind=leftouter (EmailEvents) on NetworkMessageId\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| project TimeGenerated, SenderMailFromAddress, RecipientEmailAddress, Subject, EmailDirection, EmailLanguage, DeliveryAction, ConfidenceLevel, AttachmentCount, UrlCount, NetworkMessageId", + "size": 0, + "showAnalytics": true, + "title": "Message Details", + "noDataMessage": "No file attachments were selected", + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageId", + "exportParameterName": "NetworkMessageId", + "exportDefaultValue": "None", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "SenderMailFromAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + } + }, + { + "columnMatch": "RecipientEmailAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + } + }, + { + "columnMatch": "Subject", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "35ch" + } + }, + { + "columnMatch": "EmailDirection", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "Outbound", + "representation": "right", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Inbound", + "representation": "left", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Intra-org", + "representation": "Pending", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "DeliveryAction", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "Delivered", + "representation": "success", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Blocked", + "representation": "failed", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Junked", + "representation": "Disable", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "ConfidenceLevel", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "25ch" + } + }, + { + "columnMatch": "AttachmentCount", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "UrlCount", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "NetworkMessageId", + "formatter": 5 + } + ] + } + }, + "name": "query - 6 - Copy" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Nav", + "comparison": "isEqualTo", + "value": "Attachments" + }, + "name": "AttachmentGroup" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalUrls=sum(UrlCount), DistinctRecipients=dcount(RecipientEmailAddress), DistinctRecipientDomains=dcount(RecipientDomain), NetworkMessageIds=make_set(NetworkMessageId) by SenderMailFromAddress\r\n| where TotalUrls > 0\r\n| sort by TotalUrls desc", + "size": 0, + "title": "Top Url Senders", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportedParameters": [ + { + "fieldName": "SenderMailFromAddress", + "parameterName": "Sender2", + "defaultValue": "All" + }, + { + "fieldName": "NetworkMessageIds", + "parameterName": "NetworkMessageIdsSender", + "parameterType": 1, + "defaultValue": "[[]" + } + ], + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "SenderMailFromAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "27ch" + } + }, + { + "columnMatch": "TotalUrls", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "DistinctRecipients", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "21ch" + } + }, + { + "columnMatch": "DistinctRecipientDomains", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "27ch" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "40", + "name": "query - 0 - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalUrls=sum(UrlCount), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientEmailAddress\r\n| where TotalUrls > 0\r\n| sort by TotalUrls desc", + "size": 0, + "title": "Top Url Recipients", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIds", + "exportParameterName": "NetworkMessageIdsRecipient", + "exportDefaultValue": "[[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "RecipientEmailAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "28ch" + } + }, + { + "columnMatch": "TotalUrls", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "DistinctSenders", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "140px" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "30", + "name": "query - 0 - Copy - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalUrls=sum(UrlCount), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientDomain\r\n| where TotalUrls > 0\r\n| sort by TotalUrls desc", + "size": 0, + "title": "Top Url Recipient Domains", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIds", + "exportParameterName": "NetworkMessageIdsDomain", + "exportDefaultValue": "[[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "RecipientDomain", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "25.8571ch" + } + }, + { + "columnMatch": "TotalUrls", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "DistinctSenders", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "140px" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "30", + "name": "query - 0 - Copy - Copy - Copy" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "16f2ef9f-f59b-4a34-87c7-561c4bbfa92e", + "version": "KqlParameterItem/1.0", + "name": "Url", + "type": 1, + "timeContext": { + "durationMs": 86400000 + }, + "timeContextFromParameter": "TimeRange", + "value": "" + }, + { + "id": "a64d4d00-7f7b-4fc0-991e-1b14e2f7ed1b", + "version": "KqlParameterItem/1.0", + "name": "UrlDomain", + "type": 2, + "isRequired": true, + "multiSelect": true, + "quote": "'", + "delimiter": ",", + "query": "EmailUrlInfo\r\n| summarize UrlCount=count() by UrlDomain\r\n| sort by UrlCount desc\r\n| project UrlDomain, strcat(UrlDomain, ' - ', UrlCount, ' URLs')", + "value": [ + "value::all" + ], + "typeSettings": { + "additionalResourceOptions": [ + "value::all" + ], + "selectAllValue": "*", + "showDefault": false + }, + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "defaultValue": "value::all", + "queryType": "advancedHunting" + } + ], + "style": "above" + }, + "name": "parameters - 1" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let ids = array_concat(dynamic({NetworkMessageIdsSender}),dynamic({NetworkMessageIdsRecipient}),dynamic({NetworkMessageIdsDomain}));\r\nEmailUrlInfo\r\n| where NetworkMessageId in (ids) or array_length(ids) == 0\r\n| where Url contains \"{Url}\"\r\n| where \"*\" in ({UrlDomain}) or UrlDomain in ({UrlDomain})\r\n| summarize UniqueMessagesWithUrl=dcount(NetworkMessageId), NetworkMessageIdWithUrl=make_set(NetworkMessageId) by Url, UrlDomain", + "size": 0, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIdWithUrl", + "exportParameterName": "NetworkMessageIdWithUrl", + "exportDefaultValue": "[[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "NetworkMessageIdWithUrl", + "formatter": 5 + } + ] + } + }, + "name": "query - 0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let ids = dynamic({NetworkMessageIdWithUrl});\r\nEmailUrlInfo\r\n| where NetworkMessageId in (ids)\r\n| distinct NetworkMessageId\r\n| join kind=leftouter (EmailEvents) on NetworkMessageId\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| project TimeGenerated, SenderMailFromAddress, RecipientEmailAddress, Subject, EmailDirection, EmailLanguage, DeliveryAction, ConfidenceLevel, AttachmentCount, UrlCount, NetworkMessageId\r\n| sort by TimeGenerated desc", + "size": 0, + "showAnalytics": true, + "title": "Message Details", + "noDataMessage": "No URLs were selected", + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageId", + "exportParameterName": "NetworkMessageId", + "exportDefaultValue": "None", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "SenderMailFromAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + } + }, + { + "columnMatch": "RecipientEmailAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + } + }, + { + "columnMatch": "Subject", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "35ch" + } + }, + { + "columnMatch": "EmailDirection", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "Outbound", + "representation": "right", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Inbound", + "representation": "left", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Intra-org", + "representation": "Pending", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "DeliveryAction", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "Delivered", + "representation": "success", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Blocked", + "representation": "failed", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Junked", + "representation": "Disable", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "ConfidenceLevel", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "25ch" + } + }, + { + "columnMatch": "AttachmentCount", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "UrlCount", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "NetworkMessageId", + "formatter": 5 + } + ] + } + }, + "name": "query - 6 - Copy - Copy" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Nav", + "comparison": "isEqualTo", + "value": "Url" + }, + "name": "UrlGroup" + } + ], + "fromTemplateId": "Community-Workbooks/Microsoft Sentinel - Workbooks/Microsoft Defender for Office 365", + "$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json", + "contentProvenance": { + "packageId": "azuresentinel.azure-sentinel-solution-microsoftdefenderforo365", + "packageVersion": "3.2.0", + "contentId": "3b0f3eee-3047-526b-aae0-e259182d264d", + "contentVersion": "3.2.0" + } + } + } + } + } + }, + "packageKind": "Solution", + "packageVersion": "3.2.0", + "packageName": "Microsoft Defender for Office 365", + "packageId": "azuresentinel.azure-sentinel-solution-microsoftdefenderforo365", + "contentSchemaVersion": "3.0.0", + "contentId": "3b0f3eee-3047-526b-aae0-e259182d264d", + "contentKind": "DefenderWorkbook", + "displayName": "MicrosoftDefenderForOffice365", + "contentProductId": "[concat(take(variables('_solutionId'),50),'-','dwb','-', uniqueString(concat(variables('_solutionId'),'-','DefenderWorkbook','-','3b0f3eee-3047-526b-aae0-e259182d264d','-','3.2.0')))]", + "id": "[concat(take(variables('_solutionId'),50),'-','dwb','-', uniqueString(concat(variables('_solutionId'),'-','DefenderWorkbook','-','3b0f3eee-3047-526b-aae0-e259182d264d','-','3.2.0')))]", + "version": "3.2.0", + "contentProvenance": { + "packageId": "azuresentinel.azure-sentinel-solution-microsoftdefenderforo365", + "packageVersion": "3.2.0", + "contentId": "3b0f3eee-3047-526b-aae0-e259182d264d", + "contentVersion": "3.2.0", + "requiredWorkloads": [ + { + "workload": "mdo", + "dataTypes": [ + "EmailAttachmentInfo", + "EmailEvents", + "EmailUrlInfo" + ] + } + ], + "requiredDataConnectors": [], + "requiredWorkspaceFunctions": [] + } + }, + "condition": "[parameters('DeployDefenderWorkbook')]" } ], "outputs": {} diff --git a/Solutions/Microsoft Defender for Office 365/Package/testParameters.json b/Solutions/Microsoft Defender for Office 365/Package/testParameters.json index 92c20c231fc..91b17611141 100644 --- a/Solutions/Microsoft Defender for Office 365/Package/testParameters.json +++ b/Solutions/Microsoft Defender for Office 365/Package/testParameters.json @@ -28,5 +28,33 @@ "metadata": { "description": "Name for the workbook" } + }, + "DeployPlaybook": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Deploy the playbooks carried by this solution and the automation assets they depend on (PlaybookTemplate, AzureFunction, LogicAppsCustomConnector). These are never shipped independently of the playbook they serve." + } + }, + "DeployWorkbook": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Deploy the Microsoft Sentinel workbook content and its Content Hub registration carried by this solution (ContentKind Workbook and WorkbookTemplate)." + } + }, + "DeployDefenderWorkbook": { + "type": "bool", + "defaultValue": false, + "metadata": { + "description": "Deploy Defender Workbooks and their Content Hub registrations independently of Microsoft Sentinel DeployWorkbook. Candidate provider contract requires approved lab installation, readback and update verification." + } + }, + "DeployDataConnector": { + "type": "bool", + "defaultValue": true, + "metadata": { + "description": "Deploy the data connectors carried by this solution, together with their metadata and catalog entries (ContentKind DataConnector, ResourceDataConnector and DataType)." + } } } diff --git a/Solutions/Microsoft Defender for Office 365/ReleaseNotes.md b/Solutions/Microsoft Defender for Office 365/ReleaseNotes.md index 8bc0b1f0429..482452550cf 100644 --- a/Solutions/Microsoft Defender for Office 365/ReleaseNotes.md +++ b/Solutions/Microsoft Defender for Office 365/ReleaseNotes.md @@ -1,5 +1,6 @@ | **Version** | **Date Modified (DD-MM-YYYY)** | **Change History** | |-------------|--------------------------------|--------------------------------------------------------------------------| +| 3.2.0 | 14-10-2026 | Added an **XDR Workbook** alongside the existing Sentinel workbook, preserving the connector and playbooks. | | 3.0.3 | 07-04-2025 | Updated ConnectivityCriteria Type in **Data Connector**. | | 3.0.2 | 24-04-2024 | Updated link for **Custom Connector** redirection in playbooks | | 3.0.1 | 29-09-2023 | 1 new **Playbook** added to the solution | diff --git a/Solutions/Microsoft Defender for Office 365/SolutionMetadata.json b/Solutions/Microsoft Defender for Office 365/SolutionMetadata.json index 181c7dc98d9..fab58220687 100644 --- a/Solutions/Microsoft Defender for Office 365/SolutionMetadata.json +++ b/Solutions/Microsoft Defender for Office 365/SolutionMetadata.json @@ -11,5 +11,6 @@ "name": "Microsoft Corporation", "email": "support@microsoft.com", "link": "https://support.microsoft.com/" - } -} \ No newline at end of file + }, + "version": "3.2.0" +} diff --git a/Solutions/Microsoft Defender for Office 365/XDR Workbooks/MicrosoftDefenderForOffice365.json b/Solutions/Microsoft Defender for Office 365/XDR Workbooks/MicrosoftDefenderForOffice365.json new file mode 100644 index 00000000000..e84440fbbed --- /dev/null +++ b/Solutions/Microsoft Defender for Office 365/XDR Workbooks/MicrosoftDefenderForOffice365.json @@ -0,0 +1,9270 @@ +{ + "version": "Notebook/1.0", + "items": [ + { + "type": 1, + "content": { + "json": "## Microsoft Defender for Office 365\n---\n" + }, + "name": "text - 2" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "2e238f92-709c-410b-93e0-60eab6150a75", + "version": "KqlParameterItem/1.0", + "name": "TimeRange", + "type": 4, + "isRequired": true, + "value": { + "durationMs": 604800000 + }, + "typeSettings": { + "selectableValues": [ + { + "durationMs": 1800000 + }, + { + "durationMs": 3600000 + }, + { + "durationMs": 14400000 + }, + { + "durationMs": 43200000 + }, + { + "durationMs": 86400000 + }, + { + "durationMs": 172800000 + }, + { + "durationMs": 259200000 + }, + { + "durationMs": 604800000 + }, + { + "durationMs": 1209600000 + }, + { + "durationMs": 2592000000 + }, + { + "durationMs": 5184000000 + }, + { + "durationMs": 7776000000 + } + ], + "allowCustom": true + }, + "timeContext": { + "durationMs": 86400000 + } + }, + { + "id": "ec13514a-7e54-4d41-86db-2805727a2fa7", + "version": "KqlParameterItem/1.0", + "name": "About", + "type": 10, + "description": "View release history for this workbook", + "isRequired": true, + "value": "Hide", + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "jsonData": "[\r\n \"Show\",\r\n \"Hide\"\r\n]" + } + ], + "style": "pills" + }, + "name": "parameters - 1" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "### Email Event Analysis Workbook, version 0.2\r\n\r\nauthor: Brian Delaney, MSFT\r\n\r\nRelease Notes:\r\n\r\n1.0 - Oct 18, 2021\r\n- Initial Release\r\n", + "style": "info" + }, + "name": "text - 0" + } + ] + }, + "conditionalVisibility": { + "parameterName": "About", + "comparison": "isEqualTo", + "value": "Show" + }, + "name": "AboutGroup" + }, + { + "type": 11, + "content": { + "version": "LinkItem/1.0", + "style": "tabs", + "links": [ + { + "id": "48578fe1-da47-4a4c-b495-ce7fe24ce495", + "cellValue": "Nav", + "linkTarget": "parameter", + "linkLabel": "By Email", + "subTarget": "Email", + "style": "link" + }, + { + "id": "30e93159-8bf5-4006-820f-406ea10bcd17", + "cellValue": "Nav", + "linkTarget": "parameter", + "linkLabel": "By Attachment", + "subTarget": "Attachments", + "style": "link" + }, + { + "id": "c40f76ed-94be-40ff-b65b-3fda306f2c3d", + "cellValue": "Nav", + "linkTarget": "parameter", + "linkLabel": "By Url", + "subTarget": "Url", + "style": "link" + } + ] + }, + "name": "links - 8" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "d6592a34-1ae6-4128-9a72-b9aa6295a0c7", + "version": "KqlParameterItem/1.0", + "name": "EmailDirection", + "type": 2, + "isRequired": true, + "multiSelect": true, + "quote": "'", + "delimiter": ",", + "query": "EmailEvents\r\n| summarize Count=count() by EmailDirection\r\n| sort by Count desc\r\n| project EmailDirection, Label=strcat(EmailDirection, ' - ', Count, ' messages')", + "value": [ + "value::all" + ], + "typeSettings": { + "additionalResourceOptions": [ + "value::all" + ], + "showDefault": false + }, + "timeContext": { + "durationMs": 86400000 + }, + "timeContextFromParameter": "TimeRange", + "defaultValue": "value::all", + "queryType": "advancedHunting" + }, + { + "id": "e63f1a36-a44c-4936-8ad9-30bc7d8587d4", + "version": "KqlParameterItem/1.0", + "name": "Sender", + "label": "Sender Email", + "type": 1, + "timeContext": { + "durationMs": 86400000 + }, + "value": "" + }, + { + "id": "175b1a45-d1f0-4e23-b1dd-a19afab7ef7b", + "version": "KqlParameterItem/1.0", + "name": "Recipient", + "label": "Recipient Email", + "type": 1, + "value": "", + "timeContext": { + "durationMs": 86400000 + } + }, + { + "id": "08bf6816-f40b-46d3-b526-25c846728374", + "version": "KqlParameterItem/1.0", + "name": "RecipientDomain", + "type": 2, + "isRequired": true, + "multiSelect": true, + "quote": "'", + "delimiter": ",", + "query": "EmailEvents\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| summarize Messages=count() by RecipientDomain\r\n| sort by Messages desc\r\n| project RecipientDomain, strcat(RecipientDomain, ' - ', Messages, ' messages')", + "value": [ + "value::all" + ], + "typeSettings": { + "additionalResourceOptions": [ + "value::all" + ], + "selectAllValue": "*", + "showDefault": false + }, + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting" + }, + { + "id": "4046b6e4-7487-48e2-a99f-b74975c738e5", + "version": "KqlParameterItem/1.0", + "name": "SenderDomain", + "type": 2, + "isRequired": true, + "multiSelect": true, + "quote": "'", + "delimiter": ",", + "query": "EmailEvents\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n//| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| summarize Messages=count() by SenderMailFromDomain\r\n| sort by Messages desc\r\n| project SenderMailFromDomain, strcat(SenderMailFromDomain, ' - ', Messages, ' messages')", + "typeSettings": { + "additionalResourceOptions": [ + "value::all" + ], + "selectAllValue": "*", + "showDefault": false + }, + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "defaultValue": "value::all", + "queryType": "advancedHunting" + }, + { + "id": "86a41861-0346-4a1a-95f7-8e1b5db915c1", + "version": "KqlParameterItem/1.0", + "name": "Subject", + "type": 1, + "value": "", + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange" + }, + { + "id": "ae9bd4c6-f68a-486b-ba8b-1b8abf27e67d", + "version": "KqlParameterItem/1.0", + "name": "MinimumAttachmentCount", + "type": 2, + "description": "Only include messages that have at least this many attachments", + "isRequired": true, + "query": "range x from 0 to 10 step 1", + "value": "0", + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "timeContext": { + "durationMs": 86400000 + }, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting" + }, + { + "id": "a7bc4598-cf37-45b5-9049-ac62678f147b", + "version": "KqlParameterItem/1.0", + "name": "MinimumURLCount", + "type": 2, + "description": "Only include messages that have at least these many embedded URLs", + "isRequired": true, + "query": "range x from 0 to 20 step 1", + "value": "0", + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting" + } + ], + "style": "above" + }, + "name": "parameters - 1 - Copy" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize Count=count() by EmailDirection\r\n| sort by Count desc", + "size": 1, + "title": "Email Direction", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "EmailDirection", + "exportParameterName": "Direction", + "exportDefaultValue": "All", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "showBorder": false, + "titleContent": { + "columnMatch": "EmailDirection", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + } + }, + "customWidth": "45", + "conditionalVisibility": { + "parameterName": "Nav", + "comparison": "isNotEqualTo", + "value": "Attachments" + }, + "name": "query - 5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize Count=count() by DeliveryAction\r\n| sort by Count desc", + "size": 1, + "title": "Delivery Action", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "DeliveryAction", + "exportParameterName": "DeliveryAction", + "exportDefaultValue": "All", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "DeliveryAction", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + }, + "showBorder": false + } + }, + "customWidth": "25", + "conditionalVisibility": { + "parameterName": "Nav", + "comparison": "isNotEqualTo", + "value": "Attachments" + }, + "name": "query - 5 - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where \"{DeliveryAction}\" == \"All\" or DeliveryAction == \"{DeliveryAction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize Count=count() by bin(TimeGenerated, {TimeRange:grain}), EmailDirection", + "size": 1, + "title": "Email Timeline", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "EmailAction", + "exportParameterName": "Action", + "exportDefaultValue": "All", + "queryType": "advancedHunting", + "visualization": "timechart", + "tileSettings": { + "titleContent": { + "columnMatch": "DeliveryAction", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + }, + "showBorder": false + } + }, + "customWidth": "30", + "conditionalVisibility": { + "parameterName": "Nav", + "comparison": "isNotEqualTo", + "value": "Attachments" + }, + "name": "query - 5 - Copy - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where \"{DeliveryAction}\" == \"All\" or DeliveryAction == \"{DeliveryAction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize DistinctMessages=dcount(InternetMessageId), DistinctRecipients=dcount(RecipientEmailAddress), DistinctRecipientDomains=dcount(RecipientDomain), NetworkMessageIds=make_set(NetworkMessageId) by SenderMailFromAddress\r\n| sort by DistinctMessages desc", + "size": 0, + "title": "Top Senders", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportedParameters": [ + { + "fieldName": "SenderMailFromAddress", + "parameterName": "Sender2", + "defaultValue": "All" + }, + { + "fieldName": "NetworkMessageIds", + "parameterName": "NetworkMessageIdsSender", + "parameterType": 1, + "defaultValue": "[]" + } + ], + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "SenderMailFromAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "29ch" + } + }, + { + "columnMatch": "DistinctMessages", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "20ch" + } + }, + { + "columnMatch": "DistinctRecipients", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "21ch" + } + }, + { + "columnMatch": "DistinctRecipientDomains", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "27ch" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "40", + "name": "query - 0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where \"{DeliveryAction}\" == \"All\" or DeliveryAction == \"{DeliveryAction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize DistinctMessages=dcount(InternetMessageId), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientEmailAddress\r\n| sort by DistinctMessages", + "size": 0, + "title": "Top Recipients", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIds", + "exportParameterName": "NetworkMessageIdsRecipient", + "exportDefaultValue": "[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "RecipientEmailAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "28ch" + } + }, + { + "columnMatch": "DistinctMessages", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "143px" + } + }, + { + "columnMatch": "DistinctSenders", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "140px" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "30", + "name": "query - 0 - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where \"{DeliveryAction}\" == \"All\" or DeliveryAction == \"{DeliveryAction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize DistinctMessages=dcount(InternetMessageId), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientDomain\r\n| sort by DistinctMessages desc", + "size": 0, + "title": "Top Recipient Domains", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIds", + "exportParameterName": "NetworkMessageIdsDomain", + "exportDefaultValue": "[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "RecipientDomain", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "25.8571ch" + } + }, + { + "columnMatch": "DistinctMessages", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "143px" + } + }, + { + "columnMatch": "DistinctSenders", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "140px" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "30", + "name": "query - 0 - Copy - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let ids = array_concat(dynamic({NetworkMessageIdsSender}),dynamic({NetworkMessageIdsRecipient}),dynamic({NetworkMessageIdsDomain}));\r\nEmailEvents\r\n| where NetworkMessageId in (ids) or array_length(ids) == 0\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where \"{DeliveryAction}\" == \"All\" or DeliveryAction == \"{DeliveryAction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| project TimeGenerated, SenderMailFromAddress, RecipientEmailAddress, Subject, EmailDirection, EmailLanguage, DeliveryAction, ConfidenceLevel, AttachmentCount, UrlCount, NetworkMessageId", + "size": 0, + "showAnalytics": true, + "title": "Message Details", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageId", + "exportParameterName": "NetworkMessageId", + "exportDefaultValue": "None", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "SenderMailFromAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + } + }, + { + "columnMatch": "RecipientEmailAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + } + }, + { + "columnMatch": "Subject", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "35ch" + } + }, + { + "columnMatch": "EmailDirection", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "Outbound", + "representation": "right", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Inbound", + "representation": "left", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Intra-org", + "representation": "Pending", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "DeliveryAction", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "Delivered", + "representation": "success", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Blocked", + "representation": "failed", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Junked", + "representation": "Disable", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "ConfidenceLevel", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "25ch" + } + }, + { + "columnMatch": "AttachmentCount", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "UrlCount", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "NetworkMessageId", + "formatter": 5 + } + ] + } + }, + "name": "query - 6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailAttachmentInfo\r\n| where NetworkMessageId == \"{NetworkMessageId}\"\r\n| project FileName, FileType, SHA256, ThreatTypes, ThreatNames, DetectionMethods", + "size": 0, + "title": "Attached Files", + "noDataMessage": "Either no message was selected or no attachments were present", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting" + }, + "customWidth": "50", + "name": "query - 7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailUrlInfo\r\n| where NetworkMessageId == \"{NetworkMessageId}\"\r\n| project Url, UrlDomain", + "size": 0, + "title": "Embedded URLs", + "noDataMessage": "Either no message was selected or no URLs were present", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting" + }, + "customWidth": "50", + "name": "query - 7 - Copy" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Nav", + "comparison": "isEqualTo", + "value": "Email" + }, + "name": "EmailGroup" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalAttachments=sum(AttachmentCount), DistinctRecipients=dcount(RecipientEmailAddress), DistinctRecipientDomains=dcount(RecipientDomain), NetworkMessageIds=make_set(NetworkMessageId) by SenderMailFromAddress\r\n| where TotalAttachments > 0\r\n| sort by TotalAttachments desc", + "size": 0, + "title": "Top Attachment Senders", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportedParameters": [ + { + "fieldName": "SenderMailFromAddress", + "parameterName": "Sender2", + "defaultValue": "All" + }, + { + "fieldName": "NetworkMessageIds", + "parameterName": "NetworkMessageIdsSender", + "parameterType": 1, + "defaultValue": "[]" + } + ], + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "SenderMailFromAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "27ch" + } + }, + { + "columnMatch": "TotalAttachments", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "150px" + } + }, + { + "columnMatch": "DistinctRecipients", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "21ch" + } + }, + { + "columnMatch": "DistinctRecipientDomains", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "27ch" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "40", + "name": "query - 0 - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalAttachments=sum(AttachmentCount), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientEmailAddress\r\n| where TotalAttachments > 0\r\n| sort by TotalAttachments desc", + "size": 0, + "title": "Top Attachment Recipients", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIds", + "exportParameterName": "NetworkMessageIdsRecipient", + "exportDefaultValue": "[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "RecipientEmailAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "28ch" + } + }, + { + "columnMatch": "TotalAttachments", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "20ch" + } + }, + { + "columnMatch": "DistinctSenders", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "140px" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "30", + "name": "query - 0 - Copy - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalAttachments=sum(AttachmentCount), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientDomain\r\n| where TotalAttachments > 0\r\n| sort by TotalAttachments desc", + "size": 0, + "title": "Top Attachment Recipient Domains", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIds", + "exportParameterName": "NetworkMessageIdsDomain", + "exportDefaultValue": "[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "RecipientDomain", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "25.8571ch" + } + }, + { + "columnMatch": "TotalAttachments", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "22ch" + } + }, + { + "columnMatch": "DistinctSenders", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "140px" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "30", + "name": "query - 0 - Copy - Copy - Copy" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "16f2ef9f-f59b-4a34-87c7-561c4bbfa92e", + "version": "KqlParameterItem/1.0", + "name": "AttachmentName", + "type": 1, + "timeContext": { + "durationMs": 86400000 + }, + "timeContextFromParameter": "TimeRange", + "value": "" + }, + { + "id": "a64d4d00-7f7b-4fc0-991e-1b14e2f7ed1b", + "version": "KqlParameterItem/1.0", + "name": "AttachmentType", + "type": 2, + "isRequired": true, + "multiSelect": true, + "quote": "'", + "delimiter": ",", + "query": "EmailAttachmentInfo\r\n| summarize AttachmentCount=count() by FileType\r\n| sort by AttachmentCount desc\r\n| project FileType, strcat(FileType, ' - ', AttachmentCount, ' attachments')", + "value": [ + "value::all" + ], + "typeSettings": { + "additionalResourceOptions": [ + "value::all" + ], + "selectAllValue": "*", + "showDefault": false + }, + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "defaultValue": "value::all", + "queryType": "advancedHunting" + } + ], + "style": "above" + }, + "name": "parameters - 1" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let ids = array_concat(dynamic({NetworkMessageIdsSender}),dynamic({NetworkMessageIdsRecipient}),dynamic({NetworkMessageIdsDomain}));\r\nEmailAttachmentInfo\r\n| where NetworkMessageId in (ids) or array_length(ids) == 0\r\n| where FileName contains \"{AttachmentName}\"\r\n| where \"*\" in ({AttachmentType}) or FileType in ({AttachmentType})\r\n| summarize UniqueEmailsWithThisAttachment=dcount(NetworkMessageId), NetworkMessageIdWithFile=make_set(NetworkMessageId) by FileName, FileType, SHA256", + "size": 0, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIdWithFile", + "exportParameterName": "NetworkMessageIdWithFile", + "exportDefaultValue": "[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "NetworkMessageIdWithFile", + "formatter": 5 + } + ], + "sortBy": [ + { + "itemKey": "FileName", + "sortOrder": 1 + } + ] + }, + "sortBy": [ + { + "itemKey": "FileName", + "sortOrder": 1 + } + ] + }, + "name": "query - 0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let ids = dynamic({NetworkMessageIdWithFile});\r\nEmailAttachmentInfo\r\n| where NetworkMessageId in (ids)\r\n| distinct NetworkMessageId\r\n| join kind=leftouter (EmailEvents) on NetworkMessageId\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| project TimeGenerated, SenderMailFromAddress, RecipientEmailAddress, Subject, EmailDirection, EmailLanguage, DeliveryAction, ConfidenceLevel, AttachmentCount, UrlCount, NetworkMessageId", + "size": 0, + "showAnalytics": true, + "title": "Message Details", + "noDataMessage": "No file attachments were selected", + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageId", + "exportParameterName": "NetworkMessageId", + "exportDefaultValue": "None", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "SenderMailFromAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + } + }, + { + "columnMatch": "RecipientEmailAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + } + }, + { + "columnMatch": "Subject", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "35ch" + } + }, + { + "columnMatch": "EmailDirection", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "Outbound", + "representation": "right", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Inbound", + "representation": "left", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Intra-org", + "representation": "Pending", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "DeliveryAction", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "Delivered", + "representation": "success", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Blocked", + "representation": "failed", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Junked", + "representation": "Disable", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "ConfidenceLevel", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "25ch" + } + }, + { + "columnMatch": "AttachmentCount", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "UrlCount", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "NetworkMessageId", + "formatter": 5 + } + ] + } + }, + "name": "query - 6 - Copy" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Nav", + "comparison": "isEqualTo", + "value": "Attachments" + }, + "name": "AttachmentGroup" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalUrls=sum(UrlCount), DistinctRecipients=dcount(RecipientEmailAddress), DistinctRecipientDomains=dcount(RecipientDomain), NetworkMessageIds=make_set(NetworkMessageId) by SenderMailFromAddress\r\n| where TotalUrls > 0\r\n| sort by TotalUrls desc", + "size": 0, + "title": "Top Url Senders", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportedParameters": [ + { + "fieldName": "SenderMailFromAddress", + "parameterName": "Sender2", + "defaultValue": "All" + }, + { + "fieldName": "NetworkMessageIds", + "parameterName": "NetworkMessageIdsSender", + "parameterType": 1, + "defaultValue": "[]" + } + ], + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "SenderMailFromAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "27ch" + } + }, + { + "columnMatch": "TotalUrls", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "DistinctRecipients", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "21ch" + } + }, + { + "columnMatch": "DistinctRecipientDomains", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "27ch" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "40", + "name": "query - 0 - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalUrls=sum(UrlCount), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientEmailAddress\r\n| where TotalUrls > 0\r\n| sort by TotalUrls desc", + "size": 0, + "title": "Top Url Recipients", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIds", + "exportParameterName": "NetworkMessageIdsRecipient", + "exportDefaultValue": "[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "RecipientEmailAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "28ch" + } + }, + { + "columnMatch": "TotalUrls", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "DistinctSenders", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "140px" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "30", + "name": "query - 0 - Copy - Copy" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalUrls=sum(UrlCount), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientDomain\r\n| where TotalUrls > 0\r\n| sort by TotalUrls desc", + "size": 0, + "title": "Top Url Recipient Domains", + "timeContext": { + "durationMs": 604800000 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIds", + "exportParameterName": "NetworkMessageIdsDomain", + "exportDefaultValue": "[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "RecipientDomain", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "25.8571ch" + } + }, + { + "columnMatch": "TotalUrls", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "DistinctSenders", + "formatter": 4, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "140px" + } + }, + { + "columnMatch": "NetworkMessageIds", + "formatter": 5 + } + ] + } + }, + "customWidth": "30", + "name": "query - 0 - Copy - Copy - Copy" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "16f2ef9f-f59b-4a34-87c7-561c4bbfa92e", + "version": "KqlParameterItem/1.0", + "name": "Url", + "type": 1, + "timeContext": { + "durationMs": 86400000 + }, + "timeContextFromParameter": "TimeRange", + "value": "" + }, + { + "id": "a64d4d00-7f7b-4fc0-991e-1b14e2f7ed1b", + "version": "KqlParameterItem/1.0", + "name": "UrlDomain", + "type": 2, + "isRequired": true, + "multiSelect": true, + "quote": "'", + "delimiter": ",", + "query": "EmailUrlInfo\r\n| summarize UrlCount=count() by UrlDomain\r\n| sort by UrlCount desc\r\n| project UrlDomain, strcat(UrlDomain, ' - ', UrlCount, ' URLs')", + "value": [ + "value::all" + ], + "typeSettings": { + "additionalResourceOptions": [ + "value::all" + ], + "selectAllValue": "*", + "showDefault": false + }, + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "defaultValue": "value::all", + "queryType": "advancedHunting" + } + ], + "style": "above" + }, + "name": "parameters - 1" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let ids = array_concat(dynamic({NetworkMessageIdsSender}),dynamic({NetworkMessageIdsRecipient}),dynamic({NetworkMessageIdsDomain}));\r\nEmailUrlInfo\r\n| where NetworkMessageId in (ids) or array_length(ids) == 0\r\n| where Url contains \"{Url}\"\r\n| where \"*\" in ({UrlDomain}) or UrlDomain in ({UrlDomain})\r\n| summarize UniqueMessagesWithUrl=dcount(NetworkMessageId), NetworkMessageIdWithUrl=make_set(NetworkMessageId) by Url, UrlDomain", + "size": 0, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageIdWithUrl", + "exportParameterName": "NetworkMessageIdWithUrl", + "exportDefaultValue": "[]", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "NetworkMessageIdWithUrl", + "formatter": 5 + } + ] + } + }, + "name": "query - 0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let ids = dynamic({NetworkMessageIdWithUrl});\r\nEmailUrlInfo\r\n| where NetworkMessageId in (ids)\r\n| distinct NetworkMessageId\r\n| join kind=leftouter (EmailEvents) on NetworkMessageId\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| project TimeGenerated, SenderMailFromAddress, RecipientEmailAddress, Subject, EmailDirection, EmailLanguage, DeliveryAction, ConfidenceLevel, AttachmentCount, UrlCount, NetworkMessageId\r\n| sort by TimeGenerated desc", + "size": 0, + "showAnalytics": true, + "title": "Message Details", + "noDataMessage": "No URLs were selected", + "timeContext": { + "durationMs": 0 + }, + "timeContextFromParameter": "TimeRange", + "exportFieldName": "NetworkMessageId", + "exportParameterName": "NetworkMessageId", + "exportDefaultValue": "None", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "SenderMailFromAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + } + }, + { + "columnMatch": "RecipientEmailAddress", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + } + }, + { + "columnMatch": "Subject", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "35ch" + } + }, + { + "columnMatch": "EmailDirection", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "Outbound", + "representation": "right", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Inbound", + "representation": "left", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Intra-org", + "representation": "Pending", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "DeliveryAction", + "formatter": 18, + "formatOptions": { + "thresholdsOptions": "icons", + "thresholdsGrid": [ + { + "operator": "==", + "thresholdValue": "Delivered", + "representation": "success", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Blocked", + "representation": "failed", + "text": "{0}{1}" + }, + { + "operator": "==", + "thresholdValue": "Junked", + "representation": "Disable", + "text": "{0}{1}" + }, + { + "operator": "Default", + "thresholdValue": null, + "representation": "unknown", + "text": "{0}{1}" + } + ] + } + }, + { + "columnMatch": "ConfidenceLevel", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "25ch" + } + }, + { + "columnMatch": "AttachmentCount", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "UrlCount", + "formatter": 4, + "formatOptions": { + "palette": "blue" + } + }, + { + "columnMatch": "NetworkMessageId", + "formatter": 5 + } + ] + } + }, + "name": "query - 6 - Copy - Copy" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Nav", + "comparison": "isEqualTo", + "value": "Url" + }, + "name": "UrlGroup" + } + ], + "fromTemplateId": "Community-Workbooks/Microsoft Sentinel - Workbooks/Microsoft Defender for Office 365", + "$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json", + "xdrMetadata": { + "contentId": "3b0f3eee-3047-526b-aae0-e259182d264d", + "instanceId": "e3cfc632-a943-5434-a5f9-471b080254ba", + "version": "3.2.0", + "schemaVersion": "1.0.0", + "displayName": "MicrosoftDefenderForOffice365" + }, + "contentProvenance": { + "source": { + "path": "Workbooks/MicrosoftDefenderForOffice365.json", + "sha256": "f5a3bf4c9e78da40ecf14db1e2f71fe04c2e3bec9b51cc304f7fbaa3d75b03b6", + "contentId": "Community-Workbooks/Microsoft Sentinel - Workbooks/Microsoft Defender for Office 365", + "originalMetadataVersion": null + }, + "conversion": { + "tool": "sentinel-xdr-migration", + "version": "0.1.0", + "reviewRequired": false, + "queries": [ + { + "sourcePath": "/items/1/content/parameters/1/query", + "status": "removed-scope-helper", + "outputPath": null, + "sourceSha256": "49d6e69eb90170912b1e70a4d8c01d3f19d11b10c46b8a72ba0fda4cfc4a6257", + "targetSha256": null + }, + { + "sourcePath": "/items/4/content/parameters/0/query", + "parameter": true, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "7f54b87b3feb094d04d4d4005a9f3aedf53ecfa4fe7a98936125c3634ea3a838" + }, + "conversion": { + "sourceId": "/items/4/content/parameters/0/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "EmailEvents\r\n| summarize Count=count() by EmailDirection\r\n| sort by Count desc\r\n| project EmailDirection, Label=strcat(EmailDirection, ' - ', Count, ' messages')", + "resolvedTables": [ + "EmailEvents" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailEvents", + "ahTable": "EmailEvents", + "identical": false, + "verdict": "Hard", + "score": 0.98, + "columns": [ + { + "sentinel": "AdditionalFields", + "ah": "AdditionalFields", + "laType": "dynamic", + "ahType": "string", + "relation": "compatible" + }, + { + "sentinel": "AttachmentCount", + "ah": "AttachmentCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "AuthenticationDetails", + "ah": "AuthenticationDetails", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "BulkComplaintLevel", + "ah": "BulkComplaintLevel", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "Cc", + "ah": "Cc", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "ConfidenceLevel", + "ah": "ConfidenceLevel", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Connectors", + "ah": "Connectors", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Context", + "ah": "Context", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryAction", + "ah": "DeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryLocation", + "ah": "DeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DetectionMethods", + "ah": "DetectionMethods", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DistributionList", + "ah": "DistributionList", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailAction", + "ah": "EmailAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicy", + "ah": "EmailActionPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicyGuid", + "ah": "EmailActionPolicyGuid", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailClusterId", + "ah": "EmailClusterId", + "laType": "long", + "ahType": "long", + "relation": "exact" + }, + { + "sentinel": "EmailDirection", + "ah": "EmailDirection", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailLanguage", + "ah": "EmailLanguage", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailSize", + "ah": "EmailSize", + "laType": "int", + "ahType": "long", + "relation": "compatible" + }, + { + "sentinel": "ExchangeTransportRule", + "ah": "ExchangeTransportRule", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ForwardingInformation", + "ah": "ForwardingInformation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "InternetMessageId", + "ah": "InternetMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "IsFirstContact", + "ah": "IsFirstContact", + "laType": "bool", + "ahType": "bool", + "relation": "exact" + }, + { + "sentinel": "LastEventExecutionTime", + "laType": "datetime", + "ah": null, + "ahType": null, + "relation": "missing", + "suggestion": null, + "suggestionSource": null, + "note": "no direct AH equivalent; flag for review" + }, + { + "sentinel": "LatestDeliveryAction", + "ah": "LatestDeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "LatestDeliveryLocation", + "ah": "LatestDeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "NetworkMessageId", + "ah": "NetworkMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelAction", + "ah": "OrgLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelPolicy", + "ah": "OrgLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientDomain", + "ah": "RecipientDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientEmailAddress", + "ah": "RecipientEmailAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientObjectId", + "ah": "RecipientObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ReportId", + "ah": "ReportId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderDisplayName", + "ah": "SenderDisplayName", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromAddress", + "ah": "SenderFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromDomain", + "ah": "SenderFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv4", + "ah": "SenderIPv4", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv6", + "ah": "SenderIPv6", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromAddress", + "ah": "SenderMailFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromDomain", + "ah": "SenderMailFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderObjectId", + "ah": "SenderObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Subject", + "ah": "Subject", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatClassification", + "ah": "ThreatClassification", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatNames", + "ah": "ThreatNames", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatTypes", + "ah": "ThreatTypes", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "TimeGenerated", + "ah": "TimeGenerated", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "Timestamp", + "ah": "Timestamp", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "To", + "ah": "To", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "UrlCount", + "ah": "UrlCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "UserLevelAction", + "ah": "UserLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "UserLevelPolicy", + "ah": "UserLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + } + ], + "extraInAh": [] + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/4/content/parameters/0/query", + "sourceSha256": "7f54b87b3feb094d04d4d4005a9f3aedf53ecfa4fe7a98936125c3634ea3a838", + "targetSha256": "7f54b87b3feb094d04d4d4005a9f3aedf53ecfa4fe7a98936125c3634ea3a838" + }, + { + "sourcePath": "/items/4/content/parameters/3/query", + "parameter": true, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "401ad405a538f1d6bf18b4ddda22dfb3dc43af22b62126b5b7af8b7f7f1a2a2d" + }, + "conversion": { + "sourceId": "/items/4/content/parameters/3/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "EmailEvents\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| summarize Messages=count() by RecipientDomain\r\n| sort by Messages desc\r\n| project RecipientDomain, strcat(RecipientDomain, ' - ', Messages, ' messages')", + "resolvedTables": [ + "EmailEvents" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailEvents", + "ahTable": "EmailEvents", + "identical": false, + "verdict": "Hard", + "score": 0.98, + "columns": [ + { + "sentinel": "AdditionalFields", + "ah": "AdditionalFields", + "laType": "dynamic", + "ahType": "string", + "relation": "compatible" + }, + { + "sentinel": "AttachmentCount", + "ah": "AttachmentCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "AuthenticationDetails", + "ah": "AuthenticationDetails", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "BulkComplaintLevel", + "ah": "BulkComplaintLevel", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "Cc", + "ah": "Cc", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "ConfidenceLevel", + "ah": "ConfidenceLevel", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Connectors", + "ah": "Connectors", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Context", + "ah": "Context", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryAction", + "ah": "DeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryLocation", + "ah": "DeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DetectionMethods", + "ah": "DetectionMethods", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DistributionList", + "ah": "DistributionList", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailAction", + "ah": "EmailAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicy", + "ah": "EmailActionPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicyGuid", + "ah": "EmailActionPolicyGuid", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailClusterId", + "ah": "EmailClusterId", + "laType": "long", + "ahType": "long", + "relation": "exact" + }, + { + "sentinel": "EmailDirection", + "ah": "EmailDirection", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailLanguage", + "ah": "EmailLanguage", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailSize", + "ah": "EmailSize", + "laType": "int", + "ahType": "long", + "relation": "compatible" + }, + { + "sentinel": "ExchangeTransportRule", + "ah": "ExchangeTransportRule", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ForwardingInformation", + "ah": "ForwardingInformation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "InternetMessageId", + "ah": "InternetMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "IsFirstContact", + "ah": "IsFirstContact", + "laType": "bool", + "ahType": "bool", + "relation": "exact" + }, + { + "sentinel": "LastEventExecutionTime", + "laType": "datetime", + "ah": null, + "ahType": null, + "relation": "missing", + "suggestion": null, + "suggestionSource": null, + "note": "no direct AH equivalent; flag for review" + }, + { + "sentinel": "LatestDeliveryAction", + "ah": "LatestDeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "LatestDeliveryLocation", + "ah": "LatestDeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "NetworkMessageId", + "ah": "NetworkMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelAction", + "ah": "OrgLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelPolicy", + "ah": "OrgLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientDomain", + "ah": "RecipientDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientEmailAddress", + "ah": "RecipientEmailAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientObjectId", + "ah": "RecipientObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ReportId", + "ah": "ReportId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderDisplayName", + "ah": "SenderDisplayName", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromAddress", + "ah": "SenderFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromDomain", + "ah": "SenderFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv4", + "ah": "SenderIPv4", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv6", + "ah": "SenderIPv6", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromAddress", + "ah": "SenderMailFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromDomain", + "ah": "SenderMailFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderObjectId", + "ah": "SenderObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Subject", + "ah": "Subject", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatClassification", + "ah": "ThreatClassification", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatNames", + "ah": "ThreatNames", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatTypes", + "ah": "ThreatTypes", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "TimeGenerated", + "ah": "TimeGenerated", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "Timestamp", + "ah": "Timestamp", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "To", + "ah": "To", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "UrlCount", + "ah": "UrlCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "UserLevelAction", + "ah": "UserLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "UserLevelPolicy", + "ah": "UserLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + } + ], + "extraInAh": [] + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/4/content/parameters/3/query", + "sourceSha256": "401ad405a538f1d6bf18b4ddda22dfb3dc43af22b62126b5b7af8b7f7f1a2a2d", + "targetSha256": "401ad405a538f1d6bf18b4ddda22dfb3dc43af22b62126b5b7af8b7f7f1a2a2d" + }, + { + "sourcePath": "/items/4/content/parameters/4/query", + "parameter": true, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "20ebec2f05e9277cdeb1fee33107843071509781d6f112850759b947dfd5cf44" + }, + "conversion": { + "sourceId": "/items/4/content/parameters/4/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "EmailEvents\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n//| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| summarize Messages=count() by SenderMailFromDomain\r\n| sort by Messages desc\r\n| project SenderMailFromDomain, strcat(SenderMailFromDomain, ' - ', Messages, ' messages')", + "resolvedTables": [ + "EmailEvents" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailEvents", + "ahTable": "EmailEvents", + "identical": false, + "verdict": "Hard", + "score": 0.98, + "columns": [ + { + "sentinel": "AdditionalFields", + "ah": "AdditionalFields", + "laType": "dynamic", + "ahType": "string", + "relation": "compatible" + }, + { + "sentinel": "AttachmentCount", + "ah": "AttachmentCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "AuthenticationDetails", + "ah": "AuthenticationDetails", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "BulkComplaintLevel", + "ah": "BulkComplaintLevel", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "Cc", + "ah": "Cc", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "ConfidenceLevel", + "ah": "ConfidenceLevel", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Connectors", + "ah": "Connectors", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Context", + "ah": "Context", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryAction", + "ah": "DeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryLocation", + "ah": "DeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DetectionMethods", + "ah": "DetectionMethods", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DistributionList", + "ah": "DistributionList", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailAction", + "ah": "EmailAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicy", + "ah": "EmailActionPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicyGuid", + "ah": "EmailActionPolicyGuid", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailClusterId", + "ah": "EmailClusterId", + "laType": "long", + "ahType": "long", + "relation": "exact" + }, + { + "sentinel": "EmailDirection", + "ah": "EmailDirection", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailLanguage", + "ah": "EmailLanguage", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailSize", + "ah": "EmailSize", + "laType": "int", + "ahType": "long", + "relation": "compatible" + }, + { + "sentinel": "ExchangeTransportRule", + "ah": "ExchangeTransportRule", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ForwardingInformation", + "ah": "ForwardingInformation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "InternetMessageId", + "ah": "InternetMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "IsFirstContact", + "ah": "IsFirstContact", + "laType": "bool", + "ahType": "bool", + "relation": "exact" + }, + { + "sentinel": "LastEventExecutionTime", + "laType": "datetime", + "ah": null, + "ahType": null, + "relation": "missing", + "suggestion": null, + "suggestionSource": null, + "note": "no direct AH equivalent; flag for review" + }, + { + "sentinel": "LatestDeliveryAction", + "ah": "LatestDeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "LatestDeliveryLocation", + "ah": "LatestDeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "NetworkMessageId", + "ah": "NetworkMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelAction", + "ah": "OrgLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelPolicy", + "ah": "OrgLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientDomain", + "ah": "RecipientDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientEmailAddress", + "ah": "RecipientEmailAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientObjectId", + "ah": "RecipientObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ReportId", + "ah": "ReportId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderDisplayName", + "ah": "SenderDisplayName", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromAddress", + "ah": "SenderFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromDomain", + "ah": "SenderFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv4", + "ah": "SenderIPv4", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv6", + "ah": "SenderIPv6", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromAddress", + "ah": "SenderMailFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromDomain", + "ah": "SenderMailFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderObjectId", + "ah": "SenderObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Subject", + "ah": "Subject", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatClassification", + "ah": "ThreatClassification", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatNames", + "ah": "ThreatNames", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatTypes", + "ah": "ThreatTypes", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "TimeGenerated", + "ah": "TimeGenerated", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "Timestamp", + "ah": "Timestamp", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "To", + "ah": "To", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "UrlCount", + "ah": "UrlCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "UserLevelAction", + "ah": "UserLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "UserLevelPolicy", + "ah": "UserLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + } + ], + "extraInAh": [] + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/4/content/parameters/4/query", + "sourceSha256": "20ebec2f05e9277cdeb1fee33107843071509781d6f112850759b947dfd5cf44", + "targetSha256": "20ebec2f05e9277cdeb1fee33107843071509781d6f112850759b947dfd5cf44" + }, + { + "sourcePath": "/items/4/content/parameters/6/query", + "parameter": true, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "2ccdaa784725b2a65a8f381ed39f1d053eb36879948ab0bc52508acdc47dbfea" + }, + "conversion": { + "sourceId": "/items/4/content/parameters/6/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "range x from 0 to 10 step 1", + "resolvedTables": [], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/4/content/parameters/6/query", + "sourceSha256": "2ccdaa784725b2a65a8f381ed39f1d053eb36879948ab0bc52508acdc47dbfea", + "targetSha256": "2ccdaa784725b2a65a8f381ed39f1d053eb36879948ab0bc52508acdc47dbfea" + }, + { + "sourcePath": "/items/4/content/parameters/7/query", + "parameter": true, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "e19eb4f4d503984f28cd04aba8a7975c0ff909046d9c3f980c2033c16aaf61d4" + }, + "conversion": { + "sourceId": "/items/4/content/parameters/7/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "range x from 0 to 20 step 1", + "resolvedTables": [], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/4/content/parameters/7/query", + "sourceSha256": "e19eb4f4d503984f28cd04aba8a7975c0ff909046d9c3f980c2033c16aaf61d4", + "targetSha256": "e19eb4f4d503984f28cd04aba8a7975c0ff909046d9c3f980c2033c16aaf61d4" + }, + { + "sourcePath": "/items/5/content/items/0/content/query", + "parameter": false, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "5130357556304e1822967ca2d3d4ec9e725c3d77e54dc8433c51bdfbdbfd6fd6" + }, + "conversion": { + "sourceId": "/items/5/content/items/0/content/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "EmailEvents\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize Count=count() by EmailDirection\r\n| sort by Count desc", + "resolvedTables": [ + "EmailEvents" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailEvents", + "ahTable": "EmailEvents", + "identical": false, + "verdict": "Hard", + "score": 0.98, + "columns": [ + { + "sentinel": "AdditionalFields", + "ah": "AdditionalFields", + "laType": "dynamic", + "ahType": "string", + "relation": "compatible" + }, + { + "sentinel": "AttachmentCount", + "ah": "AttachmentCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "AuthenticationDetails", + "ah": "AuthenticationDetails", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "BulkComplaintLevel", + "ah": "BulkComplaintLevel", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "Cc", + "ah": "Cc", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "ConfidenceLevel", + "ah": "ConfidenceLevel", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Connectors", + "ah": "Connectors", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Context", + "ah": "Context", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryAction", + "ah": "DeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryLocation", + "ah": "DeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DetectionMethods", + "ah": "DetectionMethods", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DistributionList", + "ah": "DistributionList", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailAction", + "ah": "EmailAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicy", + "ah": "EmailActionPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicyGuid", + "ah": "EmailActionPolicyGuid", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailClusterId", + "ah": "EmailClusterId", + "laType": "long", + "ahType": "long", + "relation": "exact" + }, + { + "sentinel": "EmailDirection", + "ah": "EmailDirection", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailLanguage", + "ah": "EmailLanguage", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailSize", + "ah": "EmailSize", + "laType": "int", + "ahType": "long", + "relation": "compatible" + }, + { + "sentinel": "ExchangeTransportRule", + "ah": "ExchangeTransportRule", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ForwardingInformation", + "ah": "ForwardingInformation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "InternetMessageId", + "ah": "InternetMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "IsFirstContact", + "ah": "IsFirstContact", + "laType": "bool", + "ahType": "bool", + "relation": "exact" + }, + { + "sentinel": "LastEventExecutionTime", + "laType": "datetime", + "ah": null, + "ahType": null, + "relation": "missing", + "suggestion": null, + "suggestionSource": null, + "note": "no direct AH equivalent; flag for review" + }, + { + "sentinel": "LatestDeliveryAction", + "ah": "LatestDeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "LatestDeliveryLocation", + "ah": "LatestDeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "NetworkMessageId", + "ah": "NetworkMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelAction", + "ah": "OrgLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelPolicy", + "ah": "OrgLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientDomain", + "ah": "RecipientDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientEmailAddress", + "ah": "RecipientEmailAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientObjectId", + "ah": "RecipientObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ReportId", + "ah": "ReportId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderDisplayName", + "ah": "SenderDisplayName", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromAddress", + "ah": "SenderFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromDomain", + "ah": "SenderFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv4", + "ah": "SenderIPv4", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv6", + "ah": "SenderIPv6", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromAddress", + "ah": "SenderMailFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromDomain", + "ah": "SenderMailFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderObjectId", + "ah": "SenderObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Subject", + "ah": "Subject", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatClassification", + "ah": "ThreatClassification", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatNames", + "ah": "ThreatNames", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatTypes", + "ah": "ThreatTypes", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "TimeGenerated", + "ah": "TimeGenerated", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "Timestamp", + "ah": "Timestamp", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "To", + "ah": "To", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "UrlCount", + "ah": "UrlCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "UserLevelAction", + "ah": "UserLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "UserLevelPolicy", + "ah": "UserLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + } + ], + "extraInAh": [] + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/5/content/items/0/content/query", + "sourceSha256": "5130357556304e1822967ca2d3d4ec9e725c3d77e54dc8433c51bdfbdbfd6fd6", + "targetSha256": "5130357556304e1822967ca2d3d4ec9e725c3d77e54dc8433c51bdfbdbfd6fd6" + }, + { + "sourcePath": "/items/5/content/items/1/content/query", + "parameter": false, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "30207d66db6f1f6958218ce4c293cc0324c5e6dda7f495f168ac1715af0067d8" + }, + "conversion": { + "sourceId": "/items/5/content/items/1/content/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "EmailEvents\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize Count=count() by DeliveryAction\r\n| sort by Count desc", + "resolvedTables": [ + "EmailEvents" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailEvents", + "ahTable": "EmailEvents", + "identical": false, + "verdict": "Hard", + "score": 0.98, + "columns": [ + { + "sentinel": "AdditionalFields", + "ah": "AdditionalFields", + "laType": "dynamic", + "ahType": "string", + "relation": "compatible" + }, + { + "sentinel": "AttachmentCount", + "ah": "AttachmentCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "AuthenticationDetails", + "ah": "AuthenticationDetails", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "BulkComplaintLevel", + "ah": "BulkComplaintLevel", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "Cc", + "ah": "Cc", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "ConfidenceLevel", + "ah": "ConfidenceLevel", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Connectors", + "ah": "Connectors", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Context", + "ah": "Context", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryAction", + "ah": "DeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryLocation", + "ah": "DeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DetectionMethods", + "ah": "DetectionMethods", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DistributionList", + "ah": "DistributionList", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailAction", + "ah": "EmailAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicy", + "ah": "EmailActionPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicyGuid", + "ah": "EmailActionPolicyGuid", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailClusterId", + "ah": "EmailClusterId", + "laType": "long", + "ahType": "long", + "relation": "exact" + }, + { + "sentinel": "EmailDirection", + "ah": "EmailDirection", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailLanguage", + "ah": "EmailLanguage", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailSize", + "ah": "EmailSize", + "laType": "int", + "ahType": "long", + "relation": "compatible" + }, + { + "sentinel": "ExchangeTransportRule", + "ah": "ExchangeTransportRule", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ForwardingInformation", + "ah": "ForwardingInformation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "InternetMessageId", + "ah": "InternetMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "IsFirstContact", + "ah": "IsFirstContact", + "laType": "bool", + "ahType": "bool", + "relation": "exact" + }, + { + "sentinel": "LastEventExecutionTime", + "laType": "datetime", + "ah": null, + "ahType": null, + "relation": "missing", + "suggestion": null, + "suggestionSource": null, + "note": "no direct AH equivalent; flag for review" + }, + { + "sentinel": "LatestDeliveryAction", + "ah": "LatestDeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "LatestDeliveryLocation", + "ah": "LatestDeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "NetworkMessageId", + "ah": "NetworkMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelAction", + "ah": "OrgLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelPolicy", + "ah": "OrgLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientDomain", + "ah": "RecipientDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientEmailAddress", + "ah": "RecipientEmailAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientObjectId", + "ah": "RecipientObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ReportId", + "ah": "ReportId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderDisplayName", + "ah": "SenderDisplayName", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromAddress", + "ah": "SenderFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromDomain", + "ah": "SenderFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv4", + "ah": "SenderIPv4", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv6", + "ah": "SenderIPv6", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromAddress", + "ah": "SenderMailFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromDomain", + "ah": "SenderMailFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderObjectId", + "ah": "SenderObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Subject", + "ah": "Subject", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatClassification", + "ah": "ThreatClassification", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatNames", + "ah": "ThreatNames", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatTypes", + "ah": "ThreatTypes", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "TimeGenerated", + "ah": "TimeGenerated", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "Timestamp", + "ah": "Timestamp", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "To", + "ah": "To", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "UrlCount", + "ah": "UrlCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "UserLevelAction", + "ah": "UserLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "UserLevelPolicy", + "ah": "UserLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + } + ], + "extraInAh": [] + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/5/content/items/1/content/query", + "sourceSha256": "30207d66db6f1f6958218ce4c293cc0324c5e6dda7f495f168ac1715af0067d8", + "targetSha256": "30207d66db6f1f6958218ce4c293cc0324c5e6dda7f495f168ac1715af0067d8" + }, + { + "sourcePath": "/items/5/content/items/2/content/query", + "parameter": false, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "0a650d806076bf2dbdec9b4be3a1fcd8278a60152ae6ad40c8a15ea3d629b295" + }, + "conversion": { + "sourceId": "/items/5/content/items/2/content/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "EmailEvents\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where \"{DeliveryAction}\" == \"All\" or DeliveryAction == \"{DeliveryAction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize Count=count() by bin(TimeGenerated, {TimeRange:grain}), EmailDirection", + "resolvedTables": [ + "EmailEvents" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailEvents", + "ahTable": "EmailEvents", + "identical": false, + "verdict": "Hard", + "score": 0.98, + "columns": [ + { + "sentinel": "AdditionalFields", + "ah": "AdditionalFields", + "laType": "dynamic", + "ahType": "string", + "relation": "compatible" + }, + { + "sentinel": "AttachmentCount", + "ah": "AttachmentCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "AuthenticationDetails", + "ah": "AuthenticationDetails", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "BulkComplaintLevel", + "ah": "BulkComplaintLevel", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "Cc", + "ah": "Cc", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "ConfidenceLevel", + "ah": "ConfidenceLevel", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Connectors", + "ah": "Connectors", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Context", + "ah": "Context", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryAction", + "ah": "DeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryLocation", + "ah": "DeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DetectionMethods", + "ah": "DetectionMethods", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DistributionList", + "ah": "DistributionList", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailAction", + "ah": "EmailAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicy", + "ah": "EmailActionPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicyGuid", + "ah": "EmailActionPolicyGuid", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailClusterId", + "ah": "EmailClusterId", + "laType": "long", + "ahType": "long", + "relation": "exact" + }, + { + "sentinel": "EmailDirection", + "ah": "EmailDirection", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailLanguage", + "ah": "EmailLanguage", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailSize", + "ah": "EmailSize", + "laType": "int", + "ahType": "long", + "relation": "compatible" + }, + { + "sentinel": "ExchangeTransportRule", + "ah": "ExchangeTransportRule", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ForwardingInformation", + "ah": "ForwardingInformation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "InternetMessageId", + "ah": "InternetMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "IsFirstContact", + "ah": "IsFirstContact", + "laType": "bool", + "ahType": "bool", + "relation": "exact" + }, + { + "sentinel": "LastEventExecutionTime", + "laType": "datetime", + "ah": null, + "ahType": null, + "relation": "missing", + "suggestion": null, + "suggestionSource": null, + "note": "no direct AH equivalent; flag for review" + }, + { + "sentinel": "LatestDeliveryAction", + "ah": "LatestDeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "LatestDeliveryLocation", + "ah": "LatestDeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "NetworkMessageId", + "ah": "NetworkMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelAction", + "ah": "OrgLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelPolicy", + "ah": "OrgLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientDomain", + "ah": "RecipientDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientEmailAddress", + "ah": "RecipientEmailAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientObjectId", + "ah": "RecipientObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ReportId", + "ah": "ReportId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderDisplayName", + "ah": "SenderDisplayName", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromAddress", + "ah": "SenderFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromDomain", + "ah": "SenderFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv4", + "ah": "SenderIPv4", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv6", + "ah": "SenderIPv6", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromAddress", + "ah": "SenderMailFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromDomain", + "ah": "SenderMailFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderObjectId", + "ah": "SenderObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Subject", + "ah": "Subject", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatClassification", + "ah": "ThreatClassification", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatNames", + "ah": "ThreatNames", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatTypes", + "ah": "ThreatTypes", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "TimeGenerated", + "ah": "TimeGenerated", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "Timestamp", + "ah": "Timestamp", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "To", + "ah": "To", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "UrlCount", + "ah": "UrlCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "UserLevelAction", + "ah": "UserLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "UserLevelPolicy", + "ah": "UserLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + } + ], + "extraInAh": [] + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/5/content/items/2/content/query", + "sourceSha256": "0a650d806076bf2dbdec9b4be3a1fcd8278a60152ae6ad40c8a15ea3d629b295", + "targetSha256": "0a650d806076bf2dbdec9b4be3a1fcd8278a60152ae6ad40c8a15ea3d629b295" + }, + { + "sourcePath": "/items/5/content/items/3/content/query", + "parameter": false, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "e35a12f2504594c80042fde446d6e57f0e2bc4fc01ab67ee5c580cfbbb8cc55e" + }, + "conversion": { + "sourceId": "/items/5/content/items/3/content/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where \"{DeliveryAction}\" == \"All\" or DeliveryAction == \"{DeliveryAction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize DistinctMessages=dcount(InternetMessageId), DistinctRecipients=dcount(RecipientEmailAddress), DistinctRecipientDomains=dcount(RecipientDomain), NetworkMessageIds=make_set(NetworkMessageId) by SenderMailFromAddress\r\n| sort by DistinctMessages desc", + "resolvedTables": [ + "EmailEvents" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailEvents", + "ahTable": "EmailEvents", + "identical": false, + "verdict": "Hard", + "score": 0.98, + "columns": [ + { + "sentinel": "AdditionalFields", + "ah": "AdditionalFields", + "laType": "dynamic", + "ahType": "string", + "relation": "compatible" + }, + { + "sentinel": "AttachmentCount", + "ah": "AttachmentCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "AuthenticationDetails", + "ah": "AuthenticationDetails", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "BulkComplaintLevel", + "ah": "BulkComplaintLevel", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "Cc", + "ah": "Cc", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "ConfidenceLevel", + "ah": "ConfidenceLevel", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Connectors", + "ah": "Connectors", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Context", + "ah": "Context", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryAction", + "ah": "DeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryLocation", + "ah": "DeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DetectionMethods", + "ah": "DetectionMethods", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DistributionList", + "ah": "DistributionList", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailAction", + "ah": "EmailAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicy", + "ah": "EmailActionPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicyGuid", + "ah": "EmailActionPolicyGuid", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailClusterId", + "ah": "EmailClusterId", + "laType": "long", + "ahType": "long", + "relation": "exact" + }, + { + "sentinel": "EmailDirection", + "ah": "EmailDirection", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailLanguage", + "ah": "EmailLanguage", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailSize", + "ah": "EmailSize", + "laType": "int", + "ahType": "long", + "relation": "compatible" + }, + { + "sentinel": "ExchangeTransportRule", + "ah": "ExchangeTransportRule", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ForwardingInformation", + "ah": "ForwardingInformation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "InternetMessageId", + "ah": "InternetMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "IsFirstContact", + "ah": "IsFirstContact", + "laType": "bool", + "ahType": "bool", + "relation": "exact" + }, + { + "sentinel": "LastEventExecutionTime", + "laType": "datetime", + "ah": null, + "ahType": null, + "relation": "missing", + "suggestion": null, + "suggestionSource": null, + "note": "no direct AH equivalent; flag for review" + }, + { + "sentinel": "LatestDeliveryAction", + "ah": "LatestDeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "LatestDeliveryLocation", + "ah": "LatestDeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "NetworkMessageId", + "ah": "NetworkMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelAction", + "ah": "OrgLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelPolicy", + "ah": "OrgLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientDomain", + "ah": "RecipientDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientEmailAddress", + "ah": "RecipientEmailAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientObjectId", + "ah": "RecipientObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ReportId", + "ah": "ReportId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderDisplayName", + "ah": "SenderDisplayName", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromAddress", + "ah": "SenderFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromDomain", + "ah": "SenderFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv4", + "ah": "SenderIPv4", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv6", + "ah": "SenderIPv6", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromAddress", + "ah": "SenderMailFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromDomain", + "ah": "SenderMailFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderObjectId", + "ah": "SenderObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Subject", + "ah": "Subject", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatClassification", + "ah": "ThreatClassification", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatNames", + "ah": "ThreatNames", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatTypes", + "ah": "ThreatTypes", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "TimeGenerated", + "ah": "TimeGenerated", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "Timestamp", + "ah": "Timestamp", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "To", + "ah": "To", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "UrlCount", + "ah": "UrlCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "UserLevelAction", + "ah": "UserLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "UserLevelPolicy", + "ah": "UserLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + } + ], + "extraInAh": [] + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/5/content/items/3/content/query", + "sourceSha256": "e35a12f2504594c80042fde446d6e57f0e2bc4fc01ab67ee5c580cfbbb8cc55e", + "targetSha256": "e35a12f2504594c80042fde446d6e57f0e2bc4fc01ab67ee5c580cfbbb8cc55e" + }, + { + "sourcePath": "/items/5/content/items/4/content/query", + "parameter": false, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "9ad60f3b5a2ffc57f40962c092561de44dc08eb8364e5dc0316534b44a1f6238" + }, + "conversion": { + "sourceId": "/items/5/content/items/4/content/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where \"{DeliveryAction}\" == \"All\" or DeliveryAction == \"{DeliveryAction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize DistinctMessages=dcount(InternetMessageId), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientEmailAddress\r\n| sort by DistinctMessages", + "resolvedTables": [ + "EmailEvents" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailEvents", + "ahTable": "EmailEvents", + "identical": false, + "verdict": "Hard", + "score": 0.98, + "columns": [ + { + "sentinel": "AdditionalFields", + "ah": "AdditionalFields", + "laType": "dynamic", + "ahType": "string", + "relation": "compatible" + }, + { + "sentinel": "AttachmentCount", + "ah": "AttachmentCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "AuthenticationDetails", + "ah": "AuthenticationDetails", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "BulkComplaintLevel", + "ah": "BulkComplaintLevel", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "Cc", + "ah": "Cc", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "ConfidenceLevel", + "ah": "ConfidenceLevel", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Connectors", + "ah": "Connectors", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Context", + "ah": "Context", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryAction", + "ah": "DeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryLocation", + "ah": "DeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DetectionMethods", + "ah": "DetectionMethods", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DistributionList", + "ah": "DistributionList", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailAction", + "ah": "EmailAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicy", + "ah": "EmailActionPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicyGuid", + "ah": "EmailActionPolicyGuid", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailClusterId", + "ah": "EmailClusterId", + "laType": "long", + "ahType": "long", + "relation": "exact" + }, + { + "sentinel": "EmailDirection", + "ah": "EmailDirection", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailLanguage", + "ah": "EmailLanguage", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailSize", + "ah": "EmailSize", + "laType": "int", + "ahType": "long", + "relation": "compatible" + }, + { + "sentinel": "ExchangeTransportRule", + "ah": "ExchangeTransportRule", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ForwardingInformation", + "ah": "ForwardingInformation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "InternetMessageId", + "ah": "InternetMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "IsFirstContact", + "ah": "IsFirstContact", + "laType": "bool", + "ahType": "bool", + "relation": "exact" + }, + { + "sentinel": "LastEventExecutionTime", + "laType": "datetime", + "ah": null, + "ahType": null, + "relation": "missing", + "suggestion": null, + "suggestionSource": null, + "note": "no direct AH equivalent; flag for review" + }, + { + "sentinel": "LatestDeliveryAction", + "ah": "LatestDeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "LatestDeliveryLocation", + "ah": "LatestDeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "NetworkMessageId", + "ah": "NetworkMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelAction", + "ah": "OrgLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelPolicy", + "ah": "OrgLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientDomain", + "ah": "RecipientDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientEmailAddress", + "ah": "RecipientEmailAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientObjectId", + "ah": "RecipientObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ReportId", + "ah": "ReportId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderDisplayName", + "ah": "SenderDisplayName", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromAddress", + "ah": "SenderFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromDomain", + "ah": "SenderFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv4", + "ah": "SenderIPv4", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv6", + "ah": "SenderIPv6", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromAddress", + "ah": "SenderMailFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromDomain", + "ah": "SenderMailFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderObjectId", + "ah": "SenderObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Subject", + "ah": "Subject", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatClassification", + "ah": "ThreatClassification", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatNames", + "ah": "ThreatNames", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatTypes", + "ah": "ThreatTypes", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "TimeGenerated", + "ah": "TimeGenerated", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "Timestamp", + "ah": "Timestamp", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "To", + "ah": "To", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "UrlCount", + "ah": "UrlCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "UserLevelAction", + "ah": "UserLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "UserLevelPolicy", + "ah": "UserLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + } + ], + "extraInAh": [] + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/5/content/items/4/content/query", + "sourceSha256": "9ad60f3b5a2ffc57f40962c092561de44dc08eb8364e5dc0316534b44a1f6238", + "targetSha256": "9ad60f3b5a2ffc57f40962c092561de44dc08eb8364e5dc0316534b44a1f6238" + }, + { + "sourcePath": "/items/5/content/items/5/content/query", + "parameter": false, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "5c729d067c07c67e8bb7704a87e5dfc5cbebb83bc1da0cd58bfec01dd895e10b" + }, + "conversion": { + "sourceId": "/items/5/content/items/5/content/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where \"{DeliveryAction}\" == \"All\" or DeliveryAction == \"{DeliveryAction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize DistinctMessages=dcount(InternetMessageId), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientDomain\r\n| sort by DistinctMessages desc", + "resolvedTables": [ + "EmailEvents" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailEvents", + "ahTable": "EmailEvents", + "identical": false, + "verdict": "Hard", + "score": 0.98, + "columns": [ + { + "sentinel": "AdditionalFields", + "ah": "AdditionalFields", + "laType": "dynamic", + "ahType": "string", + "relation": "compatible" + }, + { + "sentinel": "AttachmentCount", + "ah": "AttachmentCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "AuthenticationDetails", + "ah": "AuthenticationDetails", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "BulkComplaintLevel", + "ah": "BulkComplaintLevel", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "Cc", + "ah": "Cc", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "ConfidenceLevel", + "ah": "ConfidenceLevel", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Connectors", + "ah": "Connectors", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Context", + "ah": "Context", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryAction", + "ah": "DeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryLocation", + "ah": "DeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DetectionMethods", + "ah": "DetectionMethods", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DistributionList", + "ah": "DistributionList", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailAction", + "ah": "EmailAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicy", + "ah": "EmailActionPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicyGuid", + "ah": "EmailActionPolicyGuid", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailClusterId", + "ah": "EmailClusterId", + "laType": "long", + "ahType": "long", + "relation": "exact" + }, + { + "sentinel": "EmailDirection", + "ah": "EmailDirection", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailLanguage", + "ah": "EmailLanguage", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailSize", + "ah": "EmailSize", + "laType": "int", + "ahType": "long", + "relation": "compatible" + }, + { + "sentinel": "ExchangeTransportRule", + "ah": "ExchangeTransportRule", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ForwardingInformation", + "ah": "ForwardingInformation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "InternetMessageId", + "ah": "InternetMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "IsFirstContact", + "ah": "IsFirstContact", + "laType": "bool", + "ahType": "bool", + "relation": "exact" + }, + { + "sentinel": "LastEventExecutionTime", + "laType": "datetime", + "ah": null, + "ahType": null, + "relation": "missing", + "suggestion": null, + "suggestionSource": null, + "note": "no direct AH equivalent; flag for review" + }, + { + "sentinel": "LatestDeliveryAction", + "ah": "LatestDeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "LatestDeliveryLocation", + "ah": "LatestDeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "NetworkMessageId", + "ah": "NetworkMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelAction", + "ah": "OrgLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelPolicy", + "ah": "OrgLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientDomain", + "ah": "RecipientDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientEmailAddress", + "ah": "RecipientEmailAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientObjectId", + "ah": "RecipientObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ReportId", + "ah": "ReportId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderDisplayName", + "ah": "SenderDisplayName", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromAddress", + "ah": "SenderFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromDomain", + "ah": "SenderFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv4", + "ah": "SenderIPv4", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv6", + "ah": "SenderIPv6", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromAddress", + "ah": "SenderMailFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromDomain", + "ah": "SenderMailFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderObjectId", + "ah": "SenderObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Subject", + "ah": "Subject", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatClassification", + "ah": "ThreatClassification", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatNames", + "ah": "ThreatNames", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatTypes", + "ah": "ThreatTypes", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "TimeGenerated", + "ah": "TimeGenerated", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "Timestamp", + "ah": "Timestamp", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "To", + "ah": "To", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "UrlCount", + "ah": "UrlCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "UserLevelAction", + "ah": "UserLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "UserLevelPolicy", + "ah": "UserLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + } + ], + "extraInAh": [] + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/5/content/items/5/content/query", + "sourceSha256": "5c729d067c07c67e8bb7704a87e5dfc5cbebb83bc1da0cd58bfec01dd895e10b", + "targetSha256": "5c729d067c07c67e8bb7704a87e5dfc5cbebb83bc1da0cd58bfec01dd895e10b" + }, + { + "sourcePath": "/items/5/content/items/6/content/query", + "parameter": false, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "a776ed212051d494eb950e8eff9b94268f8f0ff9b1365edef92edbc2a8fd6f08" + }, + "conversion": { + "sourceId": "/items/5/content/items/6/content/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "let ids = array_concat(dynamic({NetworkMessageIdsSender}),dynamic({NetworkMessageIdsRecipient}),dynamic({NetworkMessageIdsDomain}));\r\nEmailEvents\r\n| where NetworkMessageId in (ids) or array_length(ids) == 0\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| where \"{Direction}\" == \"All\" or EmailDirection == \"{Direction}\"\r\n| where \"{DeliveryAction}\" == \"All\" or DeliveryAction == \"{DeliveryAction}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| project TimeGenerated, SenderMailFromAddress, RecipientEmailAddress, Subject, EmailDirection, EmailLanguage, DeliveryAction, ConfidenceLevel, AttachmentCount, UrlCount, NetworkMessageId", + "resolvedTables": [ + "EmailEvents" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailEvents", + "ahTable": "EmailEvents", + "identical": false, + "verdict": "Hard", + "score": 0.98, + "columns": [ + { + "sentinel": "AdditionalFields", + "ah": "AdditionalFields", + "laType": "dynamic", + "ahType": "string", + "relation": "compatible" + }, + { + "sentinel": "AttachmentCount", + "ah": "AttachmentCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "AuthenticationDetails", + "ah": "AuthenticationDetails", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "BulkComplaintLevel", + "ah": "BulkComplaintLevel", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "Cc", + "ah": "Cc", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "ConfidenceLevel", + "ah": "ConfidenceLevel", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Connectors", + "ah": "Connectors", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Context", + "ah": "Context", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryAction", + "ah": "DeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryLocation", + "ah": "DeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DetectionMethods", + "ah": "DetectionMethods", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DistributionList", + "ah": "DistributionList", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailAction", + "ah": "EmailAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicy", + "ah": "EmailActionPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicyGuid", + "ah": "EmailActionPolicyGuid", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailClusterId", + "ah": "EmailClusterId", + "laType": "long", + "ahType": "long", + "relation": "exact" + }, + { + "sentinel": "EmailDirection", + "ah": "EmailDirection", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailLanguage", + "ah": "EmailLanguage", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailSize", + "ah": "EmailSize", + "laType": "int", + "ahType": "long", + "relation": "compatible" + }, + { + "sentinel": "ExchangeTransportRule", + "ah": "ExchangeTransportRule", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ForwardingInformation", + "ah": "ForwardingInformation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "InternetMessageId", + "ah": "InternetMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "IsFirstContact", + "ah": "IsFirstContact", + "laType": "bool", + "ahType": "bool", + "relation": "exact" + }, + { + "sentinel": "LastEventExecutionTime", + "laType": "datetime", + "ah": null, + "ahType": null, + "relation": "missing", + "suggestion": null, + "suggestionSource": null, + "note": "no direct AH equivalent; flag for review" + }, + { + "sentinel": "LatestDeliveryAction", + "ah": "LatestDeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "LatestDeliveryLocation", + "ah": "LatestDeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "NetworkMessageId", + "ah": "NetworkMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelAction", + "ah": "OrgLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelPolicy", + "ah": "OrgLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientDomain", + "ah": "RecipientDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientEmailAddress", + "ah": "RecipientEmailAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientObjectId", + "ah": "RecipientObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ReportId", + "ah": "ReportId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderDisplayName", + "ah": "SenderDisplayName", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromAddress", + "ah": "SenderFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromDomain", + "ah": "SenderFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv4", + "ah": "SenderIPv4", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv6", + "ah": "SenderIPv6", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromAddress", + "ah": "SenderMailFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromDomain", + "ah": "SenderMailFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderObjectId", + "ah": "SenderObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Subject", + "ah": "Subject", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatClassification", + "ah": "ThreatClassification", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatNames", + "ah": "ThreatNames", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatTypes", + "ah": "ThreatTypes", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "TimeGenerated", + "ah": "TimeGenerated", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "Timestamp", + "ah": "Timestamp", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "To", + "ah": "To", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "UrlCount", + "ah": "UrlCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "UserLevelAction", + "ah": "UserLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "UserLevelPolicy", + "ah": "UserLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + } + ], + "extraInAh": [] + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/5/content/items/6/content/query", + "sourceSha256": "a776ed212051d494eb950e8eff9b94268f8f0ff9b1365edef92edbc2a8fd6f08", + "targetSha256": "a776ed212051d494eb950e8eff9b94268f8f0ff9b1365edef92edbc2a8fd6f08" + }, + { + "sourcePath": "/items/5/content/items/7/content/query", + "parameter": false, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "fe93bf34b6407356389cc1a3c35ec41da425fb9a906d4dcdc10c2b116b35fe2c" + }, + "conversion": { + "sourceId": "/items/5/content/items/7/content/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "EmailAttachmentInfo\r\n| where NetworkMessageId == \"{NetworkMessageId}\"\r\n| project FileName, FileType, SHA256, ThreatTypes, ThreatNames, DetectionMethods", + "resolvedTables": [ + "EmailAttachmentInfo" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailAttachmentInfo", + "ahTable": "EmailAttachmentInfo", + "identical": true, + "verdict": "Easy", + "score": 1.0, + "columnCount": 17, + "note": "schema identical; no column changes" + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/5/content/items/7/content/query", + "sourceSha256": "fe93bf34b6407356389cc1a3c35ec41da425fb9a906d4dcdc10c2b116b35fe2c", + "targetSha256": "fe93bf34b6407356389cc1a3c35ec41da425fb9a906d4dcdc10c2b116b35fe2c" + }, + { + "sourcePath": "/items/5/content/items/8/content/query", + "parameter": false, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "fe68a1c4a3598e9c371edcfd9e64ef444afd0e47ac4f7b6da76d872fd6d2fdcb" + }, + "conversion": { + "sourceId": "/items/5/content/items/8/content/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "EmailUrlInfo\r\n| where NetworkMessageId == \"{NetworkMessageId}\"\r\n| project Url, UrlDomain", + "resolvedTables": [ + "EmailUrlInfo" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailUrlInfo", + "ahTable": "EmailUrlInfo", + "identical": true, + "verdict": "Easy", + "score": 1.0, + "columnCount": 7, + "note": "schema identical; no column changes" + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/5/content/items/8/content/query", + "sourceSha256": "fe68a1c4a3598e9c371edcfd9e64ef444afd0e47ac4f7b6da76d872fd6d2fdcb", + "targetSha256": "fe68a1c4a3598e9c371edcfd9e64ef444afd0e47ac4f7b6da76d872fd6d2fdcb" + }, + { + "sourcePath": "/items/6/content/items/0/content/query", + "parameter": false, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "6478ab01c6c73cabdfa529927c21e777d01a7961dc3b2adab26821c68abd7fc7" + }, + "conversion": { + "sourceId": "/items/6/content/items/0/content/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalAttachments=sum(AttachmentCount), DistinctRecipients=dcount(RecipientEmailAddress), DistinctRecipientDomains=dcount(RecipientDomain), NetworkMessageIds=make_set(NetworkMessageId) by SenderMailFromAddress\r\n| where TotalAttachments > 0\r\n| sort by TotalAttachments desc", + "resolvedTables": [ + "EmailEvents" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailEvents", + "ahTable": "EmailEvents", + "identical": false, + "verdict": "Hard", + "score": 0.98, + "columns": [ + { + "sentinel": "AdditionalFields", + "ah": "AdditionalFields", + "laType": "dynamic", + "ahType": "string", + "relation": "compatible" + }, + { + "sentinel": "AttachmentCount", + "ah": "AttachmentCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "AuthenticationDetails", + "ah": "AuthenticationDetails", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "BulkComplaintLevel", + "ah": "BulkComplaintLevel", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "Cc", + "ah": "Cc", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "ConfidenceLevel", + "ah": "ConfidenceLevel", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Connectors", + "ah": "Connectors", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Context", + "ah": "Context", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryAction", + "ah": "DeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryLocation", + "ah": "DeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DetectionMethods", + "ah": "DetectionMethods", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DistributionList", + "ah": "DistributionList", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailAction", + "ah": "EmailAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicy", + "ah": "EmailActionPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicyGuid", + "ah": "EmailActionPolicyGuid", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailClusterId", + "ah": "EmailClusterId", + "laType": "long", + "ahType": "long", + "relation": "exact" + }, + { + "sentinel": "EmailDirection", + "ah": "EmailDirection", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailLanguage", + "ah": "EmailLanguage", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailSize", + "ah": "EmailSize", + "laType": "int", + "ahType": "long", + "relation": "compatible" + }, + { + "sentinel": "ExchangeTransportRule", + "ah": "ExchangeTransportRule", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ForwardingInformation", + "ah": "ForwardingInformation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "InternetMessageId", + "ah": "InternetMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "IsFirstContact", + "ah": "IsFirstContact", + "laType": "bool", + "ahType": "bool", + "relation": "exact" + }, + { + "sentinel": "LastEventExecutionTime", + "laType": "datetime", + "ah": null, + "ahType": null, + "relation": "missing", + "suggestion": null, + "suggestionSource": null, + "note": "no direct AH equivalent; flag for review" + }, + { + "sentinel": "LatestDeliveryAction", + "ah": "LatestDeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "LatestDeliveryLocation", + "ah": "LatestDeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "NetworkMessageId", + "ah": "NetworkMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelAction", + "ah": "OrgLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelPolicy", + "ah": "OrgLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientDomain", + "ah": "RecipientDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientEmailAddress", + "ah": "RecipientEmailAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientObjectId", + "ah": "RecipientObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ReportId", + "ah": "ReportId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderDisplayName", + "ah": "SenderDisplayName", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromAddress", + "ah": "SenderFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromDomain", + "ah": "SenderFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv4", + "ah": "SenderIPv4", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv6", + "ah": "SenderIPv6", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromAddress", + "ah": "SenderMailFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromDomain", + "ah": "SenderMailFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderObjectId", + "ah": "SenderObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Subject", + "ah": "Subject", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatClassification", + "ah": "ThreatClassification", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatNames", + "ah": "ThreatNames", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatTypes", + "ah": "ThreatTypes", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "TimeGenerated", + "ah": "TimeGenerated", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "Timestamp", + "ah": "Timestamp", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "To", + "ah": "To", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "UrlCount", + "ah": "UrlCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "UserLevelAction", + "ah": "UserLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "UserLevelPolicy", + "ah": "UserLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + } + ], + "extraInAh": [] + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/6/content/items/0/content/query", + "sourceSha256": "6478ab01c6c73cabdfa529927c21e777d01a7961dc3b2adab26821c68abd7fc7", + "targetSha256": "6478ab01c6c73cabdfa529927c21e777d01a7961dc3b2adab26821c68abd7fc7" + }, + { + "sourcePath": "/items/6/content/items/1/content/query", + "parameter": false, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "66119dac7b15bc65a3bf460977a6c2fa478018bf109f40b3fb543ba70e5a4067" + }, + "conversion": { + "sourceId": "/items/6/content/items/1/content/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalAttachments=sum(AttachmentCount), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientEmailAddress\r\n| where TotalAttachments > 0\r\n| sort by TotalAttachments desc", + "resolvedTables": [ + "EmailEvents" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailEvents", + "ahTable": "EmailEvents", + "identical": false, + "verdict": "Hard", + "score": 0.98, + "columns": [ + { + "sentinel": "AdditionalFields", + "ah": "AdditionalFields", + "laType": "dynamic", + "ahType": "string", + "relation": "compatible" + }, + { + "sentinel": "AttachmentCount", + "ah": "AttachmentCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "AuthenticationDetails", + "ah": "AuthenticationDetails", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "BulkComplaintLevel", + "ah": "BulkComplaintLevel", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "Cc", + "ah": "Cc", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "ConfidenceLevel", + "ah": "ConfidenceLevel", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Connectors", + "ah": "Connectors", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Context", + "ah": "Context", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryAction", + "ah": "DeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryLocation", + "ah": "DeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DetectionMethods", + "ah": "DetectionMethods", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DistributionList", + "ah": "DistributionList", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailAction", + "ah": "EmailAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicy", + "ah": "EmailActionPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicyGuid", + "ah": "EmailActionPolicyGuid", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailClusterId", + "ah": "EmailClusterId", + "laType": "long", + "ahType": "long", + "relation": "exact" + }, + { + "sentinel": "EmailDirection", + "ah": "EmailDirection", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailLanguage", + "ah": "EmailLanguage", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailSize", + "ah": "EmailSize", + "laType": "int", + "ahType": "long", + "relation": "compatible" + }, + { + "sentinel": "ExchangeTransportRule", + "ah": "ExchangeTransportRule", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ForwardingInformation", + "ah": "ForwardingInformation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "InternetMessageId", + "ah": "InternetMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "IsFirstContact", + "ah": "IsFirstContact", + "laType": "bool", + "ahType": "bool", + "relation": "exact" + }, + { + "sentinel": "LastEventExecutionTime", + "laType": "datetime", + "ah": null, + "ahType": null, + "relation": "missing", + "suggestion": null, + "suggestionSource": null, + "note": "no direct AH equivalent; flag for review" + }, + { + "sentinel": "LatestDeliveryAction", + "ah": "LatestDeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "LatestDeliveryLocation", + "ah": "LatestDeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "NetworkMessageId", + "ah": "NetworkMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelAction", + "ah": "OrgLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelPolicy", + "ah": "OrgLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientDomain", + "ah": "RecipientDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientEmailAddress", + "ah": "RecipientEmailAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientObjectId", + "ah": "RecipientObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ReportId", + "ah": "ReportId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderDisplayName", + "ah": "SenderDisplayName", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromAddress", + "ah": "SenderFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromDomain", + "ah": "SenderFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv4", + "ah": "SenderIPv4", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv6", + "ah": "SenderIPv6", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromAddress", + "ah": "SenderMailFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromDomain", + "ah": "SenderMailFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderObjectId", + "ah": "SenderObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Subject", + "ah": "Subject", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatClassification", + "ah": "ThreatClassification", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatNames", + "ah": "ThreatNames", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatTypes", + "ah": "ThreatTypes", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "TimeGenerated", + "ah": "TimeGenerated", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "Timestamp", + "ah": "Timestamp", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "To", + "ah": "To", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "UrlCount", + "ah": "UrlCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "UserLevelAction", + "ah": "UserLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "UserLevelPolicy", + "ah": "UserLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + } + ], + "extraInAh": [] + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/6/content/items/1/content/query", + "sourceSha256": "66119dac7b15bc65a3bf460977a6c2fa478018bf109f40b3fb543ba70e5a4067", + "targetSha256": "66119dac7b15bc65a3bf460977a6c2fa478018bf109f40b3fb543ba70e5a4067" + }, + { + "sourcePath": "/items/6/content/items/2/content/query", + "parameter": false, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "199bd5442911b359169912f8ab662b6f5c7715c11496cdf16a747af9639be5c8" + }, + "conversion": { + "sourceId": "/items/6/content/items/2/content/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalAttachments=sum(AttachmentCount), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientDomain\r\n| where TotalAttachments > 0\r\n| sort by TotalAttachments desc", + "resolvedTables": [ + "EmailEvents" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailEvents", + "ahTable": "EmailEvents", + "identical": false, + "verdict": "Hard", + "score": 0.98, + "columns": [ + { + "sentinel": "AdditionalFields", + "ah": "AdditionalFields", + "laType": "dynamic", + "ahType": "string", + "relation": "compatible" + }, + { + "sentinel": "AttachmentCount", + "ah": "AttachmentCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "AuthenticationDetails", + "ah": "AuthenticationDetails", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "BulkComplaintLevel", + "ah": "BulkComplaintLevel", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "Cc", + "ah": "Cc", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "ConfidenceLevel", + "ah": "ConfidenceLevel", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Connectors", + "ah": "Connectors", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Context", + "ah": "Context", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryAction", + "ah": "DeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryLocation", + "ah": "DeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DetectionMethods", + "ah": "DetectionMethods", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DistributionList", + "ah": "DistributionList", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailAction", + "ah": "EmailAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicy", + "ah": "EmailActionPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicyGuid", + "ah": "EmailActionPolicyGuid", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailClusterId", + "ah": "EmailClusterId", + "laType": "long", + "ahType": "long", + "relation": "exact" + }, + { + "sentinel": "EmailDirection", + "ah": "EmailDirection", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailLanguage", + "ah": "EmailLanguage", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailSize", + "ah": "EmailSize", + "laType": "int", + "ahType": "long", + "relation": "compatible" + }, + { + "sentinel": "ExchangeTransportRule", + "ah": "ExchangeTransportRule", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ForwardingInformation", + "ah": "ForwardingInformation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "InternetMessageId", + "ah": "InternetMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "IsFirstContact", + "ah": "IsFirstContact", + "laType": "bool", + "ahType": "bool", + "relation": "exact" + }, + { + "sentinel": "LastEventExecutionTime", + "laType": "datetime", + "ah": null, + "ahType": null, + "relation": "missing", + "suggestion": null, + "suggestionSource": null, + "note": "no direct AH equivalent; flag for review" + }, + { + "sentinel": "LatestDeliveryAction", + "ah": "LatestDeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "LatestDeliveryLocation", + "ah": "LatestDeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "NetworkMessageId", + "ah": "NetworkMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelAction", + "ah": "OrgLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelPolicy", + "ah": "OrgLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientDomain", + "ah": "RecipientDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientEmailAddress", + "ah": "RecipientEmailAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientObjectId", + "ah": "RecipientObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ReportId", + "ah": "ReportId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderDisplayName", + "ah": "SenderDisplayName", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromAddress", + "ah": "SenderFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromDomain", + "ah": "SenderFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv4", + "ah": "SenderIPv4", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv6", + "ah": "SenderIPv6", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromAddress", + "ah": "SenderMailFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromDomain", + "ah": "SenderMailFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderObjectId", + "ah": "SenderObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Subject", + "ah": "Subject", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatClassification", + "ah": "ThreatClassification", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatNames", + "ah": "ThreatNames", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatTypes", + "ah": "ThreatTypes", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "TimeGenerated", + "ah": "TimeGenerated", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "Timestamp", + "ah": "Timestamp", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "To", + "ah": "To", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "UrlCount", + "ah": "UrlCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "UserLevelAction", + "ah": "UserLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "UserLevelPolicy", + "ah": "UserLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + } + ], + "extraInAh": [] + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/6/content/items/2/content/query", + "sourceSha256": "199bd5442911b359169912f8ab662b6f5c7715c11496cdf16a747af9639be5c8", + "targetSha256": "199bd5442911b359169912f8ab662b6f5c7715c11496cdf16a747af9639be5c8" + }, + { + "sourcePath": "/items/6/content/items/3/content/parameters/1/query", + "parameter": true, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "3b0adf5e8ce3dfd99b7ccafb5d4f5d39625eceb21ce914ec40709dc880ce137a" + }, + "conversion": { + "sourceId": "/items/6/content/items/3/content/parameters/1/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "EmailAttachmentInfo\r\n| summarize AttachmentCount=count() by FileType\r\n| sort by AttachmentCount desc\r\n| project FileType, strcat(FileType, ' - ', AttachmentCount, ' attachments')", + "resolvedTables": [ + "EmailAttachmentInfo" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailAttachmentInfo", + "ahTable": "EmailAttachmentInfo", + "identical": true, + "verdict": "Easy", + "score": 1.0, + "columnCount": 17, + "note": "schema identical; no column changes" + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/6/content/items/3/content/parameters/1/query", + "sourceSha256": "3b0adf5e8ce3dfd99b7ccafb5d4f5d39625eceb21ce914ec40709dc880ce137a", + "targetSha256": "3b0adf5e8ce3dfd99b7ccafb5d4f5d39625eceb21ce914ec40709dc880ce137a" + }, + { + "sourcePath": "/items/6/content/items/4/content/query", + "parameter": false, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "07a7080807951baaa81964b822364a92ba9c760922948e1ff7350e6f5dae1a92" + }, + "conversion": { + "sourceId": "/items/6/content/items/4/content/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "let ids = array_concat(dynamic({NetworkMessageIdsSender}),dynamic({NetworkMessageIdsRecipient}),dynamic({NetworkMessageIdsDomain}));\r\nEmailAttachmentInfo\r\n| where NetworkMessageId in (ids) or array_length(ids) == 0\r\n| where FileName contains \"{AttachmentName}\"\r\n| where \"*\" in ({AttachmentType}) or FileType in ({AttachmentType})\r\n| summarize UniqueEmailsWithThisAttachment=dcount(NetworkMessageId), NetworkMessageIdWithFile=make_set(NetworkMessageId) by FileName, FileType, SHA256", + "resolvedTables": [ + "EmailAttachmentInfo" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailAttachmentInfo", + "ahTable": "EmailAttachmentInfo", + "identical": true, + "verdict": "Easy", + "score": 1.0, + "columnCount": 17, + "note": "schema identical; no column changes" + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/6/content/items/4/content/query", + "sourceSha256": "07a7080807951baaa81964b822364a92ba9c760922948e1ff7350e6f5dae1a92", + "targetSha256": "07a7080807951baaa81964b822364a92ba9c760922948e1ff7350e6f5dae1a92" + }, + { + "sourcePath": "/items/6/content/items/5/content/query", + "parameter": false, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "644af21a178c327b6a22eb97f318c22c1c1d16ee074f12585c12de467f873f17" + }, + "conversion": { + "sourceId": "/items/6/content/items/5/content/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "let ids = dynamic({NetworkMessageIdWithFile});\r\nEmailAttachmentInfo\r\n| where NetworkMessageId in (ids)\r\n| distinct NetworkMessageId\r\n| join kind=leftouter (EmailEvents) on NetworkMessageId\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| project TimeGenerated, SenderMailFromAddress, RecipientEmailAddress, Subject, EmailDirection, EmailLanguage, DeliveryAction, ConfidenceLevel, AttachmentCount, UrlCount, NetworkMessageId", + "resolvedTables": [ + "EmailAttachmentInfo", + "EmailEvents" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailAttachmentInfo", + "ahTable": "EmailAttachmentInfo", + "identical": true, + "verdict": "Easy", + "score": 1.0, + "columnCount": 17, + "note": "schema identical; no column changes" + }, + { + "sentinelTable": "EmailEvents", + "ahTable": "EmailEvents", + "identical": false, + "verdict": "Hard", + "score": 0.98, + "columns": [ + { + "sentinel": "AdditionalFields", + "ah": "AdditionalFields", + "laType": "dynamic", + "ahType": "string", + "relation": "compatible" + }, + { + "sentinel": "AttachmentCount", + "ah": "AttachmentCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "AuthenticationDetails", + "ah": "AuthenticationDetails", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "BulkComplaintLevel", + "ah": "BulkComplaintLevel", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "Cc", + "ah": "Cc", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "ConfidenceLevel", + "ah": "ConfidenceLevel", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Connectors", + "ah": "Connectors", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Context", + "ah": "Context", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryAction", + "ah": "DeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryLocation", + "ah": "DeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DetectionMethods", + "ah": "DetectionMethods", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DistributionList", + "ah": "DistributionList", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailAction", + "ah": "EmailAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicy", + "ah": "EmailActionPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicyGuid", + "ah": "EmailActionPolicyGuid", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailClusterId", + "ah": "EmailClusterId", + "laType": "long", + "ahType": "long", + "relation": "exact" + }, + { + "sentinel": "EmailDirection", + "ah": "EmailDirection", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailLanguage", + "ah": "EmailLanguage", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailSize", + "ah": "EmailSize", + "laType": "int", + "ahType": "long", + "relation": "compatible" + }, + { + "sentinel": "ExchangeTransportRule", + "ah": "ExchangeTransportRule", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ForwardingInformation", + "ah": "ForwardingInformation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "InternetMessageId", + "ah": "InternetMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "IsFirstContact", + "ah": "IsFirstContact", + "laType": "bool", + "ahType": "bool", + "relation": "exact" + }, + { + "sentinel": "LastEventExecutionTime", + "laType": "datetime", + "ah": null, + "ahType": null, + "relation": "missing", + "suggestion": null, + "suggestionSource": null, + "note": "no direct AH equivalent; flag for review" + }, + { + "sentinel": "LatestDeliveryAction", + "ah": "LatestDeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "LatestDeliveryLocation", + "ah": "LatestDeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "NetworkMessageId", + "ah": "NetworkMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelAction", + "ah": "OrgLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelPolicy", + "ah": "OrgLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientDomain", + "ah": "RecipientDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientEmailAddress", + "ah": "RecipientEmailAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientObjectId", + "ah": "RecipientObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ReportId", + "ah": "ReportId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderDisplayName", + "ah": "SenderDisplayName", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromAddress", + "ah": "SenderFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromDomain", + "ah": "SenderFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv4", + "ah": "SenderIPv4", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv6", + "ah": "SenderIPv6", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromAddress", + "ah": "SenderMailFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromDomain", + "ah": "SenderMailFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderObjectId", + "ah": "SenderObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Subject", + "ah": "Subject", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatClassification", + "ah": "ThreatClassification", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatNames", + "ah": "ThreatNames", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatTypes", + "ah": "ThreatTypes", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "TimeGenerated", + "ah": "TimeGenerated", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "Timestamp", + "ah": "Timestamp", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "To", + "ah": "To", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "UrlCount", + "ah": "UrlCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "UserLevelAction", + "ah": "UserLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "UserLevelPolicy", + "ah": "UserLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + } + ], + "extraInAh": [] + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/6/content/items/5/content/query", + "sourceSha256": "644af21a178c327b6a22eb97f318c22c1c1d16ee074f12585c12de467f873f17", + "targetSha256": "644af21a178c327b6a22eb97f318c22c1c1d16ee074f12585c12de467f873f17" + }, + { + "sourcePath": "/items/7/content/items/0/content/query", + "parameter": false, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "1798f6d6a52e4cd7ae1eaf2388f4dd7362c9389c98a904cd0b22e896a3b7806e" + }, + "conversion": { + "sourceId": "/items/7/content/items/0/content/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalUrls=sum(UrlCount), DistinctRecipients=dcount(RecipientEmailAddress), DistinctRecipientDomains=dcount(RecipientDomain), NetworkMessageIds=make_set(NetworkMessageId) by SenderMailFromAddress\r\n| where TotalUrls > 0\r\n| sort by TotalUrls desc", + "resolvedTables": [ + "EmailEvents" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailEvents", + "ahTable": "EmailEvents", + "identical": false, + "verdict": "Hard", + "score": 0.98, + "columns": [ + { + "sentinel": "AdditionalFields", + "ah": "AdditionalFields", + "laType": "dynamic", + "ahType": "string", + "relation": "compatible" + }, + { + "sentinel": "AttachmentCount", + "ah": "AttachmentCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "AuthenticationDetails", + "ah": "AuthenticationDetails", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "BulkComplaintLevel", + "ah": "BulkComplaintLevel", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "Cc", + "ah": "Cc", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "ConfidenceLevel", + "ah": "ConfidenceLevel", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Connectors", + "ah": "Connectors", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Context", + "ah": "Context", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryAction", + "ah": "DeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryLocation", + "ah": "DeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DetectionMethods", + "ah": "DetectionMethods", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DistributionList", + "ah": "DistributionList", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailAction", + "ah": "EmailAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicy", + "ah": "EmailActionPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicyGuid", + "ah": "EmailActionPolicyGuid", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailClusterId", + "ah": "EmailClusterId", + "laType": "long", + "ahType": "long", + "relation": "exact" + }, + { + "sentinel": "EmailDirection", + "ah": "EmailDirection", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailLanguage", + "ah": "EmailLanguage", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailSize", + "ah": "EmailSize", + "laType": "int", + "ahType": "long", + "relation": "compatible" + }, + { + "sentinel": "ExchangeTransportRule", + "ah": "ExchangeTransportRule", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ForwardingInformation", + "ah": "ForwardingInformation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "InternetMessageId", + "ah": "InternetMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "IsFirstContact", + "ah": "IsFirstContact", + "laType": "bool", + "ahType": "bool", + "relation": "exact" + }, + { + "sentinel": "LastEventExecutionTime", + "laType": "datetime", + "ah": null, + "ahType": null, + "relation": "missing", + "suggestion": null, + "suggestionSource": null, + "note": "no direct AH equivalent; flag for review" + }, + { + "sentinel": "LatestDeliveryAction", + "ah": "LatestDeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "LatestDeliveryLocation", + "ah": "LatestDeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "NetworkMessageId", + "ah": "NetworkMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelAction", + "ah": "OrgLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelPolicy", + "ah": "OrgLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientDomain", + "ah": "RecipientDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientEmailAddress", + "ah": "RecipientEmailAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientObjectId", + "ah": "RecipientObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ReportId", + "ah": "ReportId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderDisplayName", + "ah": "SenderDisplayName", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromAddress", + "ah": "SenderFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromDomain", + "ah": "SenderFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv4", + "ah": "SenderIPv4", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv6", + "ah": "SenderIPv6", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromAddress", + "ah": "SenderMailFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromDomain", + "ah": "SenderMailFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderObjectId", + "ah": "SenderObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Subject", + "ah": "Subject", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatClassification", + "ah": "ThreatClassification", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatNames", + "ah": "ThreatNames", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatTypes", + "ah": "ThreatTypes", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "TimeGenerated", + "ah": "TimeGenerated", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "Timestamp", + "ah": "Timestamp", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "To", + "ah": "To", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "UrlCount", + "ah": "UrlCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "UserLevelAction", + "ah": "UserLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "UserLevelPolicy", + "ah": "UserLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + } + ], + "extraInAh": [] + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/7/content/items/0/content/query", + "sourceSha256": "1798f6d6a52e4cd7ae1eaf2388f4dd7362c9389c98a904cd0b22e896a3b7806e", + "targetSha256": "1798f6d6a52e4cd7ae1eaf2388f4dd7362c9389c98a904cd0b22e896a3b7806e" + }, + { + "sourcePath": "/items/7/content/items/1/content/query", + "parameter": false, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "5d15d2cfc9a904b328f1e125aee8a43be22a743880f6639239601fa9d3ad3cdd" + }, + "conversion": { + "sourceId": "/items/7/content/items/1/content/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalUrls=sum(UrlCount), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientEmailAddress\r\n| where TotalUrls > 0\r\n| sort by TotalUrls desc", + "resolvedTables": [ + "EmailEvents" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailEvents", + "ahTable": "EmailEvents", + "identical": false, + "verdict": "Hard", + "score": 0.98, + "columns": [ + { + "sentinel": "AdditionalFields", + "ah": "AdditionalFields", + "laType": "dynamic", + "ahType": "string", + "relation": "compatible" + }, + { + "sentinel": "AttachmentCount", + "ah": "AttachmentCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "AuthenticationDetails", + "ah": "AuthenticationDetails", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "BulkComplaintLevel", + "ah": "BulkComplaintLevel", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "Cc", + "ah": "Cc", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "ConfidenceLevel", + "ah": "ConfidenceLevel", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Connectors", + "ah": "Connectors", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Context", + "ah": "Context", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryAction", + "ah": "DeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryLocation", + "ah": "DeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DetectionMethods", + "ah": "DetectionMethods", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DistributionList", + "ah": "DistributionList", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailAction", + "ah": "EmailAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicy", + "ah": "EmailActionPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicyGuid", + "ah": "EmailActionPolicyGuid", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailClusterId", + "ah": "EmailClusterId", + "laType": "long", + "ahType": "long", + "relation": "exact" + }, + { + "sentinel": "EmailDirection", + "ah": "EmailDirection", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailLanguage", + "ah": "EmailLanguage", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailSize", + "ah": "EmailSize", + "laType": "int", + "ahType": "long", + "relation": "compatible" + }, + { + "sentinel": "ExchangeTransportRule", + "ah": "ExchangeTransportRule", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ForwardingInformation", + "ah": "ForwardingInformation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "InternetMessageId", + "ah": "InternetMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "IsFirstContact", + "ah": "IsFirstContact", + "laType": "bool", + "ahType": "bool", + "relation": "exact" + }, + { + "sentinel": "LastEventExecutionTime", + "laType": "datetime", + "ah": null, + "ahType": null, + "relation": "missing", + "suggestion": null, + "suggestionSource": null, + "note": "no direct AH equivalent; flag for review" + }, + { + "sentinel": "LatestDeliveryAction", + "ah": "LatestDeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "LatestDeliveryLocation", + "ah": "LatestDeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "NetworkMessageId", + "ah": "NetworkMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelAction", + "ah": "OrgLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelPolicy", + "ah": "OrgLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientDomain", + "ah": "RecipientDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientEmailAddress", + "ah": "RecipientEmailAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientObjectId", + "ah": "RecipientObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ReportId", + "ah": "ReportId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderDisplayName", + "ah": "SenderDisplayName", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromAddress", + "ah": "SenderFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromDomain", + "ah": "SenderFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv4", + "ah": "SenderIPv4", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv6", + "ah": "SenderIPv6", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromAddress", + "ah": "SenderMailFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromDomain", + "ah": "SenderMailFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderObjectId", + "ah": "SenderObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Subject", + "ah": "Subject", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatClassification", + "ah": "ThreatClassification", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatNames", + "ah": "ThreatNames", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatTypes", + "ah": "ThreatTypes", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "TimeGenerated", + "ah": "TimeGenerated", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "Timestamp", + "ah": "Timestamp", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "To", + "ah": "To", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "UrlCount", + "ah": "UrlCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "UserLevelAction", + "ah": "UserLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "UserLevelPolicy", + "ah": "UserLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + } + ], + "extraInAh": [] + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/7/content/items/1/content/query", + "sourceSha256": "5d15d2cfc9a904b328f1e125aee8a43be22a743880f6639239601fa9d3ad3cdd", + "targetSha256": "5d15d2cfc9a904b328f1e125aee8a43be22a743880f6639239601fa9d3ad3cdd" + }, + { + "sourcePath": "/items/7/content/items/2/content/query", + "parameter": false, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "053552593226491eb95fad35412acb6c8ad49eda9011d3a596d293286f64c2ce" + }, + "conversion": { + "sourceId": "/items/7/content/items/2/content/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "EmailEvents\r\n| where EmailDirection in ({EmailDirection})\r\n| where AttachmentCount >= {MinimumAttachmentCount} and UrlCount >= {MinimumURLCount}\r\n| where isempty(\"{Sender}\") or SenderMailFromAddress =~ \"{Sender}\"\r\n| where \"{Sender2}\" == \"All\" or SenderMailFromAddress =~ \"{Sender2}\"\r\n| where isempty(\"{Recipient}\") or RecipientEmailAddress =~ \"{Recipient}\"\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| where \"*\" in ({RecipientDomain}) or RecipientDomain in ({RecipientDomain})\r\n| where \"*\" in ({SenderDomain}) or SenderMailFromDomain in ({SenderDomain})\r\n| where isempty(\"{Subject}\") or Subject contains \"{Subject}\"\r\n| summarize TotalUrls=sum(UrlCount), DistinctSenders=dcount(SenderMailFromAddress), NetworkMessageIds=make_set(NetworkMessageId) by RecipientDomain\r\n| where TotalUrls > 0\r\n| sort by TotalUrls desc", + "resolvedTables": [ + "EmailEvents" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailEvents", + "ahTable": "EmailEvents", + "identical": false, + "verdict": "Hard", + "score": 0.98, + "columns": [ + { + "sentinel": "AdditionalFields", + "ah": "AdditionalFields", + "laType": "dynamic", + "ahType": "string", + "relation": "compatible" + }, + { + "sentinel": "AttachmentCount", + "ah": "AttachmentCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "AuthenticationDetails", + "ah": "AuthenticationDetails", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "BulkComplaintLevel", + "ah": "BulkComplaintLevel", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "Cc", + "ah": "Cc", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "ConfidenceLevel", + "ah": "ConfidenceLevel", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Connectors", + "ah": "Connectors", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Context", + "ah": "Context", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryAction", + "ah": "DeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryLocation", + "ah": "DeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DetectionMethods", + "ah": "DetectionMethods", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DistributionList", + "ah": "DistributionList", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailAction", + "ah": "EmailAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicy", + "ah": "EmailActionPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicyGuid", + "ah": "EmailActionPolicyGuid", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailClusterId", + "ah": "EmailClusterId", + "laType": "long", + "ahType": "long", + "relation": "exact" + }, + { + "sentinel": "EmailDirection", + "ah": "EmailDirection", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailLanguage", + "ah": "EmailLanguage", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailSize", + "ah": "EmailSize", + "laType": "int", + "ahType": "long", + "relation": "compatible" + }, + { + "sentinel": "ExchangeTransportRule", + "ah": "ExchangeTransportRule", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ForwardingInformation", + "ah": "ForwardingInformation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "InternetMessageId", + "ah": "InternetMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "IsFirstContact", + "ah": "IsFirstContact", + "laType": "bool", + "ahType": "bool", + "relation": "exact" + }, + { + "sentinel": "LastEventExecutionTime", + "laType": "datetime", + "ah": null, + "ahType": null, + "relation": "missing", + "suggestion": null, + "suggestionSource": null, + "note": "no direct AH equivalent; flag for review" + }, + { + "sentinel": "LatestDeliveryAction", + "ah": "LatestDeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "LatestDeliveryLocation", + "ah": "LatestDeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "NetworkMessageId", + "ah": "NetworkMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelAction", + "ah": "OrgLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelPolicy", + "ah": "OrgLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientDomain", + "ah": "RecipientDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientEmailAddress", + "ah": "RecipientEmailAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientObjectId", + "ah": "RecipientObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ReportId", + "ah": "ReportId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderDisplayName", + "ah": "SenderDisplayName", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromAddress", + "ah": "SenderFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromDomain", + "ah": "SenderFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv4", + "ah": "SenderIPv4", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv6", + "ah": "SenderIPv6", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromAddress", + "ah": "SenderMailFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromDomain", + "ah": "SenderMailFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderObjectId", + "ah": "SenderObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Subject", + "ah": "Subject", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatClassification", + "ah": "ThreatClassification", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatNames", + "ah": "ThreatNames", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatTypes", + "ah": "ThreatTypes", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "TimeGenerated", + "ah": "TimeGenerated", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "Timestamp", + "ah": "Timestamp", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "To", + "ah": "To", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "UrlCount", + "ah": "UrlCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "UserLevelAction", + "ah": "UserLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "UserLevelPolicy", + "ah": "UserLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + } + ], + "extraInAh": [] + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/7/content/items/2/content/query", + "sourceSha256": "053552593226491eb95fad35412acb6c8ad49eda9011d3a596d293286f64c2ce", + "targetSha256": "053552593226491eb95fad35412acb6c8ad49eda9011d3a596d293286f64c2ce" + }, + { + "sourcePath": "/items/7/content/items/3/content/parameters/1/query", + "parameter": true, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "bcb564f29d1b232472686d4957887149e202de4237056bede37cd9c6c99d033a" + }, + "conversion": { + "sourceId": "/items/7/content/items/3/content/parameters/1/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "EmailUrlInfo\r\n| summarize UrlCount=count() by UrlDomain\r\n| sort by UrlCount desc\r\n| project UrlDomain, strcat(UrlDomain, ' - ', UrlCount, ' URLs')", + "resolvedTables": [ + "EmailUrlInfo" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailUrlInfo", + "ahTable": "EmailUrlInfo", + "identical": true, + "verdict": "Easy", + "score": 1.0, + "columnCount": 7, + "note": "schema identical; no column changes" + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/7/content/items/3/content/parameters/1/query", + "sourceSha256": "bcb564f29d1b232472686d4957887149e202de4237056bede37cd9c6c99d033a", + "targetSha256": "bcb564f29d1b232472686d4957887149e202de4237056bede37cd9c6c99d033a" + }, + { + "sourcePath": "/items/7/content/items/4/content/query", + "parameter": false, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "37fc28a79b04647d27bc2989c9cd6a579f34ae5d51cfe17b7efeb00d3b469b00" + }, + "conversion": { + "sourceId": "/items/7/content/items/4/content/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "let ids = array_concat(dynamic({NetworkMessageIdsSender}),dynamic({NetworkMessageIdsRecipient}),dynamic({NetworkMessageIdsDomain}));\r\nEmailUrlInfo\r\n| where NetworkMessageId in (ids) or array_length(ids) == 0\r\n| where Url contains \"{Url}\"\r\n| where \"*\" in ({UrlDomain}) or UrlDomain in ({UrlDomain})\r\n| summarize UniqueMessagesWithUrl=dcount(NetworkMessageId), NetworkMessageIdWithUrl=make_set(NetworkMessageId) by Url, UrlDomain", + "resolvedTables": [ + "EmailUrlInfo" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailUrlInfo", + "ahTable": "EmailUrlInfo", + "identical": true, + "verdict": "Easy", + "score": 1.0, + "columnCount": 7, + "note": "schema identical; no column changes" + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/7/content/items/4/content/query", + "sourceSha256": "37fc28a79b04647d27bc2989c9cd6a579f34ae5d51cfe17b7efeb00d3b469b00", + "targetSha256": "37fc28a79b04647d27bc2989c9cd6a579f34ae5d51cfe17b7efeb00d3b469b00" + }, + { + "sourcePath": "/items/7/content/items/5/content/query", + "parameter": false, + "resolutionEvidence": { + "actor": "kingwil", + "reference": "User approval 2026-10-14 against e63e9f85f96128834e2d334990adc0eea1b5e904cf3c7d0e5dc754817653c9b4; all source query hashes unchanged after authorized literal-range fix", + "planSha256": "17829f17e44e7cf201227e0d797d9ab584b39d22523b502a0089ba8f4154fa8d", + "decision": "accept", + "querySha256": "f1f231be6c48d158095ac2c171a67c10401244333c91a1f82803393d33efa9bd" + }, + "conversion": { + "sourceId": "/items/7/content/items/5/content/query", + "artifactType": "workbook", + "status": "converted", + "convertedKql": "let ids = dynamic({NetworkMessageIdWithUrl});\r\nEmailUrlInfo\r\n| where NetworkMessageId in (ids)\r\n| distinct NetworkMessageId\r\n| join kind=leftouter (EmailEvents) on NetworkMessageId\r\n| extend RecipientDomain = tostring(split(RecipientEmailAddress, \"@\", 1)[0])\r\n| project TimeGenerated, SenderMailFromAddress, RecipientEmailAddress, Subject, EmailDirection, EmailLanguage, DeliveryAction, ConfidenceLevel, AttachmentCount, UrlCount, NetworkMessageId\r\n| sort by TimeGenerated desc", + "resolvedTables": [ + "EmailEvents", + "EmailUrlInfo" + ], + "mappingTier": "1to1", + "renamedTables": {}, + "renamedAsimTables": {}, + "diff": [], + "schemaMap": [ + { + "sentinelTable": "EmailEvents", + "ahTable": "EmailEvents", + "identical": false, + "verdict": "Hard", + "score": 0.98, + "columns": [ + { + "sentinel": "AdditionalFields", + "ah": "AdditionalFields", + "laType": "dynamic", + "ahType": "string", + "relation": "compatible" + }, + { + "sentinel": "AttachmentCount", + "ah": "AttachmentCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "AuthenticationDetails", + "ah": "AuthenticationDetails", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "BulkComplaintLevel", + "ah": "BulkComplaintLevel", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "Cc", + "ah": "Cc", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "ConfidenceLevel", + "ah": "ConfidenceLevel", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Connectors", + "ah": "Connectors", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Context", + "ah": "Context", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryAction", + "ah": "DeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DeliveryLocation", + "ah": "DeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DetectionMethods", + "ah": "DetectionMethods", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "DistributionList", + "ah": "DistributionList", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailAction", + "ah": "EmailAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicy", + "ah": "EmailActionPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailActionPolicyGuid", + "ah": "EmailActionPolicyGuid", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailClusterId", + "ah": "EmailClusterId", + "laType": "long", + "ahType": "long", + "relation": "exact" + }, + { + "sentinel": "EmailDirection", + "ah": "EmailDirection", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailLanguage", + "ah": "EmailLanguage", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "EmailSize", + "ah": "EmailSize", + "laType": "int", + "ahType": "long", + "relation": "compatible" + }, + { + "sentinel": "ExchangeTransportRule", + "ah": "ExchangeTransportRule", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ForwardingInformation", + "ah": "ForwardingInformation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "InternetMessageId", + "ah": "InternetMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "IsFirstContact", + "ah": "IsFirstContact", + "laType": "bool", + "ahType": "bool", + "relation": "exact" + }, + { + "sentinel": "LastEventExecutionTime", + "laType": "datetime", + "ah": null, + "ahType": null, + "relation": "missing", + "suggestion": null, + "suggestionSource": null, + "note": "no direct AH equivalent; flag for review" + }, + { + "sentinel": "LatestDeliveryAction", + "ah": "LatestDeliveryAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "LatestDeliveryLocation", + "ah": "LatestDeliveryLocation", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "NetworkMessageId", + "ah": "NetworkMessageId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelAction", + "ah": "OrgLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "OrgLevelPolicy", + "ah": "OrgLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientDomain", + "ah": "RecipientDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientEmailAddress", + "ah": "RecipientEmailAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "RecipientObjectId", + "ah": "RecipientObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ReportId", + "ah": "ReportId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderDisplayName", + "ah": "SenderDisplayName", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromAddress", + "ah": "SenderFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderFromDomain", + "ah": "SenderFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv4", + "ah": "SenderIPv4", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderIPv6", + "ah": "SenderIPv6", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromAddress", + "ah": "SenderMailFromAddress", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderMailFromDomain", + "ah": "SenderMailFromDomain", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "SenderObjectId", + "ah": "SenderObjectId", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "Subject", + "ah": "Subject", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatClassification", + "ah": "ThreatClassification", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatNames", + "ah": "ThreatNames", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "ThreatTypes", + "ah": "ThreatTypes", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "TimeGenerated", + "ah": "TimeGenerated", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "Timestamp", + "ah": "Timestamp", + "laType": "datetime", + "ahType": "datetime", + "relation": "exact" + }, + { + "sentinel": "To", + "ah": "To", + "laType": "dynamic", + "ahType": "dynamic", + "relation": "exact" + }, + { + "sentinel": "UrlCount", + "ah": "UrlCount", + "laType": "int", + "ahType": "int", + "relation": "exact" + }, + { + "sentinel": "UserLevelAction", + "ah": "UserLevelAction", + "laType": "string", + "ahType": "string", + "relation": "exact" + }, + { + "sentinel": "UserLevelPolicy", + "ah": "UserLevelPolicy", + "laType": "string", + "ahType": "string", + "relation": "exact" + } + ], + "extraInAh": [] + }, + { + "sentinelTable": "EmailUrlInfo", + "ahTable": "EmailUrlInfo", + "identical": true, + "verdict": "Easy", + "score": 1.0, + "columnCount": 7, + "note": "schema identical; no column changes" + } + ], + "recommendations": [], + "confidence": 0.7, + "unsupported": [], + "validation": null, + "blockedReason": null + }, + "status": "converted", + "outputPath": "/items/7/content/items/5/content/query", + "sourceSha256": "f1f231be6c48d158095ac2c171a67c10401244333c91a1f82803393d33efa9bd", + "targetSha256": "f1f231be6c48d158095ac2c171a67c10401244333c91a1f82803393d33efa9bd" + } + ] + }, + "requiredWorkloads": [ + { + "workload": "mdo", + "dataTypes": [ + "EmailAttachmentInfo", + "EmailEvents", + "EmailUrlInfo" + ] + } + ], + "requiredDataConnectors": [], + "dependencyReviewRequired": false + } +} From ca49c39c2bec0c63ef4e76e19d24dc5094bfa86a Mon Sep 17 00:00:00 2001 From: v-skharode Date: Thu, 15 Oct 2026 11:42:58 +0530 Subject: [PATCH 2/6] Updated ReleaseNotes updated 3.2.0 row. --- Solutions/Microsoft Defender for Office 365/ReleaseNotes.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Solutions/Microsoft Defender for Office 365/ReleaseNotes.md b/Solutions/Microsoft Defender for Office 365/ReleaseNotes.md index 482452550cf..2b3ae40d695 100644 --- a/Solutions/Microsoft Defender for Office 365/ReleaseNotes.md +++ b/Solutions/Microsoft Defender for Office 365/ReleaseNotes.md @@ -1,8 +1,7 @@ | **Version** | **Date Modified (DD-MM-YYYY)** | **Change History** | |-------------|--------------------------------|--------------------------------------------------------------------------| -| 3.2.0 | 14-10-2026 | Added an **XDR Workbook** alongside the existing Sentinel workbook, preserving the connector and playbooks. | +| 3.2.0 | 15-10-2026 | Added the Microsoft Defender for Office 365 **XDR Workbook** alongside the existing Sentinel **Workbook**; the **Data Connector** and six **Playbooks** remain unchanged. | | 3.0.3 | 07-04-2025 | Updated ConnectivityCriteria Type in **Data Connector**. | | 3.0.2 | 24-04-2024 | Updated link for **Custom Connector** redirection in playbooks | | 3.0.1 | 29-09-2023 | 1 new **Playbook** added to the solution | -| 3.0.0 | 11-07-2023 | 4 new **Playbooks** added to the solution | -| | | 1 **Custom Connector** added as a pre-requisite for playbooks deployment | \ No newline at end of file +| 3.0.0 | 11-07-2023 | Added 4 **Playbooks** and 1 **Custom Connector** required for playbook deployment. | From 8714b8141ed62841d658d413ee087819bc70f304 Mon Sep 17 00:00:00 2001 From: v-skharode Date: Thu, 15 Oct 2026 11:56:31 +0530 Subject: [PATCH 3/6] Revert "Updated ReleaseNotes" This reverts commit ca49c39c2bec0c63ef4e76e19d24dc5094bfa86a. --- Solutions/Microsoft Defender for Office 365/ReleaseNotes.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Solutions/Microsoft Defender for Office 365/ReleaseNotes.md b/Solutions/Microsoft Defender for Office 365/ReleaseNotes.md index 2b3ae40d695..482452550cf 100644 --- a/Solutions/Microsoft Defender for Office 365/ReleaseNotes.md +++ b/Solutions/Microsoft Defender for Office 365/ReleaseNotes.md @@ -1,7 +1,8 @@ | **Version** | **Date Modified (DD-MM-YYYY)** | **Change History** | |-------------|--------------------------------|--------------------------------------------------------------------------| -| 3.2.0 | 15-10-2026 | Added the Microsoft Defender for Office 365 **XDR Workbook** alongside the existing Sentinel **Workbook**; the **Data Connector** and six **Playbooks** remain unchanged. | +| 3.2.0 | 14-10-2026 | Added an **XDR Workbook** alongside the existing Sentinel workbook, preserving the connector and playbooks. | | 3.0.3 | 07-04-2025 | Updated ConnectivityCriteria Type in **Data Connector**. | | 3.0.2 | 24-04-2024 | Updated link for **Custom Connector** redirection in playbooks | | 3.0.1 | 29-09-2023 | 1 new **Playbook** added to the solution | -| 3.0.0 | 11-07-2023 | Added 4 **Playbooks** and 1 **Custom Connector** required for playbook deployment. | +| 3.0.0 | 11-07-2023 | 4 new **Playbooks** added to the solution | +| | | 1 **Custom Connector** added as a pre-requisite for playbooks deployment | \ No newline at end of file From dac4f6d4c680f833a8b758ae40c3d4ff0fa5f0e4 Mon Sep 17 00:00:00 2001 From: kingwil <5839248+kingwil@users.noreply.github.com> Date: Thu, 15 Oct 2026 09:03:29 +0100 Subject: [PATCH 4/6] Add native O365 Detections and Insights XDR workbook to 3.2.0 Preserve the original native Notebook and explicit source/query review provenance without adding a Sentinel parent. Regenerate the additive candidate with the V3.1 hybrid packager while retaining all existing content. The packaging-time ARM-TTK run reports 47 passes and six failures, plus a trailing null-Path diagnostic. This remains an unqualified review candidate; no full suite or deployment was performed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- ...olution_MicrosoftDefenderforOffice365.json | 3 +- .../Package/3.2.0.zip | Bin 39011 -> 257672 bytes .../Package/createUiDefinition.json | 2 +- .../Package/mainTemplate.json | 29926 +++++++++++++++- .../ReleaseNotes.md | 2 +- ...nderForOffice365DetectionsAndInsights.json | 14895 ++++++++ ...nderForOffice365DetectionsAndInsights.json | 17407 +++++++++ 7 files changed, 62231 insertions(+), 4 deletions(-) create mode 100644 Solutions/Microsoft Defender for Office 365/Workbook Sources/Native/MicrosoftDefenderForOffice365DetectionsAndInsights.json create mode 100644 Solutions/Microsoft Defender for Office 365/XDR Workbooks/MicrosoftDefenderForOffice365DetectionsAndInsights.json diff --git a/Solutions/Microsoft Defender for Office 365/Data/Solution_MicrosoftDefenderforOffice365.json b/Solutions/Microsoft Defender for Office 365/Data/Solution_MicrosoftDefenderforOffice365.json index b2f1408ca46..526f372c706 100644 --- a/Solutions/Microsoft Defender for Office 365/Data/Solution_MicrosoftDefenderforOffice365.json +++ b/Solutions/Microsoft Defender for Office 365/Data/Solution_MicrosoftDefenderforOffice365.json @@ -25,6 +25,7 @@ "OfficeATP" ], "XDR Workbooks": [ - "XDR Workbooks/MicrosoftDefenderForOffice365.json" + "XDR Workbooks/MicrosoftDefenderForOffice365.json", + "XDR Workbooks/MicrosoftDefenderForOffice365DetectionsAndInsights.json" ] } diff --git a/Solutions/Microsoft Defender for Office 365/Package/3.2.0.zip b/Solutions/Microsoft Defender for Office 365/Package/3.2.0.zip index e3034385c30968dd484a5cd17f6bd23c7482685e..2fc9e487489953aa53685e5af20671008ee4085e 100644 GIT binary patch literal 257672 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

q!9V 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

#yb%SN5`lRGdLF|Bs4&0=)-}UfqL%VGLXLb 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

BWF`1%N;oUtJ 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\n\n**Note:** Please refer to the following before installing the solution: \n\n• Review the solution [Release Notes](https://github.com/Azure/Azure-Sentinel/tree/master/Solutions/Microsoft%20Defender%20for%20Office%20365/ReleaseNotes.md)\n\n • There may be [known issues](https://aka.ms/sentinelsolutionsknownissues) pertaining to this Solution, please refer to them before installing.\n\nThe [Microsoft Defender for Office 365](https://www.microsoft.com/security/business/threat-protection/office-365-defender) solution for Microsoft Sentinel enables you to ingest security alerts from the Defender for Office 365 platform, providing visibility into threats within email messages, links (URLs) and collaboration tools.\n\n**Underlying Microsoft Technologies used:**\n\nThis solution is dependent on the following technologies, and some of these dependencies either may be in [Preview](https://azure.microsoft.com/support/legal/preview-supplemental-terms/) state or might result in additional ingestion or operational costs:\n\na. [Codeless Connector Platform/Native Microsoft Sentinel Polling](https://docs.microsoft.com/azure/sentinel/create-codeless-connector?tabs=deploy-via-arm-template%2Cconnect-via-the-azure-portal)\n\n**Data Connectors:** 1, **Workbooks:** 1, **Function Apps:** 1, **Playbooks:** 5, **XDR Workbooks:** 1\n\n[Learn more about Microsoft Sentinel](https://aka.ms/azuresentinel) | [Learn more about Solutions](https://aka.ms/azuresentinelsolutionsdoc)", + "description": "\n\n**Note:** Please refer to the following before installing the solution: \n\n• Review the solution [Release Notes](https://github.com/Azure/Azure-Sentinel/tree/master/Solutions/Microsoft%20Defender%20for%20Office%20365/ReleaseNotes.md)\n\n • There may be [known issues](https://aka.ms/sentinelsolutionsknownissues) pertaining to this Solution, please refer to them before installing.\n\nThe [Microsoft Defender for Office 365](https://www.microsoft.com/security/business/threat-protection/office-365-defender) solution for Microsoft Sentinel enables you to ingest security alerts from the Defender for Office 365 platform, providing visibility into threats within email messages, links (URLs) and collaboration tools.\n\n**Underlying Microsoft Technologies used:**\n\nThis solution is dependent on the following technologies, and some of these dependencies either may be in [Preview](https://azure.microsoft.com/support/legal/preview-supplemental-terms/) state or might result in additional ingestion or operational costs:\n\na. [Codeless Connector Platform/Native Microsoft Sentinel Polling](https://docs.microsoft.com/azure/sentinel/create-codeless-connector?tabs=deploy-via-arm-template%2Cconnect-via-the-azure-portal)\n\n**Data Connectors:** 1, **Workbooks:** 1, **Function Apps:** 1, **Playbooks:** 5, **XDR Workbooks:** 2\n\n[Learn more about Microsoft Sentinel](https://aka.ms/azuresentinel) | [Learn more about Solutions](https://aka.ms/azuresentinelsolutionsdoc)", "subscription": { "resourceProviders": [ "Microsoft.OperationsManagement/solutions", diff --git a/Solutions/Microsoft Defender for Office 365/Package/mainTemplate.json b/Solutions/Microsoft Defender for Office 365/Package/mainTemplate.json index 6c71a85b353..31dda3269b0 100644 --- a/Solutions/Microsoft Defender for Office 365/Package/mainTemplate.json +++ b/Solutions/Microsoft Defender for Office 365/Package/mainTemplate.json @@ -4084,7 +4084,7 @@ "contentSchemaVersion": "3.0.0", "displayName": "Microsoft Defender for Office 365", "publisherDisplayName": "Microsoft Sentinel, Microsoft Corporation", - "descriptionHtml": "

Note: Please refer to the following before installing the solution:

\n

• Review the solution Release Notes

\n

• There may be known issues pertaining to this Solution, please refer to them before installing.

\n

The Microsoft Defender for Office 365 solution for Microsoft Sentinel enables you to ingest security alerts from the Defender for Office 365 platform, providing visibility into threats within email messages, links (URLs) and collaboration tools.

\n

Underlying Microsoft Technologies used:

\n

This solution is dependent on the following technologies, and some of these dependencies either may be in Preview state or might result in additional ingestion or operational costs:

\n
    \n
  1. Codeless Connector Platform/Native Microsoft Sentinel Polling
  2. \n
\n

Data Connectors: 1, Workbooks: 1, Function Apps: 1, Playbooks: 5, XDR Workbooks: 1

\n

Learn more about Microsoft Sentinel | Learn more about Solutions

\n", + "descriptionHtml": "

Note: Please refer to the following before installing the solution:

\n

• Review the solution Release Notes

\n

• There may be known issues pertaining to this Solution, please refer to them before installing.

\n

The Microsoft Defender for Office 365 solution for Microsoft Sentinel enables you to ingest security alerts from the Defender for Office 365 platform, providing visibility into threats within email messages, links (URLs) and collaboration tools.

\n

Underlying Microsoft Technologies used:

\n

This solution is dependent on the following technologies, and some of these dependencies either may be in Preview state or might result in additional ingestion or operational costs:

\n
    \n
  1. Codeless Connector Platform/Native Microsoft Sentinel Polling
  2. \n
\n

Data Connectors: 1, Workbooks: 1, Function Apps: 1, Playbooks: 5, XDR Workbooks: 2

\n

Learn more about Microsoft Sentinel | Learn more about Solutions

\n", "contentKind": "Solution", "contentProductId": "[variables('_solutioncontentProductId')]", "id": "[variables('_solutioncontentProductId')]", @@ -4153,6 +4153,11 @@ "kind": "DefenderWorkbook", "contentId": "3b0f3eee-3047-526b-aae0-e259182d264d", "version": "3.2.0" + }, + { + "kind": "DefenderWorkbook", + "contentId": "55a394cc-f0af-55c1-8ff2-ec483e3e68a3", + "version": "3.2.0" } ] }, @@ -7461,6 +7466,29925 @@ } }, "condition": "[parameters('DeployDefenderWorkbook')]" + }, + { + "type": "Microsoft.Resources/deployments", + "apiVersion": "2025-04-01", + "name": "DefenderWorkbook-fcbb3d6973f129d54269dbefb1a96dea", + "dependsOn": [ + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" + ], + "properties": { + "mode": "Incremental", + "expressionEvaluationOptions": { + "scope": "inner" + }, + "template": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "imports": { + "MicrosoftSecurity": { + "provider": "MicrosoftSecurity", + "version": "1.0.0" + } + }, + "resources": { + "workbook": { + "import": "MicrosoftSecurity", + "type": "Microsoft.Security/workbooks@2026-06-01-preview", + "properties": { + "id": "0eba4431-9e8b-5ffb-9623-2a0391db7b01", + "name": "Microsoft Defender for Office 365 Detections and Insights - ISOC", + "content": { + "version": "Notebook/1.0", + "items": [ + { + "type": 1, + "content": { + "json": "# Microsoft Defender for Office 365 Detections and Insights\n\nThis workbook provides email and collaboration security insights directly in Microsoft Defender using Advanced Hunting. It is designed for customers using workspace-less Workbooks in the Integrated Security Operations Center (ISOC) and does not require Microsoft Sentinel or a Log Analytics workspace.\n\n[Learn about Integrated Security Operations Center in Microsoft Defender](https://techcommunity.microsoft.com/blog/microsoftthreatprotectionblog/integrated-security-operations-center-in-microsoft-defender/4559097)\n\n- The time selector is bounded by the Defender data available to this tenant.\n- The default range is 7 days and the maximum selectable range is 90 days.\n- Subscription, workspace, cross-workspace, and MSSP selectors are not available in the workspace-less experience.\n- Incident visuals that depend on Microsoft Sentinel tables show an explicit ISOC workspace-required notice." + }, + "name": "text - 2", + "id": "d2b45ab8-a1c1-43d2-853d-290640bf4c94" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "2e238f92-709c-410b-93e0-60eab6150a75", + "version": "KqlParameterItem/1.0", + "name": "TimeRange", + "type": 4, + "isRequired": true, + "isGlobal": true, + "typeSettings": { + "selectableValues": [ + { + "durationMs": 3600000 + }, + { + "durationMs": 14400000 + }, + { + "durationMs": 43200000 + }, + { + "durationMs": 86400000 + }, + { + "durationMs": 172800000 + }, + { + "durationMs": 259200000 + }, + { + "durationMs": 604800000 + }, + { + "durationMs": 1209600000 + }, + { + "durationMs": 2592000000 + }, + { + "durationMs": 5184000000 + }, + { + "durationMs": 7776000000 + } + ], + "allowCustom": true + }, + "timeContext": { + "durationMs": 86400000 + }, + "value": { + "durationMs": 604800000 + }, + "key": "2e238f92-709c-410b-93e0-60eab6150a75" + }, + { + "id": "165f2f4a-e49f-4561-adc5-d0527a4caf32", + "version": "KqlParameterItem/1.0", + "name": "Granularity", + "label": "Trend interval", + "type": 2, + "isRequired": true, + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "jsonData": "[[{\"value\":\"1d\",\"label\":\"Daily (1d)\",\"selected\":true},{\"value\":\"7d\",\"label\":\"Weekly (7d)\",\"selected\":false},{\"value\":\"30d\",\"label\":\"Monthly (30d)\",\"selected\":false},{\"value\":\"90d\",\"label\":\"Quarterly (90d)\",\"selected\":false}]", + "timeContext": { + "durationMs": 86400000 + }, + "value": "1d" + } + ], + "style": "pills" + }, + "name": "parameters - 1", + "id": "0021e733-42b4-461f-8f6c-14e6e765389d" + }, + { + "type": 11, + "content": { + "version": "LinkItem/1.0", + "style": "tabs", + "links": [ + { + "id": "3d26d949-bba8-486c-9af7-2b85bd5c8ab0", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Executive Summary", + "subTarget": "1", + "style": "link", + "key": "3d26d949-bba8-486c-9af7-2b85bd5c8ab0" + }, + { + "id": "a5f95467-84c1-4d8b-858c-7819339af748", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Email - Malware", + "subTarget": "2", + "style": "link", + "key": "a5f95467-84c1-4d8b-858c-7819339af748" + }, + { + "id": "b6c93de8-16d9-4c90-999b-837935de5645", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Email - Phish", + "subTarget": "3", + "style": "link", + "key": "b6c93de8-16d9-4c90-999b-837935de5645" + }, + { + "id": "9e006e81-4fd4-40b9-9d20-3705dd6c17ad", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Email - Impersonation & BEC", + "subTarget": "15", + "style": "link", + "key": "75f1e28f-e95a-4810-af40-6b47b35cda46" + }, + { + "id": "df2c53b4-b6ed-4151-95fb-b3f08b849b84", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Email - Spam", + "subTarget": "4", + "style": "link", + "key": "df2c53b4-b6ed-4151-95fb-b3f08b849b84" + }, + { + "id": "fd2006c9-39b5-43ac-b05d-47309ee22deb", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Teams & Collaboration", + "subTarget": "14", + "style": "link", + "key": "fd2006c9-39b5-43ac-b05d-47309ee22deb" + }, + { + "id": "ee01f95a-c5f7-4864-82e8-54a164741ba2", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "File - Malware (SharePoint, Teams and OneDrive)", + "subTarget": "9", + "style": "link", + "key": "ee01f95a-c5f7-4864-82e8-54a164741ba2" + }, + { + "id": "9df30067-3266-48a8-b9e3-d65952098d46", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "URL & Clicks", + "subTarget": "5", + "style": "link", + "key": "9df30067-3266-48a8-b9e3-d65952098d46" + }, + { + "id": "b4be0ac3-3f48-44a8-b4b6-b46e17c710cd", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Top Users & Exfiltration", + "subTarget": "6", + "style": "link", + "key": "b4be0ac3-3f48-44a8-b4b6-b46e17c710cd" + }, + { + "id": "e1d34091-7b3c-4e2d-a032-8be82a989313", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Email - Detection Overrides", + "subTarget": "7", + "style": "link", + "key": "e1d34091-7b3c-4e2d-a032-8be82a989313" + }, + { + "id": "a1e6264d-8f85-4a94-9ffd-eee36c04a0d5", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Post-Delivery & Quarantine", + "subTarget": "11", + "style": "link", + "key": "a1e6264d-8f85-4a94-9ffd-eee36c04a0d5" + }, + { + "id": "08c43a4f-f502-4813-9b8d-3f6b0b62b2fd", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "False Negative(FN) Submissions", + "subTarget": "8", + "style": "link", + "key": "08c43a4f-f502-4813-9b8d-3f6b0b62b2fd" + }, + { + "id": "638d931f-f319-4914-b72d-8d68e914c7d4", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "False Positive(FP) Submissions", + "subTarget": "10", + "style": "link", + "key": "638d931f-f319-4914-b72d-8d68e914c7d4" + }, + { + "id": "b2920bee-c32a-4fdd-9d32-b004db2f3ac8", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Security Operations Center (SOC) Insights", + "subTarget": "13", + "style": "link", + "key": "b2920bee-c32a-4fdd-9d32-b004db2f3ac8" + } + ] + }, + "name": "links - 14", + "id": "5c9a1d6b-c248-432b-a1c0-496337635775" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Defender for Office 365 - Protection Insights\r\n
\r\n\r\n**Microsoft Defender for Office 365** is a comprehensive security solution designed to protect organizations from advanced threats targeting their email and collaboration tools. It leverages a multi-layered approach to safeguard against phishing, malware, business email compromise (BEC), and other sophisticated attacks.\r\n" + }, + "name": "text - 13", + "styleSettings": { + "margin": "0", + "padding": "0" + }, + "id": "46119f93-fad9-413c-8e10-7615c6fdde2f" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows the number behind the effectiveness of phish and malware false positives including post delivery events but without edge data detections.\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\n\r\n// Get all mailflow detected as clean at time of delivery \r\nlet EmailEventsClean = materialize( \r\n EmailEvents \r\n | where Timestamp between (toscalar(minTime) .. toscalar(maxTime)) and EmailDirection == \"Inbound\" \r\n // | where ThreatTypes !contains \"Phish\" and ThreatTypes !contains \"Malware\" // Streaming-SIEM branch disabled for Advanced Hunting current-state semantics.\r\n // this alteration is due to the threat types being updated directly within advanced hunting.\r\n | where DeliveryLocation != \"Quarantine\" // Advanced Hunting current-state branch.\r\n | project NetworkMessageId,ThreatTypes \r\n); \r\n// Get all mailflow detected as phish or malware at time of delivery \r\nlet EmailEventsThreats = materialize( \r\n EmailEvents \r\n | where Timestamp between (toscalar(minTime) .. toscalar(maxTime)) and EmailDirection == \"Inbound\" \r\n | where ThreatTypes contains \"Phish\" or ThreatTypes contains \"Malware\" \r\n | extend MDO_detection = parse_json(DetectionMethods) \r\n | extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n | extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n | project NetworkMessageId,FirstDetection,FirstSubcategory,MDO_detection,ThreatTypes \r\n); \r\n// Get all post delivery ZAP / Redelivery events, and arg_max them to ensure we have the latest verdict to work with for each \r\nlet EmailPostDeliveryFiltered = materialize( \r\n EmailPostDeliveryEvents \r\n | where Timestamp between (toscalar(minTime) .. datetime_add('day', 7, toscalar(maxTime))) \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") or Action has_any (\"Redelivery\",\"Reprocessed\") \r\n | extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n | summarize arg_max(Timestamp, *) by Key \r\n | project Action,ActionType,ActionResult,ThreatTypes,NetworkMessageId \r\n); \r\n// Optional - get all admin submissions for malware or phish, so we can also count these in the miss bucket. \r\nlet CloudAppEventsFiltered = materialize( \r\n CloudAppEvents \r\n | where Timestamp between (toscalar(minTime) .. datetime_add('day', 7, toscalar(maxTime)))\r\n | where ActionType == \"AdminSubmissionSubmitted\" \r\n | extend SubmissionType = tostring(parse_json(RawEventData).SubmissionType) \r\n | extend NetworkMessageId = tostring(parse_json(RawEventData).ObjectId) \r\n | where SubmissionType in (\"1\", \"2\") \r\n | project SubmissionType,NetworkMessageId \r\n); \r\n// get the number of threats caught in mailflow \r\nlet Mal_Phish_Mailflow = toscalar( \r\n EmailEventsThreats \r\n | summarize count() \r\n); \r\n// get the number of threats caught in mailflow which turned out to be false positives (FPs) so we can correct the calculation \r\nlet FP_ZAP = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ThreatTypes !contains \"Phish\" and ThreatTypes !contains \"Malware\" and Action has_any (\"Redelivery\",\"Reprocessed\") \r\n | join kind=leftsemi (EmailEventsThreats) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// get the number of threats successfully cleaned up post delivery, ignoring where administrative policy stopped action \r\nlet FN_ZAP_Successful = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") and ActionResult in (\"Success\",\"AdminPolicy\") \r\n | join kind=leftsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// get the number of threats unsuccessfully cleaned up post delivery. \r\nlet FN_ZAP_Unsuccessful = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") and ActionResult !in (\"Success\",\"AdminPolicy\") \r\n | join kind=leftsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// join the administrative submissions to clean mailflow to find the additional miss \r\nlet FN_Admin_Submissions = toscalar( \r\n CloudAppEventsFiltered \r\n | join kind=rightsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n ); \r\n // print each result, and run the calculation to work out effectiveness at time of delivery and post delivery. \r\n\r\nprint StatisticName=\"Effectiveness Post Delivery\", Value=abs(round(((toreal(toscalar(FN_Admin_Submissions))+toreal(toscalar(FN_ZAP_Unsuccessful)))/(toreal(toscalar(Mal_Phish_Mailflow))+toreal(toscalar(FN_ZAP_Successful))+toreal(toscalar(FN_ZAP_Unsuccessful))+toreal(toscalar(FN_Admin_Submissions))-toreal(toscalar(FP_ZAP)))*100-100),2))", + "size": 1, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "tileSettings": { + "showBorder": false, + "titleContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Value", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "graphSettings": { + "type": 0, + "topContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Value", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "statSettings": { + "valueField": "Value", + "valueAggregation": "None", + "colorSettings": { + "type": "thresholds", + "mode": "foreground", + "heatmapPalette": "greenRed", + "thresholdsGrid": [ + { + "operator": ">", + "thresholdValue": "95", + "representation": "green" + }, + { + "operator": "<=", + "thresholdValue": "95", + "representation": "orange" + }, + { + "operator": "<=", + "thresholdValue": "90", + "representation": "red" + } + ] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "numberFormatSettings": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "tagText": "Phish / Malware Effectiveness - Post Delivery", + "valueFontStyle": "superLarge", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 5", + "id": "62de2a91-a809-48ec-a111-e697d556b2b3" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the percentage of emails released from quarantine out of the total ammount of quarantined emails\r\nlet Quarantine_Releases = toscalar(EmailPostDeliveryEvents\r\n| where Action == \"Quarantine release\"\r\n| join kind=leftouter (EmailEvents | where DeliveryLocation == \"Quarantine\") on NetworkMessageId\r\n| summarize count());\r\nlet Quarantined_Mailflow = toscalar(EmailEvents | where DeliveryLocation == \"Quarantine\"\r\n| summarize count());\r\nprint\r\nQuarantine_Releases = toreal(Quarantine_Releases),\r\nQuarantined_Mailflow = toreal(Quarantined_Mailflow),\r\nRelease_Percentage = abs(round(((toreal(Quarantine_Releases)/toreal(Quarantined_Mailflow))*100),2))", + "size": 1, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "tileSettings": { + "titleContent": { + "columnMatch": "Release_Percentage", + "formatter": 12, + "formatOptions": { + "palette": "none" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + "showBorder": true, + "sortCriteriaField": "Release_Percentage", + "size": "auto" + }, + "graphSettings": { + "type": 0, + "topContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Value", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "statSettings": { + "valueField": "Release_Percentage", + "valueAggregation": "None", + "colorSettings": { + "type": "thresholds", + "mode": "foreground", + "heatmapPalette": "greenRed", + "thresholdsGrid": [ + { + "operator": "<", + "thresholdValue": "5", + "representation": "green" + }, + { + "operator": ">", + "thresholdValue": "5", + "representation": "redDark" + } + ] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "numberFormatSettings": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "tagText": "Quarantine Release Percentage", + "valueFontStyle": "superLarge", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 1", + "id": "858ac1a4-8828-45e9-968c-d3cfc1216c64" + } + ] + }, + "name": "TopNr", + "id": "1369c97e-848b-475a-b447-3a435cb7a1f1" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "**Effectiveness visually represents the protection given by Defender for Office 365 against phishing and malware in email messages.**
\r\nWe consider messages that your users report, as well as decisions that are made after delivery." + }, + "name": "text - 9", + "styleSettings": { + "margin": "1px" + }, + "id": "25e2e19e-aefb-4e37-b28f-b4138d63e109" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows the number behind the effectiveness of phish and malware false positives including post delivery events but without edge data detections.\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\n\r\n// Get all mailflow detected as clean at time of delivery \r\nlet EmailEventsClean = materialize( \r\n EmailEvents \r\n | where Timestamp between (toscalar(minTime) .. toscalar(maxTime)) and EmailDirection == \"Inbound\" \r\n // | where ThreatTypes !contains \"Phish\" and ThreatTypes !contains \"Malware\" // Streaming-SIEM branch disabled for Advanced Hunting current-state semantics.\r\n // this alteration is due to the threat types being updated directly within advanced hunting.\r\n | where DeliveryLocation != \"Quarantine\" // Advanced Hunting current-state branch.\r\n | project NetworkMessageId,ThreatTypes \r\n); \r\n// Get all mailflow detected as phish or malware at time of delivery \r\nlet EmailEventsThreats = materialize( \r\n EmailEvents \r\n | where Timestamp between (toscalar(minTime) .. toscalar(maxTime)) and EmailDirection == \"Inbound\" \r\n | where ThreatTypes contains \"Phish\" or ThreatTypes contains \"Malware\" \r\n | extend MDO_detection = parse_json(DetectionMethods) \r\n | extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n | extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n | project NetworkMessageId,FirstDetection,FirstSubcategory,MDO_detection,ThreatTypes \r\n); \r\n// Get all post delivery ZAP / Redelivery events, and arg_max them to ensure we have the latest verdict to work with for each \r\nlet EmailPostDeliveryFiltered = materialize( \r\n EmailPostDeliveryEvents \r\n | where Timestamp between (toscalar(minTime) .. datetime_add('day', 7, toscalar(maxTime))) \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") or Action has_any (\"Redelivery\",\"Reprocessed\") \r\n | extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n | summarize arg_max(Timestamp, *) by Key \r\n | project Action,ActionType,ActionResult,ThreatTypes,NetworkMessageId \r\n); \r\n// Optional - get all admin submissions for malware or phish, so we can also count these in the miss bucket. \r\nlet CloudAppEventsFiltered = materialize( \r\n CloudAppEvents \r\n | where Timestamp between (toscalar(minTime) .. datetime_add('day', 7, toscalar(maxTime)))\r\n | where ActionType == \"AdminSubmissionSubmitted\" \r\n | extend SubmissionType = tostring(parse_json(RawEventData).SubmissionType) \r\n | extend NetworkMessageId = tostring(parse_json(RawEventData).ObjectId) \r\n | where SubmissionType in (\"1\", \"2\") \r\n | project SubmissionType,NetworkMessageId \r\n); \r\n// get the number of threats caught in mailflow \r\nlet Mal_Phish_Mailflow = toscalar( \r\n EmailEventsThreats \r\n | summarize count() \r\n); \r\n// get the number of threats caught in mailflow which turned out to be false positives (FPs) so we can correct the calculation \r\nlet FP_ZAP = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ThreatTypes !contains \"Phish\" and ThreatTypes !contains \"Malware\" and Action has_any (\"Redelivery\",\"Reprocessed\") \r\n | join kind=leftsemi (EmailEventsThreats) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// get the number of threats successfully cleaned up post delivery, ignoring where administrative policy stopped action \r\nlet FN_ZAP_Successful = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") and ActionResult in (\"Success\",\"AdminPolicy\") \r\n | join kind=leftsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// get the number of threats unsuccessfully cleaned up post delivery. \r\nlet FN_ZAP_Unsuccessful = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") and ActionResult !in (\"Success\",\"AdminPolicy\") \r\n | join kind=leftsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// join the administrative submissions to clean mailflow to find the additional miss \r\nlet FN_Admin_Submissions = toscalar( \r\n CloudAppEventsFiltered \r\n | join kind=rightsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n ); \r\n // print each result, and run the calculation to work out effectiveness at time of delivery and post delivery. \r\nunion withsource=Table \r\n (print StatisticName=\"Mal/Phish Mailflow totals - Minus FPs\", Value=toreal(Mal_Phish_Mailflow) - toreal(FP_ZAP)), \r\n (print StatisticName=\"Admin Mal/Phish FNs Submitted\", Value=toreal(FN_Admin_Submissions)), \r\n (print StatisticName=\"Mal/Phish FPs Reverse Zapped\", Value=toreal(FP_ZAP)), \r\n (print StatisticName=\"Mal / Phish Successfully Zapped\", Value=toreal(FN_ZAP_Successful)), \r\n (print StatisticName=\"Mal / Phish UN-Successfully Zapped\", Value=toreal(FN_ZAP_Unsuccessful)), \r\n (print StatisticName=\"Effectiveness Post Delivery (%)\", Value=abs(round(((toreal(FN_Admin_Submissions)+toreal(FN_ZAP_Unsuccessful))/(toreal(Mal_Phish_Mailflow)+toreal(FN_ZAP_Successful)+toreal(FN_ZAP_Unsuccessful)+toreal(FN_Admin_Submissions)-toreal(FP_ZAP))*100-100),2))), \r\n (print StatisticName=\"Effectiveness Pre-Delivery (%)\", Value=abs(round(((toreal(FN_Admin_Submissions)+toreal(FN_ZAP_Unsuccessful)+toreal(FN_ZAP_Successful))/(toreal(Mal_Phish_Mailflow)+toreal(FN_ZAP_Successful)+toreal(FN_ZAP_Unsuccessful)+toreal(FN_Admin_Submissions)-toreal(FP_ZAP))*100-100),2))) \r\n| project StatisticName, Value", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Value", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "tileSettings": { + "showBorder": false, + "titleContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Value", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "graphSettings": { + "type": 2, + "topContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Value", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + }, + "nodeIdField": "StatisticName", + "sourceIdField": "Value", + "targetIdField": "Value", + "graphOrientation": 3, + "showOrientationToggles": false, + "nodeSize": null, + "staticNodeSize": 100, + "colorSettings": null, + "hivesMargin": 5, + "edgeColorSettings": null + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 7", + "id": "9e09ff94-8092-49c7-860f-341049e1398c" + } + ] + }, + "customWidth": "50", + "name": "Effectiveness Nr", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "31081a73-9a54-4668-9e26-ad7347f1e06e" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "**Quarantine release rate by detection technology.** \r\n
\r\nFor each detector, the share of its quarantined mail that was later released (Release % = released / quarantined). A high rate can indicate false positives worth reviewing." + }, + "name": "text - 1", + "styleSettings": { + "margin": "1px" + }, + "id": "e9848043-03dd-4ada-9e73-238067463f74" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Per detection technology: the share of its quarantined emails later released from quarantine (a high rate can indicate false positives). Top 7 by release rate; detectors with <10 quarantined excluded so the rate is meaningful.\r\nEmailEvents\r\n| where DeliveryLocation == \"Quarantine\"\r\n| extend MDO_detection = parse_json(DetectionMethods)\r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0]))\r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\")\r\n| where FirstSubcategory contains \"Malware\" or FirstSubcategory contains \"Phish\"\r\n| join kind=leftouter (\r\n EmailPostDeliveryEvents\r\n | where Action == \"Quarantine release\"\r\n | distinct NetworkMessageId\r\n | extend ReleasedFlag = \"yes\"\r\n ) on NetworkMessageId\r\n| summarize Quarantined = dcount(NetworkMessageId), Released = dcountif(NetworkMessageId, ReleasedFlag == \"yes\") by FirstSubcategory\r\n| where Quarantined >= 10 and Released > 0\r\n| extend ReleaseRate = round(Released * 100.0 / Quarantined, 2)\r\n| project ['Detection Technology']=FirstSubcategory, ['Quarantined Emails']=Quarantined, ['Released']=Released, ['Release %']=ReleaseRate\r\n| order by ['Release %'] desc\r\n| take 7", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Quarantined Emails", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Released", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Release %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 2", + "id": "1bbae9d1-d6f8-446a-817c-8fdc2df83d4c" + } + ] + }, + "customWidth": "50", + "name": "Quarantine Overview Relese", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "36fd8f20-ece7-4889-9fb1-f5b85b97b45a" + } + ] + }, + "customWidth": "100", + "name": "group - Exec Protection Insights", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "1d8e22e0-22f7-453e-aed2-9e56ace1363a" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Protection details\r\n
\r\n\r\nThis Overview provides an executive summary of your Microsoft Defender for Office 365 email security posture: the volume of mail processed, threats detected and filtered (phishing, malware, spam), overall protection effectiveness, and the mix of threats targeting your organization. Use it as a starting point, then drill into the dedicated tabs for detailed investigation." + }, + "name": "text - 13", + "id": "24cf577c-e12a-4747-95a7-1c19bee17397" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "5c0f0101-0a11-4b22-9c33-000000000101", + "version": "KqlParameterItem/1.0", + "name": "ProtectionView", + "label": "Protection view", + "type": 2, + "isRequired": true, + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "jsonData": "[[{ \"value\": \"Table\", \"label\": \"Summary table\", \"selected\": true }, { \"value\": \"Tiles\", \"label\": \"Detailed tiles\" }]", + "value": "Tiles" + } + ], + "style": "pills" + }, + "name": "Protection view selector", + "id": "5c0f0102-0a11-4b22-9c33-000000000102" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let base = materialize(EmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| summarize arg_max(Timestamp, ThreatTypes, DeliveryAction, OrgLevelPolicy, OrgLevelAction, UserLevelAction) by Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress));\r\nlet agg = materialize(base | summarize\r\n Total = count(),\r\n Filtered = countif(isnotempty(ThreatTypes) and DeliveryAction != \"Delivered\" and OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")),\r\n FMal = countif(ThreatTypes has \"Malware\" and OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")),\r\n FPhish = countif(ThreatTypes has \"Phish\" and not(ThreatTypes has \"Malware\") and DeliveryAction != \"Delivered\" and OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")),\r\n FSpam = countif(ThreatTypes == \"Spam\" and DeliveryAction != \"Delivered\" and OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")),\r\n Deliv = countif(isnotempty(ThreatTypes) and DeliveryAction == \"Delivered\" and (isnotempty(OrgLevelAction) or isnotempty(UserLevelAction))),\r\n Blocked = countif(isempty(ThreatTypes) and DeliveryAction != \"Delivered\" and (isnotempty(OrgLevelAction) or isnotempty(UserLevelAction))),\r\n Clean = countif(isempty(ThreatTypes) and DeliveryAction == \"Delivered\"));\r\nlet pd = materialize(EmailPostDeliveryEvents | where ActionResult == \"Success\" | summarize MalZap = countif(ActionType == \"Malware ZAP\"), PhishZap = countif(ActionType == \"Phish ZAP\"), SpamZap = countif(ActionType == \"Spam ZAP\"));\r\nlet sub = materialize(CloudAppEvents | extend R = tostring(parse_json(RawEventData).RecordType), SCT = tostring(parse_json(RawEventData).SubmissionContentType) | where R == \"29\" | summarize Adm = countif(ActionType == \"AdminSubmissionSubmitted\" and SCT == \"Mail\"), Usr = countif(ActionType == \"UserSubmission\"));\r\nlet Total = toscalar(agg | project Total);\r\nlet Filtered = toscalar(agg | project Filtered);\r\nlet FMal = toscalar(agg | project FMal);\r\nlet FPhish = toscalar(agg | project FPhish);\r\nlet FSpam = toscalar(agg | project FSpam);\r\nlet Deliv = toscalar(agg | project Deliv);\r\nlet Blocked = toscalar(agg | project Blocked);\r\nlet Clean = toscalar(agg | project Clean);\r\nlet MalZap = toscalar(pd | project MalZap);\r\nlet PhishZap = toscalar(pd | project PhishZap);\r\nlet SpamZap = toscalar(pd | project SpamZap);\r\nlet Adm = toscalar(sub | project Adm);\r\nlet Usr = toscalar(sub | project Usr);\r\nunion\r\n (print o = 1, Name = \"Total Inbound Emails\", Count = Total),\r\n (print o = 2, Name = \"    Filtering Totals\", Count = Filtered),\r\n (print o = 3, Name = \"        Filtered as Malware\", Count = FMal),\r\n (print o = 4, Name = \"        Filtered as Phish\", Count = FPhish),\r\n (print o = 5, Name = \"        Filtered as Spam\", Count = FSpam),\r\n (print o = 6, Name = \"    Delivered with Detection\", Count = Deliv),\r\n (print o = 7, Name = \"    User/Admin Blocked\", Count = Blocked),\r\n (print o = 8, Name = \"    Clean Emails\", Count = Clean),\r\n (print o = 9, Name = \"Post-Delivery ZAP Removals\", Count = MalZap + PhishZap + SpamZap),\r\n (print o = 10, Name = \"    Removed by Malware ZAP\", Count = MalZap),\r\n (print o = 11, Name = \"    Removed by Phish ZAP\", Count = PhishZap),\r\n (print o = 12, Name = \"    Removed by Spam ZAP\", Count = SpamZap),\r\n (print o = 13, Name = \"User/Admin Reported\", Count = Adm + Usr),\r\n (print o = 14, Name = \"    Reported by Admins\", Count = Adm),\r\n (print o = 15, Name = \"    Reported by Users\", Count = Usr)\r\n| sort by o asc\r\n| extend [\"% of Inbound\"] = round(Count * 100.0 / Total, 1)\r\n| project Name, Count, [\"% of Inbound\"]", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Name", + "formatter": 1, + "formatOptions": { + "customColumnWidthSetting": "3fr" + } + }, + { + "columnMatch": "Count", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "3fr" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "% of Inbound", + "formatter": 3, + "formatOptions": { + "palette": "green", + "min": 0, + "max": 100, + "customColumnWidthSetting": "2fr" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "ProtectionView", + "comparison": "isEqualTo", + "value": "Table" + }, + "name": "query - option 1 grid", + "id": "5c0f0005-0a11-4b22-9c33-000000000005" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "title": "Total Emails", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| summarize Count = count()\r\n| extend Details = \"Total Inbound Emails\";", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Count", + "formatter": 4, + "formatOptions": { + "palette": "greenRed" + } + } + ] + }, + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1, + "formatOptions": { + "compositeBarSettings": { + "labelText": "" + } + } + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "blue", + "compositeBarSettings": { + "labelText": "" + } + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "chartSettings": { + "xAxis": "Count", + "createOtherGroup": 0 + }, + "mapSettings": { + "locInfo": "LatLong", + "sizeSettings": "Count", + "sizeAggregation": "Sum", + "legendMetric": "Count", + "legendAggregation": "Sum", + "itemColorSettings": { + "type": "heatmap", + "colorAggregation": "Sum", + "nodeColorField": "Count", + "heatmapPalette": "greenRed" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 1", + "id": "84e8d60b-7937-46f5-b2f4-a1a4adf06c9f" + } + ] + }, + "name": "Total Inbound", + "id": "1aeed046-9ea5-4583-b966-722847997fc7" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "title": "Filtering Totals", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where isnotempty(ThreatTypes) and EmailDirection == \"Inbound\" and DeliveryAction != 'Delivered'\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| summarize Count = count()\r\n| extend Details = \"Filtering Totals\";", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1, + "formatOptions": { + "compositeBarSettings": { + "labelText": "" + } + } + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "redDark", + "compositeBarSettings": { + "labelText": "" + } + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 1", + "id": "bae9a200-589f-4ca6-a3cf-f1110f644c49" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Total emails detected as Malware\r\nEmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| where ThreatTypes has ('Malware') and EmailDirection == \"Inbound\"\r\n| summarize Count= count()\r\n| extend Details = \"Emails Filtered as Malware\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "red" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 4", + "id": "0984d05b-fd2c-48e1-835f-41afc5a2385a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Total emails detected as Phish\r\nEmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| where ThreatTypes has \"Phish\" and not(ThreatTypes has \"Malware\") and EmailDirection == \"Inbound\" and DeliveryAction != 'Delivered'\r\n| summarize Count= count()\r\n| extend Details = \"Emails Filtered as Phish\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "orange" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 4", + "id": "ced2d054-76d1-40df-a412-0bc86a6c3336" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Total emails by detected as Spam\r\nEmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| where ThreatTypes == 'Spam' and EmailDirection == \"Inbound\" and DeliveryAction != 'Delivered'\r\n| summarize Count= count()\r\n| extend Details = \"Emails Filtered as Spam\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "yellow" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 4", + "id": "14456a0d-f5ac-46a0-a007-c72c7c40c58f" + } + ] + }, + "customWidth": "50", + "name": "group - 9", + "id": "d4e69885-f1b2-4c2b-85c2-188a6708dc4b" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "title": " ", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and DeliveryAction == 'Delivered'\r\n| where isnotempty(OrgLevelAction) or isnotempty(UserLevelAction)\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| summarize Count= count()\r\n| extend Details = \"Delivered with Detection\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "red" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "394d1ed4-7089-4291-bc80-f9948e3be6a9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\" and isempty(ThreatTypes) \r\n| where isnotempty(OrgLevelAction) or isnotempty(UserLevelAction)\r\n| where DeliveryAction != 'Delivered'\r\n| summarize Count= count()\r\n| extend Details = \"User/Admin Blocked\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "gray" + }, + "tooltipFormat": { + "tooltip": "Emails blocked from being delivered because of User or Admin overriddes" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "c29a2268-67d1-4958-a9a3-696384075987" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where isempty(ThreatTypes) and EmailDirection == \"Inbound\" and DeliveryAction == 'Delivered'\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| summarize Count= count()\r\n| extend Details = \"Clean Emails\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "gray" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "89a02ac7-971c-4672-bf5d-64709c479536" + } + ] + }, + "customWidth": "50", + "name": "group - 8", + "id": "761e74d4-279e-465f-ba47-5eeec4cf05d2" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "title": "Post-Delivery ZAP Removals", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailPostDeliveryEvents\r\n| where ActionResult == \"Success\"\r\n| where ActionType == \"Malware ZAP\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Removed by Malware ZAP\"\r\n", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "red" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "b06666bc-6ec0-49e7-a332-77e278d2320f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailPostDeliveryEvents\r\n| where ActionResult == \"Success\"\r\n| where ActionType == \"Phish ZAP\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Removed by Phish ZAP\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "orange" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "6fbac01b-0c42-46dc-8ca8-68e285593a45" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailPostDeliveryEvents\r\n| where ActionResult == \"Success\"\r\n| where ActionType == \"Spam ZAP\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Removed by Spam ZAP\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "yellow" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "7bd27a3b-be13-4ca0-9964-0f872f826b45" + } + ] + }, + "name": "Post Delivery", + "id": "4d20339e-5215-4edf-99d6-728cac183d16" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails reported by user and total emails reported by Admins as false positive or false negative detection\r\nCloudAppEvents\r\n| extend Record= (parse_json(RawEventData)).RecordType\r\n| extend SubmissionState = (parse_json(RawEventData)).SubmissionState,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Reported by Admins\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "palette": "none" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 3", + "id": "7490fa3a-e287-4fc3-b025-8772b9edb601" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails reported by user and total emails reported by Admins as false positive or false negative detection\r\nCloudAppEvents\r\n| extend Record= (parse_json(RawEventData)).RecordType\r\n| extend SubmissionState = (parse_json(RawEventData)).SubmissionState\r\n| where Record == 29 and ActionType == \"UserSubmission\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Reported by Users\"\r\n", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "palette": "none" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 2", + "id": "7af222dc-fd74-40ec-8ab7-741e179c07bf" + } + ] + }, + "name": "Reported", + "id": "8151e242-1c30-4550-ae9c-83f159e1a456" + } + ] + }, + "conditionalVisibility": { + "parameterName": "ProtectionView", + "comparison": "isEqualTo", + "value": "Tiles" + }, + "name": "Protection - Tiles view", + "id": "5c0f0103-0a11-4b22-9c33-000000000103" + }, + { + "type": 1, + "content": { + "json": "## Most Attacked Users
\r\n\r\n**The users most targeted by inbound email threats across all threat types (malware, phishing, and spam) in the selected period. Concentrated targeting of a few individuals is a strong signal of deliberate campaigns.**

**Recommended action:** Prioritise these users for security awareness training, tighter protection policies (for example the Strict preset), and closer monitoring - they are your highest-risk people." + }, + "name": "exec vap banner", + "id": "1fe431fb-cc96-4e81-b164-3a1a3823ebeb" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query surfaces the users most targeted by inbound email threats across all threat types (malware, phishing, spam) for the selected period, so SecOps can prioritise the highest-risk individuals. Similar to a \"Most Attacked People\" view.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| where isnotempty(ThreatTypes)\r\n| summarize\r\n ['Total Threats'] = count(),\r\n Malware = countif(ThreatTypes has \"Malware\"),\r\n Phish = countif(ThreatTypes has \"Phish\"),\r\n Spam = countif(ThreatTypes has \"Spam\"),\r\n ['Last Seen'] = max(Timestamp)\r\n by ['User']=RecipientEmailAddress\r\n| top 10 by ['Total Threats']\r\n| project ['User'], ['Total Threats'], Malware, Phish, Spam, ['Last Seen']", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Malware", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "145px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Phish", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "145px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Spam", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "145px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Total Threats", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "145px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "exec vap table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "2dfd91b1-b8d3-4a72-aaf4-a30a1886bed7" + }, + { + "type": 1, + "content": { + "json": "## Detection trend over time - grouped by {Granularity}\r\n**Represents total emails, total detections, total user submissions and admin email submissions over time summarizing the data per {Granularity} interval**" + }, + "name": "text - 14", + "id": "ddbbdaef-b374-42a8-821c-7fcd7ee53ba9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails, total detections, total user, and admin email submissions over time summarizing the data daily\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet scaffold = range Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran;\r\nlet baseQuery = materialize(EmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where isnotempty(Timestamp));\r\nlet sub = materialize(CloudAppEvents\r\n| extend Record = (parse_json(RawEventData)).RecordType, SubmissionContentType = tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29);\r\nlet zapbase = EmailPostDeliveryEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ActionResult == \"Success\"\r\n| where ActionType == \"Phish ZAP\" or ActionType == \"Malware ZAP\" or ActionType == \"Spam ZAP\";\r\nunion\r\n(scaffold | join kind=leftouter (baseQuery | where EmailDirection == \"Inbound\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Inbound Emails\"),\r\n(scaffold | join kind=leftouter (baseQuery | where ThreatTypes has ('Phish') | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Emails Detected as Phish\"),\r\n(scaffold | join kind=leftouter (baseQuery | where ThreatTypes has ('Malware') | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Emails Detected as Malware\"),\r\n(scaffold | join kind=leftouter (baseQuery | where ThreatTypes has ('Spam') | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Emails Detected as Spam\"),\r\n(scaffold | join kind=leftouter (baseQuery | where EmailDirection == \"Intra-org\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Intra-org Emails\"),\r\n(scaffold | join kind=leftouter (baseQuery | where EmailDirection == \"Outbound\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Outbound Emails\"),\r\n(scaffold | join kind=leftouter (baseQuery | where isnotempty(ThreatTypes) | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Emails with Threat\"),\r\n(scaffold | join kind=leftouter (sub | where ActionType == \"UserSubmission\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Emails Reported by Users\"),\r\n(scaffold | join kind=leftouter (zapbase | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Emails Removed by ZAP\"),\r\n(scaffold | join kind=leftouter (sub | where ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType == \"Mail\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Emails Reported by Admins\")", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp", + "seriesLabelSettings": [ + { + "seriesName": "Total Inbound Emails", + "label": "Inbound Emails", + "color": "green" + }, + { + "seriesName": "Total Emails with Threat", + "label": "Emails with Threat", + "color": "redDark" + }, + { + "seriesName": "Emails Detected as Phish", + "label": "Emails with Phish", + "color": "redBright" + }, + { + "seriesName": "Emails Detected as Malware", + "label": "Emails with Malware", + "color": "red" + }, + { + "seriesName": "Total Intra-org Emails", + "label": "Intra-org Emails", + "color": "greenDark" + }, + { + "seriesName": "Emails Detected as Spam", + "label": "Emails with Spam", + "color": "gray" + }, + { + "seriesName": "Total Outbound Emails", + "label": "Outbound Emails", + "color": "greenDarkDark" + }, + { + "seriesName": "Total Emails Removed by ZAP", + "label": "Emails ZAP-d", + "color": "orangeDark" + }, + { + "seriesName": "Total Emails Reported by Users", + "label": "User Reported Emails", + "color": "lightBlue" + }, + { + "seriesName": "Total Emails Reported by Admins", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 1", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "bcbefa48-f553-4290-acff-2691caf898ea" + }, + { + "type": 1, + "content": { + "json": "## Bad traffic (%) - Inbound Emails - grouped by {Granularity}\r\n**This represents bad traffic (% of emails with threats) compared to total inbound emails, summarized per {Granularity} interval over time.**" + }, + "name": "text - 15", + "id": "30761bcc-b1a5-45e2-8c0a-22388fbbf16c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises bad traffic (% of emails with threats) compared to total inbound emails over time summarising the data daily.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalEmailCount = count(),\r\n BadEmailCount = countif(isnotempty(ThreatTypes)) by bin(Timestamp, {Granularity})\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(BadEmailCount / todouble(TotalEmailCount) * 100, 2))\r\n| project Timestamp, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 0, + "aggregation": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 4", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "508036a8-d969-44c2-b2d2-c62d99999197" + } + ] + }, + "customWidth": "100", + "name": "group - Exec Protection Details", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "e6edeeeb-dcde-41d0-88c7-97ef773403b1" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Collaboration Protection Posture\r\n
\r\n\r\nMicrosoft Defender for Office 365 protects Microsoft Teams and collaboration, not only email. This snapshot shows Teams threat activity for the period.

**Recommended action:** Review the dedicated **Teams & Collaboration** tab for impersonation, malicious URLs, risky senders and file threats in Teams." + }, + "name": "exec collab banner", + "id": "3d78a6aa-51d4-4cab-93d1-26dff86fd667" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Headline Microsoft Teams / collaboration protection metrics for the executive summary, with per-interval sparklines so the collaboration threat trend is visible at a glance. Messages and URLs are counted per distinct Teams message.\r\nlet gran = {Granularity};\r\nlet me = materialize(MessageEvents);\r\nlet cae = materialize(CloudAppEvents | where ActionType == \"TeamsImpersonationDetected\");\r\nlet mui = materialize(MessageUrlInfo);\r\nlet uce = materialize(UrlClickEvents | where Workload == \"Teams\" and ActionType in (\"ClickBlocked\",\"ClickBlockedByTenantPolicy\"));\r\nlet fmc = materialize(FileMaliciousContentInfo | where Workload == \"MicrosoftTeams\");\r\nunion\r\n(me | summarize Count = dcount(TeamsMessageId) | extend Details = \"Teams Messages Scanned\", Ord = 1, Trend = toscalar(me | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(me | where isnotempty(ThreatTypes) | summarize Count = count() | extend Details = \"Teams Threat Messages\", Ord = 2, Trend = toscalar(me | where isnotempty(ThreatTypes) | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(cae | summarize Count = count() | extend Details = \"Teams Impersonation Detections\", Ord = 3, Trend = toscalar(cae | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(mui | summarize Count = dcount(TeamsMessageId) | extend Details = \"URLs Shared in Teams\", Ord = 4, Trend = toscalar(mui | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(uce | summarize Count = count() | extend Details = \"Malicious Clicks Blocked\", Ord = 5, Trend = toscalar(uce | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(fmc | summarize Count = count() | extend Details = \"Teams Files Scanned\", Ord = 6, Trend = toscalar(fmc | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(fmc | where isnotempty(ThreatTypes) | summarize Count = count() | extend Details = \"Malicious Teams Files\", Ord = 7, Trend = toscalar(fmc | where isnotempty(ThreatTypes) | make-series S = count() default = 0 on Timestamp step gran | project S))\r\n| sort by Ord asc\r\n| project Details, Count, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21 + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "exec collab tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3175aee5-56d2-4cb1-b1c3-75be683e6ffb" + } + ] + }, + "customWidth": "100", + "name": "group - Exec Collaboration Posture", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "39b0921f-fcef-49f4-8d52-0dcd1f33045b" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Emerging Threats\r\n
\r\n\r\n

With more sophisticated adversaries and new threats emerging frequently and prevalently, it's critical to be able to quickly identify and react to these threats.

\r\n\r\n[

🛡️Activity Profile: Email threat landscape

](https://security.microsoft.com/threatanalytics3/f186e4b0-28df-499a-901e-c64768b6d0dc/overview?filters=tags%253DPhishing)\r\n[

🛡️Activity Profile: Automated business email impersonation campaign uses parallel aging report and payroll diversion lures

](https://security.microsoft.com/threatanalytics3/3eb53378-892d-4695-a497-25d0a54181ee)\r\n[

🛡️Tool Profile: StealC

](https://security.microsoft.com/threatanalytics3/4d837c12-1db4-49c8-8466-219198d40b9b)\r\n[

🛡️OSINT Profile: UNC1151/Ghostwriter phishing campaign targeting Gmail accounts

](https://security.microsoft.com/threatanalytics3/b1a7e5e7-4b43-4758-8805-f714a131161a)\r\n[

🛡️Activity Profile: Encrypted message campaign targets real estate/financial sectors

](https://security.microsoft.com/threatanalytics3/651d669a-4721-42ab-bb96-509e94b5bfd9)\r\n\r\n
\r\n\r\nView all\r\n \r\n\r\n" + }, + "name": "text - 10", + "styleSettings": { + "margin": "0", + "padding": "0" + }, + "id": "0c781e85-af9a-41a6-9cf7-b3bb9a09d5d0" + } + ] + }, + "customWidth": "100", + "name": "group - Exec Emerging Threats", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "4f8886d3-882a-4c14-ab7f-a37bd302e32f" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Microsoft 365 Secure Email Gateway Performance\r\n
\r\n\r\n

Using multiple vendor email security products can offer diverse detections. However, our comprehensive end-to-end approach—spanning prevention, detection, posture, investigation, response, and user training—delivers a unified and effective defense that matches or exceeds the efficacy of siloed Secure Email Gateway solutions.

\r\n\r\n[

Learn more

](https://www.microsoft.com/en-us/security/blog/2026/06/15/microsoft-defender-email-security-benchmarking-key-insights-from-one-year-of-data/) \r\n\r\n
\r\n

High-severity email threats missed per 1,000 users protected - February–April 2026 (Microsoft Defender email security benchmarking)

" + }, + "name": "text - 12", + "id": "94c804f9-2860-4768-be59-fb31a4ff22d7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "datatable(Index:int, Name:string, Value:int)\r\n[\r\n 1, \"Defender for Office 365\", 194,\r\n 2, \"Mimecast\", 478,\r\n 3, \"ProofPoint\", 483,\r\n 4, \"HornetSecurity\", 813,\r\n 5, \"TrendMicro\", 1151,\r\n 6, \"IronPort\", 1274,\r\n 7, \"Barracuda\", 1585,\r\n 8, \"FireEye\", 2107\r\n]\r\n| project [\"Email security solution\"] = Name, [\"High-severity threats missed / 1K users\"] = Value\r\n| order by [\"High-severity threats missed / 1K users\"] asc\r\n", + "size": 0, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Email security solution", + "formatter": 1, + "formatOptions": { + "customColumnWidthSetting": "40%" + } + }, + { + "columnMatch": "High-severity threats missed / 1K users", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "min": 0, + "max": 2107, + "customColumnWidthSetting": "60%" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "useGrouping": true + } + } + } + ], + "rowLimit": 10, + "sortBy": [ + { + "itemKey": "High-severity threats missed / 1K users", + "sortOrder": 1 + } + ] + } + }, + "name": "query - 11", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e54fd5bd-17e2-40dc-897d-8a3bb21116ff" + } + ] + }, + "customWidth": "100", + "name": "group - Exec SEG Performance", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "1f3a7e2b-0a1f-48ba-9da3-e7531d500938" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "id": "ab3756d3-3f60-4024-9376-0f1a7d47ac13", + "type": 1, + "name": "text - 18", + "content": { + "json": "\r\n\r\n\r\n\r\n
Stay Current\r\n
\r\n\r\n
\r\n\r\n- **Threat Analytics (Defender XDR)** — live, tenant-specific threat intelligence and recommended actions: aka.ms/threatanalytics\r\n- **Microsoft Security Blog** — campaign write-ups and threat research: microsoft.com/security/blog\r\n- **Microsoft Defender for Office 365 Tech Community blog** — product updates and reporting guidance: Tech Community\r\n- **Latest features in Microsoft Defender for Office 365** — What's new in Microsoft Defender for Office 365 \r\n- **Share reporting feedback**: aka.ms/mdoreportingfeedback\r\n" + } + } + ] + }, + "customWidth": "100", + "name": "group - Exec Stay Current", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "5e22c565-cd2e-41f3-8d5a-0735af67c93f" + } + ], + "exportParameters": true + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "1" + }, + "name": "Detection Overview", + "styleSettings": { + "margin": "0", + "padding": "0" + }, + "id": "3f2cc277-9eb3-486d-a1f8-9fa5374a3d80" + }, + { + "type": 1, + "content": { + "json": "# Malware detection insights\r\n\r\n---\r\n\r\nThis tab provides insights into email message **detections** by Microsoft Defender for Office 365 where the message contained a **malware threat** (such as viruses, spyware, or ransomware) within its **URLs** or **attachments**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "text - 13", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "81f28ffc-b69e-4960-a61c-cac17a012ed6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//KPI summary of inbound email malware detections for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet mal = EmailEvents | where EmailDirection == \"Inbound\" | where ThreatTypes has \"Malware\";\r\nlet inbox = mal | where DeliveryLocation has \"Inbox\";\r\nlet malTrend = toscalar(mal | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet inboxTrend = toscalar(inbox | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(mal | summarize count()), Details = \"Malware Emails\", Ord = 1, Trend = malTrend),\r\n(print Count = toscalar(mal | summarize dcount(RecipientEmailAddress)), Details = \"Users Targeted\", Ord = 2, Trend = malTrend),\r\n(print Count = toscalar(mal | summarize dcount(SenderFromDomain)), Details = \"Sender Domains\", Ord = 3, Trend = malTrend),\r\n(print Count = toscalar(inbox | summarize count()), Details = \"Delivered to Inbox\", Ord = 4, Trend = inboxTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "malware kpi strip", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "20c06dd3-5025-4b2b-960e-ff012f5d2343" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Malware Detection Trends, Threat Classes, and Malware Names\r\n
\r\n\r\nThis section consolidates key visuals that track and explain malware detections in inbound email as identified by Microsoft Defender for Office 365 focusing on per-{Granularity} trend, threat classes and Malware types. \r\n

**Recommended action:** If malware volume spikes, confirm Safe Attachments (Block mode) is enabled for all users and investigate the top malware families below." + }, + "name": "text - 14", + "id": "1f09c6ec-b2de-4aa9-bd8e-81d11c92ebd4" + }, + { + "type": 1, + "content": { + "json": "### Malware Detection Trend\r\n**This visual displays a per-{Granularity} trend of email malware detections identified by Microsoft Defender for Office 365. The area chart summarises the number of messages flagged for malware threats.**" + }, + "name": "text - Malware Trend header", + "id": "e90b714f-de84-4571-9a60-b3b2f3bd09dd" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents \r\n| where ThreatTypes has \"Malware\" \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize MalwareDetections = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, MalwareDetections = coalesce(MalwareDetections, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "MalwareDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 0", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "350d0aa3-c093-4105-a150-c20111ac2912" + }, + { + "type": 1, + "content": { + "json": "### Malware Detection Trend - Advanced Threats\r\n**Not all threats are going to be easily recognisable, that's why Microsoft Defender for Office 365 has advanced threat detection methods, that use virtual sandbox environments to detonate URLs and Files. These virtual sandbox technologies look for known patterns, such as a recognisable login page in a URL, or a file accessing command and control infrastructure. This visual displays a per-{Granularity} trend of Malware detections of these advanced threats**" + }, + "name": "text - Malware Advanced Threats header", + "id": "12e07248-ada4-41d9-99cc-824eb65cff79" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections over time summarizing the data daily by Malware detection technologies/controls used for detecting unknown-unique malware.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Malware'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand MalwareMethod = ParsedMethods.Malware\r\n| where MalwareMethod in ('File detonation','URL detonation')\r\n| summarize Count = count() by MalwareMethod = tostring(MalwareMethod), Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct MalwareMethod | extend d = 1) on d | project Timestamp, MalwareMethod\r\n| join kind=leftouter (agg) on Timestamp, MalwareMethod\r\n| project Timestamp, MalwareMethod, Count = coalesce(Count, 0)\r\n| sort by MalwareMethod asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "File detonation", + "color": "redDark" + }, + { + "seriesName": "URL detonation", + "color": "orangeDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 9", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "ebcb6f29-02be-4dd0-b792-cd99285c29d4" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by Threat Classification\r\n**Summary of email messages detected by Microsoft Defender for Office 365 as malware, grouped by type of malware (Adware, Downloader, HackTool, Ransomware, Remote access trojan, Spyware).**" + }, + "customWidth": "33", + "name": "text - 15", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5638fc51-0830-4675-87d4-82f03df17bbf" + }, + { + "type": 1, + "content": { + "json": "### Top Attacked Users by Malware Threat Classification\r\n**Displays the recipient most frequently targeted for each malware type (Adware, Downloader, HackTool, Ransomware, Remote access trojan, Spyware) in inbound email detections.**" + }, + "customWidth": "33", + "name": "text - 15 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d2e3903b-4984-40da-a437-3d6a2b121e23" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by Threat Name\r\n**Summarises email messages flagged by Microsoft Defender for Office 365, grouped by specific malware names detected in URLs or attachments.**" + }, + "customWidth": "33", + "name": "text - 15 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6c0bebcf-9838-4385-ab3a-30db6c994284" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by threat classification of the malware threat in the message.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where ThreatTypes has 'Malware' and ThreatClassification has_any(\"Adware\",\"Downloader\",\"HackTool\",\"Ransomware\",\"Remote access trojan\",\"Spyware\")\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Count = count(Key) by ThreatClassification\r\n| sort by Count desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "query - 11", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "acb98530-8e3a-4383-b42f-8fd74b1c3fbe" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Malware detections in emails summarizing by various Threat classes showing the top attacked user for each threat classification type.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where ThreatTypes has \"Malware\" and EmailDirection == \"Inbound\" and ThreatClassification has_any(\"Adware\",\"Downloader\",\"HackTool\",\"Ransomware\",\"Remote access trojan\",\"Spyware\")\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize EmailCount=count() by ThreatClassification, RecipientEmailAddress\r\n| summarize Count = arg_max(EmailCount, RecipientEmailAddress) by ThreatClassification\r\n| sort by Count desc\r\n| project ['Threat Classification'] = ThreatClassification, ['Top Recipient'] = RecipientEmailAddress, ['Emails'] = Count", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "TopEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "statSettings": { + "valueField": "RecipientEmailAddress", + "valueAggregation": "None", + "colorSettings": { + "type": "static", + "mode": "background", + "heatmapPalette": "greenRed", + "thresholdsGrid": [] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "tagText": "", + "valueFontStyle": "auto" + }, + "chartSettings": { + "xAxis": "RecipientEmailAddress" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 5 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d9b46c97-91ce-4d64-aca6-3126ac49c0ff" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by ThreatNames of the malware detected.\r\nEmailEvents \r\n| where isnotempty(ThreatNames) and ThreatTypes has \"Malware\" \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| mv-expand ThreatName = split(ThreatNames, \",\") to typeof(string)\r\n| where isnotempty(ThreatName)\r\n| distinct Key, ThreatName\r\n| summarize Count = count() by ThreatName\r\n| top 15 by Count\r\n| project ['Threat Name'] = ThreatName, Count", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Count", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "xAxis": "ThreatNames", + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 3", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b9a4b34f-f54f-4d6e-bb20-81925d0f5540" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "group - 3", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "82853a93-e11f-4e4a-80f4-733850a1d3ff" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Malware Detections by Delivery Location, Detection Technology and Sender Infrastructure Insights\r\n
\r\n\r\nThis section consolidates key visuals that track and explain malware detections delivery locations, detection technologies used for detections, sender infrastructure insights in inbound email identified by Microsoft Defender for Office 365 as Malware. \r\n

**Recommended action:** For sender IPs or countries you do not do business with, consider connection filtering or geo-based rules; verify the detection technologies catching these are enabled." + }, + "name": "banner - Malware Delivery Detection Sender", + "id": "cba6403d-e2b1-4fe8-af52-57e5c2aa8e54" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by delivery location\r\n**Visualizes counts (per {Granularity}) of malware detections of inbound emails by delivery location: Quarantine or Failed (rejected with or without NDR)**" + }, + "name": "text - Malware Delivery Location header", + "id": "95be7f48-40eb-4154-91d8-20f7033f2ff5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections over time summarizing the data daily by Delivery Location\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Malware' and EmailDirection == 'Inbound'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalMalwareDetections=count(), Quarantine=countif(DeliveryLocation == 'Quarantine'), Failed=countif(DeliveryLocation == 'Failed') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, TotalMalwareDetections=coalesce(TotalMalwareDetections,0), Quarantine=coalesce(Quarantine,0), Failed=coalesce(Failed,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "TotalMalwareDetections", + "color": "blue" + }, + { + "seriesName": "Quarantine", + "color": "orangeDark" + }, + { + "seriesName": "Failed", + "color": "redDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 10", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b2c19e58-2123-490b-9631-c0b238c582e6" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by Detection Technology\r\n**Visualizes counts (per {Granularity}) of Malware detections of inbound emails by various Microsoft Defender for Office 365 detection technologies.**" + }, + "name": "text - Malware Detection Technology header", + "id": "f3c2691e-4f32-4109-9524-8a11719e4425" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections over time summarizing the data daily by various Malware detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Malware'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand MalwareMethod = ParsedMethods.Malware\r\n| summarize Count = count() by MalwareMethod = tostring(MalwareMethod), Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct MalwareMethod | extend d = 1) on d | project Timestamp, MalwareMethod\r\n| join kind=leftouter (agg) on Timestamp, MalwareMethod\r\n| project Timestamp, MalwareMethod, Count = coalesce(Count, 0)\r\n| sort by MalwareMethod asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 8", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f00c1ce0-e55e-44c0-8bf0-4af662ccef89" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by various Malware detection technologies/controls in Microsoft Defender for Office 365.\r\nEmailEvents \r\n| where DetectionMethods has 'Malware'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand MalwareMethod = ParsedMethods.Malware\r\n| summarize Count = count() by MalwareMethod = tostring(MalwareMethod)\r\n| sort by Count desc\r\n| project ['Detection Technology'] = MalwareMethod, ['Detections'] = Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "34", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 2", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "590880a9-1cf7-44ae-b4de-2f65bc700b5d" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by SenderIPv4 Geo Location\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Malware, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" + }, + "name": "text - Malware Geo Location header", + "id": "19d78b48-af58-4bee-abfe-57efb1eba125" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by email sender IP address (SenderIPv4).\r\nEmailEvents \r\n| where ThreatTypes has 'Malware' and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_", + "size": 0, + "showAnalytics": true, + "title": "Malware Detections-Sender Heatmap (IPv4)", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "map", + "gridSettings": { + "sortBy": [ + { + "itemKey": "count_", + "sortOrder": 2 + } + ] + }, + "sortBy": [ + { + "itemKey": "count_", + "sortOrder": 2 + } + ], + "mapSettings": { + "locInfo": "LatLong", + "locInfoColumn": "GeoInfo", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "none" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 1", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8cb46ec0-ac2a-41d1-bf8a-0b8585d1fefc" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where ThreatTypes has 'Malware' and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Malware Emails'] = count_\r\n| sort by ['Malware Emails'] desc\r\n\r\n\r\n", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Malware Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "mapSettings": { + "locInfo": "LatLong", + "locInfoColumn": "GeoInfo", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "heatmap", + "heatmapPalette": "red" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 1 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b6a0355a-2b8f-48a5-8edc-58f4f7f8180a" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "Malware-Detectiontech-Deliverylocation-SendingInfra", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "2692cb5e-825c-45c1-bd3a-096b55e8d760" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Malware Detections Top attacked users and top senders\r\n
\r\n\r\nThis section consolidates key visuals that track and explain malware detections in inbound email as identified by Microsoft Defender for Office 365 focusing on top attacked users and top senders. \r\n

**Recommended action:** Apply the Strict preset security policy to the most-attacked users and consider adding persistent malicious sender domains to the Tenant Allow/Block List." + }, + "name": "banner - Malware Top Users Senders", + "id": "bc5b37a4-71e4-4a2f-b0ba-b3dd87333391" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections top attacked users\r\n**Displays the top 10 recipient email addresses that received inbound emails flagged as Malware. These users may be at higher risk and should be prioritised for targeted cybersecurity awareness training. Training should cover the specific threat types and techniques they are exposed to, and reinforce best practices for promptly reporting any suspicious messages that might bypass security controls and reach their inbox.**" + }, + "customWidth": "100", + "name": "text - Malware Top Users header", + "id": "cb87a026-ad03-45cc-887e-ab460490d9a5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails with Malware detections summarizing the data by the top 15 recipient email address (RecipientEmailAddress).\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),MalwareEmailCount = countif(ThreatTypes has \"Malware\") by RecipientEmailAddress\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(MalwareEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| where MalwareEmailCount !=0\r\n| top 15 by MalwareEmailCount\r\n| project ['Recipient'] = RecipientEmailAddress, ['Malware Emails'] = MalwareEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Malware Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - Malware Top Recipients", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e7ffef62-f85e-4188-8ab9-d90a5c666c30" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains with Malware Detections (Inbound)\r\n**Displays the top 10 sender domains sending inbound emails detected as Malware. Helps identify external sources most frequently associated with malicious content for prioritised threat monitoring and mitigation.**" + }, + "customWidth": "100", + "name": "text - Malware Top Senders header", + "id": "93390807-25b2-4bea-9648-98e821da8ec6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by the top 15 email sender P2 domain (SenderFromDomain). Adding additional insights for total inbound emails and bad traffic percentage for each sender domain.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount = count(), MalwareEmailCount = countif(ThreatTypes has \"Malware\") by SenderFromDomain\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(MalwareEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| where MalwareEmailCount !=0\r\n| top 15 by MalwareEmailCount\r\n| project ['Sender Domain'] = SenderFromDomain, ['Malware Emails'] = MalwareEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Malware Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal", + "useGrouping": false + } + } + }, + { + "columnMatch": "BadEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - Malware Top Sender Domains", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "eaa45734-2df2-4a5e-b35b-1295e00cb46f" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "MalwareTopAttackedUser-TopSenders", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "4e0900ab-e7e4-4cf1-93a4-7e86bca20782" + }, + { + "type": 1, + "content": { + "json": "# Phishing Detection Insights\r\n\r\n---\r\nThis tab provides insights into email message **detections** by Microsoft Defender for Office 365 where the message contained a **Phishing threat** within its **email content**, **URLs**, or **attachments**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "text - 24", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "fe82d665-fa9e-4fc2-9ba9-7e2eabb9a04b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//KPI summary of inbound email phishing detections for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet ph = EmailEvents | where EmailDirection == \"Inbound\" | where ThreatTypes has \"Phish\";\r\nlet inbox = ph | where DeliveryLocation has \"Inbox\";\r\nlet phTrend = toscalar(ph | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet inboxTrend = toscalar(inbox | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(ph | summarize count()), Details = \"Phish Emails\", Ord = 1, Trend = phTrend),\r\n(print Count = toscalar(ph | summarize dcount(RecipientEmailAddress)), Details = \"Users Targeted\", Ord = 2, Trend = phTrend),\r\n(print Count = toscalar(ph | summarize dcount(SenderFromDomain)), Details = \"Sender Domains\", Ord = 3, Trend = phTrend),\r\n(print Count = toscalar(inbox | summarize count()), Details = \"Delivered to Inbox\", Ord = 4, Trend = inboxTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "phish kpi strip", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5debf0b8-4384-485b-8a7f-71ead592718a" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Phishing Detection Trend, LLM Content Analysis, Advanced Threats, and Threat Classes\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Phish detections in inbound email as identified by Microsoft Defender for Office 365 focusing on per-{Granularity} trends, advanced threat detections, LLM-based content analysis, and threat classes.

**Recommended action:** Review the LLM-classified phishing themes; enable Safe Links and impersonation protection, and prioritise awareness training on the dominant lure types." + }, + "name": "text - Phish Section1 Banner", + "id": "ce5e489f-c83b-4bc8-9e63-b08dfb5ef31f" + }, + { + "type": 1, + "content": { + "json": "### Phish Detection Trend
\r\n\r\n**This visual displays a per-{Granularity} trend of email Phish detections identified by Microsoft Defender for Office 365. The area chart summarises the number of messages flagged for Phish threats.**" + }, + "name": "text - Phish Trend Header", + "id": "429ef4d2-61a9-40d0-940f-2212ddce22ce" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections over time summarizing the data daily.\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has \"Phish\"\r\n| summarize PhishDetections = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, PhishDetections = coalesce(PhishDetections, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "PhishDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b0d170ec-331c-4ad0-8ce6-258704cc5345" + }, + { + "type": 1, + "content": { + "json": "### Phish Detection Trend - Advanced Threats
\r\n\r\n**Not all threats are easily recognizable, which is why Microsoft Defender for Office 365 uses advanced detection methods, including virtual sandbox environments to detonate URLs and files. These virtual sandbox technologies look for known patterns, such as a recognisable login page in a URL, or a file accessing command and control infrastructure. This visual displays a per-{Granularity} trend of Phish detections of these advanced threats.**" + }, + "name": "text - Phish AdvThreats Header", + "id": "425476e0-066a-42ee-afb9-5dabc612a3c8" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections over time summarizing the data daily by Phish detection technologies/controls used for detecting unknown-unique phish.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| project Timestamp, RecipientEmailAddress, NetworkMessageId, DT=parse_json(DetectionMethods)\r\n| evaluate bag_unpack(DT)\r\n| summarize [\"File detonation\"]=countif(Phish has 'File detonation' and Phish !has 'File detonation reputation'), [\"URL detonation\"]=countif(Phish has 'URL detonation' and Phish !has 'URL detonation reputation') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, [\"File detonation\"]=coalesce([\"File detonation\"],0), [\"URL detonation\"]=coalesce([\"URL detonation\"],0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "URL detonation", + "color": "orangeDark" + }, + { + "seriesName": "File detonation", + "color": "redDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish AdvThreats Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6b62347a-b162-49e6-891c-07697af22dd9" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - LLM content analysis
\r\n\r\n**Microsoft Defender for Office 365 uses Language AI for Phish and Business Email Compromise (BEC) detection. These models are progressively learning from thousands of real-world phishing attempts and analyzing all messages classified as phish. Furthermore, it incorporates advanced Machine Learning and Natural Language Processing (NLP) techniques to read, process, and understand email content the way a human analyst might, yet in a fraction of the time and at a large scale. [Learn more](https://techcommunity.microsoft.com/blog/microsoftdefenderforoffice365blog/microsoft-defender-for-office-365s-language-ai-for-phish-enhancing-email-securit/4410446)**" + }, + "customWidth": "50", + "name": "text - Phish LLM Content Header", + "id": "c23460b1-e025-4f6c-b2d5-3f78c0c9afc6" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - LLM Threat Classifications
\r\n\r\n**Microsoft Defender for Office 365 uses purpose-built Large Language Models (LLM) at scale to provide AI-powered email and collaboration security. Our solution now parses language to understand and identify attacker intent and classifies threats at machine speed – keeping malicious emails out of your inbox and giving security operations (SOC) teams a new level of insight into adversary techniques. [Learn more](https://techcommunity.microsoft.com/blog/microsoftdefenderforoffice365blog/microsoft-ignite-redefining-email-security-with-llms-to-tackle-a-new-era-of-soci/4302421)**" + }, + "customWidth": "50", + "name": "text - Phish LLM ThreatClass Header", + "id": "1d723c26-501f-4385-9331-957ab7ae5019" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails detected as Phish by LLM content analysis detection technology in Microsoft Defender for Office 365. \r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has 'Phish' and DetectionMethods contains \"LLM content analysis\"\r\n| summarize count()\r\n| sort by count_ desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "statSettings": { + "valueAggregation": "None", + "colorSettings": { + "type": "thresholds", + "mode": "foreground", + "thresholdsGrid": [ + { + "operator": ">", + "thresholdValue": "0", + "representation": "red" + }, + { + "operator": "<=", + "thresholdValue": "0", + "representation": "red" + } + ] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "tagText": "", + "valueFontStyle": "auto", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish LLM Content Count", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "86a301c5-2bc0-436a-982c-861beee7c9ab" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by intent of the message.\r\n// Microsoft Defender for Office 365 LLM analysis is analyzing email messages to understand the intent of the messages. These threat classifications are then used in filtering decisions.\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has 'Phish' and ThreatClassification has_any(\"Business intelligence\",\"Contact establishment\",\"Gift card\",\"Invoice\",\"Payroll\",\"PII gathering\",\"Task\")\r\n| summarize count() by ThreatClassification\r\n| sort by count_ desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish LLM ThreatClass Pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d547b730-f174-4f78-8998-02f24453304e" + }, + { + "type": 1, + "content": { + "json": "### Top Attacked Users by LLM Threat classes (Phish)
\r\n\r\n**Displays recipients most frequently targeted by inbound phishing emails, grouped by threat classification (e.g., Gift Card, Invoice, Payroll). Helps identify users at higher risk for phishing attacks. These users may be at higher risk and should be prioritised for targeted cybersecurity awareness training. Training should cover the specific threat types and techniques they are exposed to, and reinforce best practices for promptly reporting any suspicious messages that might bypass security controls and reach their inbox.**" + }, + "customWidth": "100", + "name": "text - Phish LLM TopUsers Header", + "id": "4ba9d9eb-d88d-4e5d-ba58-a740559677f7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Phish detections in emails summarizing by various Threat classes showing the top attacked user for each threat classification type.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has \"Phish\" and EmailDirection == \"Inbound\" and ThreatClassification has_any(\"Business intelligence\",\"Contact establishment\",\"Gift card\",\"Invoice\",\"Payroll\",\"PII gathering\",\"Task\")\r\n| summarize EmailCount=count() by ThreatClassification, RecipientEmailAddress\r\n| summarize Emails = arg_max(EmailCount, RecipientEmailAddress) by ThreatClassification\r\n| sort by Emails desc\r\n| project ['Threat Classification'] = ThreatClassification, ['Top Recipient'] = RecipientEmailAddress, ['Emails'] = Emails", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "80px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish LLM TopUsers", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "51599ab2-db69-4195-b4e9-2828729ec35b" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "group - 5", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "25c47f6a-3525-435e-90cf-357f02fb2fed" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Phish Detections by Delivery location, Detection technology and Sender infrastructure insights\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Phish detections delivery locations, detection technologies used for detections, sender infrastructure insights in inbound email identified by Microsoft Defender for Office 365 as Phish.

**Recommended action:** Verify anti-phishing and Safe Links policies cover these delivery paths; consider blocking sender infrastructure from regions you do not operate in, where appropriate." + }, + "name": "text - Phish Section2 Banner", + "id": "6876063e-6a4f-48ea-829d-4486922783dd" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections by delivery location
\r\n\r\n**Visualizes counts (per {Granularity}) of Phish detections of inbound emails by various delivery locations: Quarantine, Junk folder or Failed (rejected with or without NDR)**" + }, + "name": "text - Phish DeliveryLoc Header", + "id": "b5045aab-1b4b-4d35-af41-a6315d36e864" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections over time summarizing the data daily by Delivery Location.\r\n//The comment in the query excludes deliveries to the SecOps Mailboxes and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\" and EmailDirection == \"Inbound\"\r\n| summarize TotalPhishDetections=count(), Quarantine=countif(DeliveryLocation == \"Quarantine\"), Junkfolder=countif(DeliveryLocation == \"Junk folder\"), Inbox=countif(DeliveryLocation == \"Inbox/folder\"), Failed=countif(DeliveryLocation == \"Failed\"), Dropped=countif(DeliveryLocation == \"Dropped\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, TotalPhishDetections=coalesce(TotalPhishDetections,0), Quarantine=coalesce(Quarantine,0), Junkfolder=coalesce(Junkfolder,0), Inbox=coalesce(Inbox,0), Failed=coalesce(Failed,0), Dropped=coalesce(Dropped,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Quarantine", + "color": "greenDark" + }, + { + "seriesName": "Failed", + "color": "green" + }, + { + "seriesName": "Dropped", + "color": "green" + }, + { + "seriesName": "Junk folder", + "color": "orangeDark" + }, + { + "seriesName": "Inbox", + "color": "redBright" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish DeliveryLoc Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e839848c-d176-4251-bbb4-1c2e1103ed2d" + }, + { + "type": 1, + "content": { + "json": "### Phish detections by Detection Technology
\r\n\r\n**Visualizes counts (per {Granularity}) of Phish detections of inbound emails by various Microsoft Defender for Office 365 detection technologies.**" + }, + "name": "text - Phish DetTech Header", + "id": "149bf1b3-80cc-4e82-ae5d-ddee0f6b0cd9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections over time summarizing the data daily by various Phish Detection technologies/controls in Microsoft Defender for Office 365.\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "createOtherGroup": 15 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish DetTech Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b0b16329-e1a6-4138-871e-76d57a60b978" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarized by individual Phish detection technology/control in Microsoft Defender for Office 365.\r\n//Each detection technology is counted individually via mv-expand over DetectionMethods.Phish (matching the sibling trend line chart), so a message flagged by multiple techniques counts once per technique.\r\n//The where clause excludes deliveries to the SecOps Mailbox and by the Phish Simulation system.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details\r\n| sort by Count desc\r\n| project ['Detection Technology'] = Details, ['Detections'] = Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish DetTech Pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5270ba04-599f-4940-805b-687f7475bc70" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections by SenderIPv4 Geo Location
\r\n\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Phish, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" + }, + "name": "text - Phish Geo Header", + "id": "ddd0c12f-1bb1-4d7d-afb4-f28bcfcd7c4b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by email sender IP address (SenderIPv4).\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has \"Phish\" and isnotempty(SenderIPv4)\r\n| summarize count() by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "map", + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "none" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish Geo Map", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "85ea7223-7d77-43f5-b0d9-e0de7c898758" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where ThreatTypes has 'Phish' and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Phish Emails'] = count_\r\n| sort by ['Phish Emails'] desc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Phish Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "heatmap", + "heatmapPalette": "red" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish Country Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f561209b-15a6-442e-af10-63e375088209" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "group - 25- Phish delivery locations-detecion tech-sender infra", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "10f3e3eb-b330-4955-952e-01eff69405e9" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Phish Detections Top attacked users and top senders\r\n
\r\n\r\nThis section consolidates key visuals that track and explain phish detections in inbound email as identified by Microsoft Defender for Office 365 focusing on top attacked users and top senders.

**Recommended action:** Enroll the most-targeted users in security awareness training and consider blocking persistent phishing sender domains." + }, + "name": "text - Phish Section3 Banner", + "id": "f46ed4a8-e2b5-4ccd-ae38-efc571bfc791" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections top attacked users\r\n**Displays the top 10 recipient email addresses that received inbound emails flagged as Phish. These users may be at higher risk and should be prioritised for targeted cybersecurity awareness training. Training should cover the specific threat types and techniques they are exposed to, and reinforce best practices for promptly reporting any suspicious messages that might bypass security controls and reach their inbox.**" + }, + "customWidth": "100", + "name": "text - Phish TopUsers Header", + "id": "96d9b543-070a-42d4-bbed-3f5cf79ca7ce" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails with Phish detections summarizing the data by the top 15 recipient email address (RecipientEmailAddress).\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),PhishEmailCount = countif(ThreatTypes has \"Phish\") by RecipientEmailAddress\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(PhishEmailCount / todouble(TotalEmailCount) * 100, 2))\r\n| where PhishEmailCount !=0\r\n| top 15 by PhishEmailCount\r\n| project ['Recipient'] = RecipientEmailAddress, ['Phish Emails'] = PhishEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Phish Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish TopRecipients Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "25100115-78d3-4144-b44e-613b44f02484" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains with Phish Detections (Inbound)\r\n**Displays the top 10 sender domains sending inbound emails detected as Phish. Helps identify external sources most frequently associated with malicious content for prioritised threat monitoring and mitigation.**" + }, + "customWidth": "100", + "name": "text - Phish TopSenders Header", + "id": "e7fcb7fe-4bca-4153-a9b0-8ded135b1c64" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by the top 15 email sender P2 domain (SenderFromDomain), now including the Phish confidence split (High/Normal) and the aggregated phish detection methods seen per domain. Adding additional insights for total inbound emails and bad traffic percentage for each sender domain.\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where EmailDirection == \"Inbound\"\r\n| extend PhishConf = tostring(parse_json(ConfidenceLevel).Phish)\r\n| extend PhishMethods = parse_json(DetectionMethods).Phish\r\n| summarize TotalEmailCount = count(),\r\n PhishEmailCount = countif(ThreatTypes has \"Phish\"),\r\n Phish_High = countif(ThreatTypes has \"Phish\" and PhishConf == \"High\"),\r\n Phish_Normal = countif(ThreatTypes has \"Phish\" and PhishConf == \"Normal\"),\r\n PhishMethodSet = make_set_if(PhishMethods, ThreatTypes has \"Phish\") by SenderFromDomain\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(PhishEmailCount / todouble(TotalEmailCount) * 100, 2))\r\n| where PhishEmailCount != 0\r\n| top 15 by PhishEmailCount\r\n| mv-apply S = PhishMethodSet on ( mv-expand m = S to typeof(string) | summarize Methods = make_set(m) )\r\n| project ['Sender Domain'] = SenderFromDomain, ['Phish Emails'] = PhishEmailCount, ['Phish (High)'] = Phish_High, ['Phish (Normal)'] = Phish_Normal, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound, ['Detection Methods'] = strcat_array(Methods, \", \")", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Phish Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish (High)", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish (Normal)", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "BadEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish TopSenders Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "717bfce8-b5d4-4900-99db-4ba0c503591d" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "group - 26-PhishDetectionsTopattackedusers-topsenders", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "553afca2-caa1-45b1-bec0-dca426b5be46" + }, + { + "type": 1, + "content": { + "json": "# Spam Detection Insights\r\n\r\n---\r\nThis tab provides insights into email message **detections** by Microsoft Defender for Office 365 where the message contained a **Spam threat** within its **email content**, **URLs**, or **attachments**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "4" + }, + "name": "text - Spam Tab Intro", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a693a05a-a772-4ac4-9863-07ad0d1b7092" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//KPI summary of inbound email spam detections for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet sp = EmailEvents | where EmailDirection == \"Inbound\" | where ThreatTypes has \"Spam\";\r\nlet junk = sp | where DeliveryLocation has \"Junk\";\r\nlet spTrend = toscalar(sp | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet junkTrend = toscalar(junk | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(sp | summarize count()), Details = \"Spam Emails\", Ord = 1, Trend = spTrend),\r\n(print Count = toscalar(sp | summarize dcount(RecipientEmailAddress)), Details = \"Users Targeted\", Ord = 2, Trend = spTrend),\r\n(print Count = toscalar(sp | summarize dcount(SenderFromDomain)), Details = \"Sender Domains\", Ord = 3, Trend = spTrend),\r\n(print Count = toscalar(junk | summarize count()), Details = \"Sent to Junk\", Ord = 4, Trend = junkTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "4" + }, + "name": "spam kpi strip", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "cadd5331-1db8-4ac8-bc99-42cd5227ee51" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Spam Detection Effectiveness and Trends\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Spam detections in inbound email as identified by Microsoft Defender for Office 365 focusing on Effectiveness and per-{Granularity} trend. For effectiveness, we consider messages reported by your admins and decisions made post-delivery.

**Recommended action:** If legitimate mail is marked as spam, review the Spam and Bulk thresholds; if spam is leaking through, tighten them." + }, + "name": "text - Spam Section1 Banner", + "id": "1093f3b6-cea7-4f54-9029-f9aadd79ca9f" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query calculates the effectiveness of spam detections without edge data.\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\n// baseQuery _FN_Admin_Submissions_SPM\r\nlet _FN_Admin_Submissions_SPM = toscalar(\r\nCloudAppEvents\r\n| where Timestamp between (minTime .. maxTime)\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType)\r\n| extend NetworkMessageId = tostring((parse_json(RawEventData)).ObjectId)\r\n| where SubmissionType in (\"0\")\r\n| summarize count()\r\n);\r\n// baseQuery _FN_ZAP_Successful_Spam\r\nlet _FN_ZAP_Successful_Spam = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and ActionType == \"Spam ZAP\" and ActionResult == \"Success\" and Timestamp between (minTime .. maxTime)\r\n| summarize count()\r\n //Take all our Spam ZAP, and count how many messages we missed and successfully cleaned up.\r\n);\r\n// baseQuery _FN_ZAP_Unsuccessful_Spam\r\nlet _FN_ZAP_Unsuccessful_Spam = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and ActionType == \"Spam ZAP\" and ActionResult != \"Success\" and Timestamp between (minTime .. maxTime)\r\n| summarize count()\r\n//Take all our Spam ZAP, and count how many messages we failed to clean up due to error or users/admins/API vendors getting to the message first.\r\n);\r\n// baseQuery _SPAM_ZAP_FP\r\nlet _SPAM_ZAP_FP = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and Action has_any (\"Redelivery\",\"Reprocessed\") and Timestamp between (minTime .. maxTime)\r\n| join kind=leftsemi (\r\n EmailEvents\r\n | where Timestamp between (minTime ..maxTime )\r\n | where ThreatTypes contains \"Spam\"\r\n | project NetworkMessageId, ThreatTypes)\r\n on NetworkMessageId\r\n| summarize count()\r\n// count all the FPs which were originally Spam, and when we TT'd them were not so we can subtract that from our mailfow catch, and therefore the total true bad.\r\n);\r\n// baseQuery _Spam_Mailflow\r\nlet _Spam_Mailflow = toscalar(\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and ThreatTypes == \"Spam\" and Timestamp between (minTime .. maxTime)\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count()\r\n// Get all the mailflow detected as SPM, then count all the NMIDs (not distinct)\r\n);\r\nprint\r\nEffectiveness_PostDelivery = abs(round(((toreal(toscalar(_FN_Admin_Submissions_SPM))+toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)))/(toreal(toscalar(_Spam_Mailflow))+toreal(toscalar(_FN_ZAP_Successful_Spam))+toreal(toscalar(_FN_ZAP_Unsuccessful_Spam))+toreal(toscalar(_FN_Admin_Submissions_SPM))-toreal(toscalar(_SPAM_ZAP_FP)))*100-100),2))", + "size": 1, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "statSettings": { + "valueAggregation": "None", + "colorSettings": { + "type": "thresholds", + "mode": "foreground", + "heatmapPalette": "greenRed", + "thresholdsGrid": [ + { + "operator": ">", + "thresholdValue": "95", + "representation": "green" + }, + { + "operator": "<=", + "thresholdValue": "95", + "representation": "orange" + }, + { + "operator": "<=", + "thresholdValue": "90", + "representation": "red" + } + ] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "numberFormatSettings": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "tagText": "Spam Effectiveness (without Edge data)", + "valueFontStyle": "superLarge", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Effectiveness Stat", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "036851c1-489e-4fda-8059-850c161578b3" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\n// baseQuery _FN_Admin_Submissions_SPM\r\nlet _FN_Admin_Submissions_SPM = toscalar(\r\nCloudAppEvents\r\n| where Timestamp between (minTime .. maxTime)\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType)\r\n| extend NetworkMessageId = tostring((parse_json(RawEventData)).ObjectId)\r\n| where SubmissionType in (\"0\")\r\n| summarize count()\r\n);\r\n// baseQuery _FN_ZAP_Successful_Spam\r\nlet _FN_ZAP_Successful_Spam = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and ActionType == \"Spam ZAP\" and ActionResult == \"Success\" and Timestamp between (minTime .. maxTime)\r\n| summarize count()\r\n //Take all our Spam ZAP, and count how many messages we missed and successfully cleaned up.\r\n);\r\n// baseQuery _FN_ZAP_Unsuccessful_Spam\r\nlet _FN_ZAP_Unsuccessful_Spam = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and ActionType == \"Spam ZAP\" and ActionResult != \"Success\" and Timestamp between (minTime .. maxTime)\r\n| summarize count()\r\n//Take all our Spam ZAP, and count how many messages we failed to clean up due to error or users/admins/API vendors getting to the message first.\r\n);\r\n// baseQuery _SPAM_ZAP_FP\r\nlet _SPAM_ZAP_FP = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and Action has_any (\"Redelivery\",\"Reprocessed\") and Timestamp between (minTime .. maxTime)\r\n| join kind=leftsemi (\r\n EmailEvents\r\n | where Timestamp between (minTime ..maxTime )\r\n | where ThreatTypes contains \"Spam\"\r\n | project NetworkMessageId, ThreatTypes)\r\n on NetworkMessageId\r\n| summarize count()\r\n// count all the FPs which were originally Spam, and when we TT'd them were not so we can subtract that from our mailfow catch, and therefore the total true bad.\r\n);\r\n// baseQuery _Spam_Mailflow\r\nlet _Spam_Mailflow = toscalar(\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and ThreatTypes == \"Spam\" and Timestamp between (minTime .. maxTime)\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count()\r\n// Get all the mailflow detected as SPM, then count all the NMIDs (not distinct)\r\n);\r\nprint StatisticName=\"Spam Mailflow Minus FPs\", Value=toreal((toscalar(_Spam_Mailflow)) - toreal(toscalar(_SPAM_ZAP_FP)))\r\n| union (print StatisticName=\"Spam Admin FNs Submitted\", Value=toreal(toscalar(_FN_Admin_Submissions_SPM)))\r\n| union (print StatisticName=\"Spam FPs Reverse Zapped\", Value=toreal(toscalar(_SPAM_ZAP_FP)))\r\n| union (print StatisticName=\"Spam Zapped Successfully\", Value=toreal(toscalar(_FN_ZAP_Successful_Spam)))\r\n| union (print StatisticName=\"Spam NotZapped\", Value=toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)))\r\n| union (print StatisticName=\"Spam Effectiveness Post Delivery %\", Value=abs(round(((toreal(toscalar(_FN_Admin_Submissions_SPM)) + toreal(toscalar(_FN_ZAP_Unsuccessful_Spam))) / (toreal(toscalar(_Spam_Mailflow)) + toreal(toscalar(_FN_ZAP_Successful_Spam)) + toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)) + toreal(toscalar(_FN_Admin_Submissions_SPM)) - toreal(toscalar(_SPAM_ZAP_FP)))) * 100 - 100, 2)))\r\n| union (print StatisticName=\"Spam Effectiveness Pre-Delivery %\", Value=abs(round(((toreal(toscalar(_FN_Admin_Submissions_SPM)) + toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)) + (toscalar(_FN_ZAP_Successful_Spam))) / (toreal(toscalar(_Spam_Mailflow)) + toreal(toscalar(_FN_ZAP_Successful_Spam)) + toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)) + toreal(toscalar(_FN_Admin_Submissions_SPM)) - toreal(toscalar(_SPAM_ZAP_FP)))) * 100 - 100, 2 )))\r\n| project ['Statistic'] = StatisticName, Value", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "tileSettings": { + "showBorder": false, + "titleContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Value", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Value", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 2 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Effectiveness Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8d456ea2-f04a-4d71-95c6-fbaad8c2d2f2" + } + ] + }, + "customWidth": "100", + "name": "Spam Effectiveness", + "id": "82812b88-e7f7-4be0-9d13-8e7a7d8c0c4e" + }, + { + "type": 1, + "content": { + "json": "### Spam Detection Trend
\r\n\r\n**This visual displays a per-{Granularity} trend of email Spam detections identified by Microsoft Defender for Office 365. The area chart summarises the number of messages flagged for Spam threats.**" + }, + "name": "text - Spam Trend Header", + "id": "b5574a88-430b-4cca-a76e-9a0b07e9da2e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where ThreatTypes has \"Spam\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, SpamDetections = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "SpamDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "09b7d330-1683-45c4-ac0e-8141580d13b5" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "4" + }, + "name": "group - 6-Spam-detections-trend", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "25273f47-8201-4565-8815-1d059ee8abb6" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Spam Detections by Delivery location, Detection technology, Sender infrastructure and Bulk insights\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Spam detections delivery locations, detection technologies used for detections, sender infrastructure and Bulk insights in inbound email identified by Microsoft Defender for Office 365 as Spam.

**Recommended action:** Raise the Bulk Complaint Level (BCL) threshold for noisy sender domains and consider blocking high-volume, low-value bulk senders where appropriate." + }, + "name": "text - Spam Section2 Banner", + "id": "b82f442b-a3a0-44f7-82df-2fd4a9594992" + }, + { + "type": 1, + "content": { + "json": "### Spam Detections by delivery location
\r\n\r\n**Visualizes counts (per {Granularity}) of Spam detections of inbound emails by various delivery locations Quarantine, Junk folder or Failed (rejected with or without NDR)**" + }, + "name": "text - Spam DeliveryLoc Header", + "id": "a6326d97-56cc-45fb-8019-e0c3346968f2" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections over time summarizing the data daily by Delivery Location.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Spam\" and EmailDirection == \"Inbound\"\r\n| summarize TotalSpamDetections=count(), Quarantine=countif(DeliveryLocation == \"Quarantine\"), Junkfolder=countif(DeliveryLocation == \"Junk folder\"), Inbox=countif(DeliveryLocation == \"Inbox/folder\"), Failed=countif(DeliveryLocation == \"Failed\"), Dropped=countif(DeliveryLocation == \"Dropped\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, TotalSpamDetections=coalesce(TotalSpamDetections,0), Quarantine=coalesce(Quarantine,0), Junkfolder=coalesce(Junkfolder,0), Inbox=coalesce(Inbox,0), Failed=coalesce(Failed,0), Dropped=coalesce(Dropped,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "TotalSpamDetections", + "color": "blue" + }, + { + "seriesName": "Quarantine", + "color": "greenDark" + }, + { + "seriesName": "Junkfolder", + "color": "orangeDark" + }, + { + "seriesName": "Inbox", + "color": "redBright" + }, + { + "seriesName": "Failed", + "color": "red" + }, + { + "seriesName": "Dropped", + "color": "redDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam DeliveryLoc Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "97f89032-34e3-40ff-bb88-42d195aea095" + }, + { + "type": 1, + "content": { + "json": "### Spam Detections Detection Technology
\r\n\r\n**Visualizes counts (per {Granularity}) of Spam detections of inbound emails by various Microsoft Defender for Office 365 detection technologies.**" + }, + "name": "text - Spam DetTech Header", + "id": "935ea90d-8430-49d5-b942-3a7b319a603e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections over time summarizing the data daily by various Spam Detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where DetectionMethods has \"Spam\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| mv-expand Details = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam DetTech Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f31ec0d1-04e1-4b2b-9b98-27289ca34b84" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections summarized by individual Spam detection technology/control in Microsoft Defender for Office 365.\r\n//Each technique is counted individually via mv-expand over DetectionMethods.Spam (matching the sibling trend line chart), so a message flagged by multiple techniques counts once per technique.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Spam\"\r\n| mv-expand Details = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details\r\n| sort by Count desc\r\n| project ['Detection Technology'] = Details, ['Detections'] = Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam DetTech Pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "95e40479-f0bc-41ff-8191-634b606d3632" + }, + { + "type": 1, + "content": { + "json": "### Spam Detections by SenderIPv4 Geo Location
\r\n\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Spam, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" + }, + "name": "text - Spam Geo Header", + "id": "614d1c3f-df6a-4659-b170-7b466c66d66f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections summarizing the data by email sender IP address (SenderIPv4).\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where ThreatTypes has \"Spam\" and isnotempty(SenderIPv4)\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_ ", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "map", + "mapSettings": { + "locInfo": "LatLong", + "locInfoColumn": "SenderIPv4", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "none" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Geo Map", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5519d715-dc79-45f8-8ed5-a63a253c45e3" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where ThreatTypes has 'Spam' and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Spam Emails'] = count_\r\n| sort by ['Spam Emails'] desc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spam Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "mapSettings": { + "locInfo": "LatLong", + "locInfoColumn": "SenderIPv4", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "heatmap", + "heatmapPalette": "red" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Country Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5078dc24-e8be-4943-98fc-6527968e1e3d" + }, + { + "type": 1, + "content": { + "json": "### Spam Detections Bulk Insights
\r\n\r\n**Displays the distribution of inbound emails across different Bulk Complaint Levels together with Top 10 domains sending Bulk email (grey mail). Helps identify patterns in bulk email complaints and assess potential spam or unwanted message trends.**" + }, + "name": "text - Spam Bulk Header", + "id": "cd7b3cbe-a6c1-422c-ab37-4afc26002d5d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails which has any Bulk complaint level. It is summarizing the data by the various Bulk Complaint levels to understand how many messages are detected with each Bulk Complaint level.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\" and isnotnull(BulkComplaintLevel)\r\n| summarize count() by BulkComplaintLevel\r\n| sort by BulkComplaintLevel desc\r\n| project ['Bulk Complaint Level'] = BulkComplaintLevel, Emails=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "blueDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Bulk By Level", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "021c022b-aa67-427d-9e1a-688af7aed5d4" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails which has any Bulk complaint level. It is summarizing the data by the various Bulk Complaint levels and SenderFromDomain of the email sender. It provides insights how many messages are detected with each Bulk Complaint level for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\" and isnotnull(BulkComplaintLevel)\r\n| summarize count() by BulkComplaintLevel, SenderFromDomain\r\n| top 10 by count_ desc\r\n| project ['Sender Domain'] = SenderFromDomain, ['Bulk Complaint Level'] = BulkComplaintLevel, Emails=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Bulk By Domain", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b1835e0f-f9ad-44c3-bba4-cf9a9546d09a" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "4" + }, + "name": "group - 28-Spam-Delivery location-Detection technology-Sender infrastructure insights", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "307d3d03-93ae-4c8f-b68b-f833ee7d38e8" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n\r\n
Spam Detections Top attacked users and top senders\r\n
\r\n\r\nThis section consolidates key visuals that track and explain spam detections in inbound email as identified by Microsoft Defender for Office 365 focusing on top attacked users and top senders.

**Recommended action:** Review the most-affected users and the top spam sender domains as possible block-list candidates." + }, + "name": "text - Spam Section3 Banner", + "id": "4c34ed7b-86da-4ee1-8a69-f96c213a4340" + }, + { + "type": 1, + "content": { + "json": "### Spam Detections top attacked users
\r\n\r\n**Displays the top 10 recipient email addresses that received inbound emails flagged as Spam. These users may be at higher risk and should be prioritised for targeted cybersecurity awareness training. Training should cover the specific threat types and techniques they are exposed to, and reinforce best practices for promptly reporting any suspicious messages that might bypass security controls and reach their inbox.**" + }, + "customWidth": "100", + "name": "text - Spam TopUsers Header", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "be708ad5-51fd-4a54-b1bc-f912e12b4a01" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails with Spam detections summarizing the data by the top 15 recipient email address (RecipientEmailAddress).\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where EmailDirection ==\"Inbound\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),SpamEmailCount = countif(ThreatTypes has \"Spam\") by RecipientEmailAddress\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(SpamEmailCount / todouble(TotalEmailCount)* 100, 2))\r\n| where SpamEmailCount !=0\r\n| top 15 by SpamEmailCount\r\n| project ['Recipient'] = RecipientEmailAddress, ['Spam Emails'] = SpamEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spam Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "40ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal", + "useGrouping": false + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam TopRecipients Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6e7b357d-6792-41c5-83fc-efae31afe2ee" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains with Spam Detections (Inbound)
\r\n\r\n**Displays the top 10 sender domains sending inbound emails detected as Spam. Helps identify external sources most frequently associated with spam content for prioritised monitoring and mitigation.**" + }, + "customWidth": "100", + "name": "text - Spam TopSenders Header", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1d1bdb8d-9619-488b-935a-3791ad73f096" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails with Spam detections summarizing the data by the top 15 email sender P2 domain (SenderFromDomain). Adding additional insights for total inbound emails and bad traffic percentage for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where EmailDirection == \"Inbound\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount = count(),\r\n SpamEmailCount = countif(ThreatTypes has \"Spam\") by SenderFromDomain\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(SpamEmailCount / todouble(TotalEmailCount) * 100, 2))\r\n| where SpamEmailCount !=0\r\n| top 15 by SpamEmailCount\r\n| project ['Sender Domain'] = SenderFromDomain, ['Spam Emails'] = SpamEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spam Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "40ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam TopSenders Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "253efada-ca89-49c5-b1e3-e42ac005b938" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "4" + }, + "name": "group - 29-Spam Detections Top attacked users and top senders", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "d4cc057f-c9b7-40b9-85d3-52f90767d1f5" + }, + { + "type": 1, + "content": { + "json": "# Email Impersonation & BEC Insights\r\n\r\n---\r\nThis tab focuses on the highest-value email threat class: **impersonation and Business Email Compromise (BEC)**. It brings together impersonation and spoof detections, sender authentication (DMARC, DKIM, SPF, CompAuth), supply-chain and partner-compromise correlation, and first-contact / new-vendor senders - the signals that precede targeted financial and credential attacks. It is the email-side companion to the impersonation insights on the **Teams & Collaboration** tab." + }, + "name": "text - impersonation bec description", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "id": "fda8ccd5-fafc-457a-a6a2-05b504be1023" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//KPI summary of inbound email impersonation and spoof (BEC) detections for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet bec = EmailEvents | where EmailDirection == \"Inbound\" | where DetectionMethods has \"Impersonation\" or DetectionMethods has \"Spoof\";\r\nlet inbox = bec | where DeliveryLocation has \"Inbox\";\r\nlet becTrend = toscalar(bec | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet inboxTrend = toscalar(inbox | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(bec | summarize count()), Details = \"Impersonation / Spoof Emails\", Ord = 1, Trend = becTrend),\r\n(print Count = toscalar(bec | summarize dcount(RecipientEmailAddress)), Details = \"Users Targeted\", Ord = 2, Trend = becTrend),\r\n(print Count = toscalar(bec | summarize dcount(SenderFromDomain)), Details = \"Spoofed Sender Domains\", Ord = 3, Trend = becTrend),\r\n(print Count = toscalar(inbox | summarize count()), Details = \"Delivered to Inbox\", Ord = 4, Trend = inboxTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "name": "bec kpi strip", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "91fdd28f-31c4-4f94-b60a-12cd97d44ddf" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Phish Detections Business Email Compromise (BEC) detections\r\n
\r\n\r\nThis section consolidates key visuals that track and explain phish detections in inbound email as identified by Microsoft Defender for Office 365 focusing on Business Email Compromise (BEC) detections Impersonation and Spoof.

**Recommended action:** Enable mailbox intelligence and impersonation protection for frequently-impersonated users and domains; consider adding confirmed look-alike domains to the Tenant Block List." + }, + "name": "text - Phish BEC Banner", + "id": "e3b2232c-8056-4913-a652-64f70e228750" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Impersonation detections Trend\r\n**Displays counts (per {Granularity}) of inbound emails flagged for Business Email Compromise (BEC) using Impersonation detection methods by Microsoft Defender for Office 365. Helps track impersonation attack patterns over time.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Imp Trend Header", + "id": "e95667df-3bcd-4023-9e8f-99ed05bc4bf0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Impersonation detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has 'Impersonation'\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ImpersonationDetections = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "ImpersonationDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Imp Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "61fa166d-f300-42a6-a324-de18b3fdf4c1" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Impersonation detections by Detection Technology\r\n**Visualizes counts (per {Granularity}) of Phish detections of inbound emails by various Microsoft Defender for Office 365 detection technologies used for detecting Impersonations.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Imp Tech Header", + "id": "09e1a866-f344-4a92-a3bd-8c3c3c5d598d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Impersonation detections over time summarizing the data daily by various Impersonation Detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where Details has \"Impersonation\"\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Imp Tech Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6cd5662f-13b4-4a9b-afe7-0a6343e3ab5c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish - Business Email Compromise (BEC) - Impersonation detections summarized by individual detection technology/control in Microsoft Defender for Office 365.\r\n//Each technique is counted individually via mv-expand over DetectionMethods.Phish (matching the sibling trend line chart), so a message flagged by multiple techniques counts once per technique.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where Details has \"Impersonation\"\r\n| summarize Count = count() by Details\r\n| sort by Count desc\r\n| project ['Detection Technology'] = Details, ['Detections'] = Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "graphSettings": { + "type": 0 + }, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Imp Tech Pie", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "73499618-e842-440e-a555-cd8849093884" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Impersonation detections by SenderIPv4 Geo Location\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Phish - Impersonation, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Imp Geo Header", + "id": "189a1ac1-f275-4697-880b-7ffae1e5d263" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Impersonation detections summarizing the data by email sender IP address (SenderIPv4).\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Impersonation\" and isnotempty(SenderIPv4)\r\n//| project Timestamp, EmailDirection, SenderFromAddress, AdditionalFields, SenderIPv4 \r\n| summarize count()by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_ ", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "map", + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "none" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish BEC Imp Geo Map", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "574b61ad-ec2d-4517-93c5-d0e9bd14f2e9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where DetectionMethods has \"Impersonation\" and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Impersonation Emails'] = count_\r\n| sort by ['Impersonation Emails'] desc", + "size": 0, + "showAnalytics": true, + "title": "Impersonation Detections-Sender Heatmap (IPv4)", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Impersonation Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "heatmap", + "heatmapPalette": "red" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish BEC Imp Country", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e53b7dbc-4683-4309-b879-c7be68599159" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Spoof detections Trend\r\n**Displays counts (per {Granularity}) of inbound emails flagged for Business Email Compromise (BEC) using Spoof detection methods by Microsoft Defender for Office 365. Helps track Spoofing based attack patterns over time.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Spoof Trend Header", + "id": "8db0f1b0-49bf-43a2-9f9f-164eb9530629" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Spoof detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has 'Spoof'\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, SpoofDetections = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "SpoofDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Spoof Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "9a308cd9-bf05-4287-b0d5-54636d081a82" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Spoof detections Trend by Detection Technology\r\n**Visualizes counts (per {Granularity}) of Phish detections of inbound emails by various Microsoft Defender for Office 365 detection technologies used for detecting Spoofing.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Spoof Tech Header", + "id": "28c9c15d-d22f-4412-9efc-868b95082668" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Spoof detections over time summarizing the data daily by various Spoof Detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where Details has \"Spoof\"\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "yAxis": [ + "Count" + ], + "seriesLabelSettings": [ + { + "seriesName": "[[\"Spoof external domain\"]", + "color": "redDark" + }, + { + "seriesName": "[[\"Spoof intra-org\"]", + "color": "orangeDark" + }, + { + "seriesName": "[[\"Spoof DMARC\"]", + "color": "yellowDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Spoof Tech Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1a1328fc-5404-4dff-99ed-3a30082a4cbe" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish - Business Email Compromise (BEC) - Spoof detections summarized by individual detection technology/control in Microsoft Defender for Office 365.\r\n//Each technique is counted individually via mv-expand over DetectionMethods.Phish (matching the sibling trend line chart), so a message flagged by multiple techniques counts once per technique.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where Details has \"Spoof\"\r\n| summarize Count = count() by Details\r\n| sort by Count desc\r\n| project ['Detection Technology'] = Details, ['Detections'] = Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Spoof Tech Pie", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "f7df9892-85b4-49c3-8739-873b745183a3" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Spoof detections by SenderIPv4 Geo Location\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Phish - Spoofing, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Spoof Geo Header", + "id": "3c83e7f0-5391-4b1a-bb5b-de0d17488efd" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Spoof detections summarizing the data by email sender IP address (SenderIPv4).\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Spoof\" and isnotempty(SenderIPv4)\r\n//| project Timestamp, EmailDirection, SenderFromAddress, AdditionalFields, SenderIPv4 \r\n| summarize count()by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_ ", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "map", + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "none" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish BEC Spoof Geo Map", + "styleSettings": { + "margin": "15px", + "padding": "15px" + }, + "id": "122d860c-ab0d-475e-b29e-2955020680c7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where DetectionMethods has \"Spoof\" and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Spoof Emails'] = count_\r\n| sort by ['Spoof Emails'] desc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spoof Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "heatmap", + "heatmapPalette": "red" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish BEC Spoof Country", + "styleSettings": { + "margin": "15px", + "padding": "15px" + }, + "id": "9d0111bc-8d01-4a99-9009-645dc02c3bed" + }, + { + "type": 1, + "content": { + "json": "### Supply-Chain & Partner Risk (Possible Partner Compromise)\r\n**Correlates the external domains your organization emails most with inbound emails from those same domains that carried threats. A trusted partner or supplier domain suddenly sending threats is a strong signal that the partner may be compromised - a common supply-chain and business email compromise (BEC) vector.**

**Recommended action:** Verify any flagged partner through a trusted channel before acting on their recent messages, alert them to a possible compromise, and consider tightening inbound policy for that domain until confirmed clean." + }, + "customWidth": "100", + "name": "text - Phish Partner Compromise Header", + "id": "2c62c576-3b05-4663-ae2e-4f961d7409c6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises top outbound recipient domains by outbound email volume and shows total number of inbound emails with Threats from the same domains (as inbound senders) \r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Outbound\"\r\n| project RecipientDomain = tostring(split(RecipientEmailAddress, \"@\")[1])\r\n| summarize count() by RecipientDomain\r\n| project OutboundCount=count_, RecipientDomain, SenderFromDomain=RecipientDomain\r\n| join (EmailEvents | where EmailDirection == \"Inbound\" and isempty(ThreatTypes)==false) on SenderFromDomain\r\n| summarize max(OutboundCount),count() by SenderFromDomain\r\n| project SenderFromDomain, OutboundEmails=max_OutboundCount, IncomingEmailsWithThreats=count_\r\n| extend Bad_Traffic_Percentage = todouble(round(IncomingEmailsWithThreats / todouble(OutboundEmails) * 100, 2))\r\n| top 15 by OutboundEmails\r\n| project ['Sender Domain'] = SenderFromDomain, ['Outbound Emails'] = OutboundEmails, ['Inbound w/ Threats'] = IncomingEmailsWithThreats, ['Bad Traffic %'] = Bad_Traffic_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Outbound Emails", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Inbound w/ Threats", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "60ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish Partner Compromise", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1aaa047c-1108-4288-833e-61ca35b5495a" + }, + { + "type": 1, + "content": { + "json": "### Top Recipients Targeted by Impersonation / BEC\r\n**Lists the recipients most frequently targeted by impersonation and Business Email Compromise (BEC) attempts, showing the number of impersonation emails, how many distinct senders were involved, the top spoofed sender domains, and how many of those messages were delivered to the inbox. Helps identify high-risk users (often executives or finance staff) who may need extra protection or awareness.**" + }, + "customWidth": "100", + "name": "text - impersonation targets", + "id": "b1e7c2a4-9f3d-4a6b-8c12-7d5e9f0a1b23" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top recipients targeted by impersonation / BEC, with distinct senders, spoofed domains and how many landed in the inbox.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| where OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")\r\n| where DetectionMethods has \"Impersonation\"\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize ImpersonationEmails = count(),\r\n DistinctSenders = dcount(SenderFromAddress),\r\n TopSpoofedDomains = make_set(SenderFromDomain, 5),\r\n DeliveredToInbox = countif(DeliveryLocation has \"Inbox\")\r\n by RecipientEmailAddress\r\n| top 20 by ImpersonationEmails\r\n| project ['Recipient'] = RecipientEmailAddress, ['Impersonation Emails'] = ImpersonationEmails, ['Distinct Senders'] = DistinctSenders, ['Top Spoofed Domains'] = strcat_array(TopSpoofedDomains, \", \"), ['Delivered to Inbox'] = DeliveredToInbox", + "size": 0, + "title": "Top Recipients Targeted by Impersonation / BEC", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "showAnalytics": true, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Impersonation Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "name": "newviz - impersonation targets", + "id": "afe28369-af82-47ae-846d-179bd86b660e" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "name": "group - 7 - Phish-BEC-Insights", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "b7971cd9-d086-47c7-8f66-50956b9c56c3" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Phish Detections Sender Authentication details (DMARC, DKIM, SPF, CompAuth)\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Sender Authentication checks details in inbound email by Microsoft Defender for Office 365 focusing on the various Sender Authentication standards: DMARC, DKIM, SPF, CompAuth.

**Recommended action:** For domains failing DMARC/DKIM/SPF, verify your own outbound authentication is published and enforced (p=reject), and treat persistent external spoofers as possible block candidates." + }, + "name": "text - Phish Section5 Banner", + "id": "90d7a338-d943-4398-b788-bfd4f93007d4" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections Sender Authentication Trend (DMARC, DKIM, SPF, CompAuth)\r\n**Shows counts (per {Granularity}) of sender authentication check outcomes (DMARC, DKIM, SPF, CompAuth) performed by Microsoft Defender for Office 365 on inbound emails. Useful for monitoring authentication success and failure patterns over time to identify anomalies or potential phishing risks.**" + }, + "customWidth": "100", + "name": "text - Phish SenderAuth Trend Header", + "id": "4a0ab90e-55dd-4fa6-82c3-0edc57ce0966" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spoof- DMARC fails summarizing the data daily.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend DMARCFail = (tostring(parse_json(AuthenticationDetails).DMARC) == \"fail\") \r\n| summarize DMARCFail = sum(DMARCFail) by bin (Timestamp,{Granularity})", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "DMARCFail", + "color": "orangeDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish Auth DMARC Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "79920d30-01d4-4412-b994-853e50c9d7d8" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spoof- DKIM fails summarizing the data daily.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend DKIMFail = (tostring(parse_json(AuthenticationDetails).DKIM) == \"fail\") \r\n| summarize DKIMFail = sum(DKIMFail) by bin (Timestamp,{Granularity})", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "DKIMFail", + "color": "yellowDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish Auth DKIM Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "bf09ffd4-eee0-42f7-a507-1cf54d9c365a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spoof- SPF fails summarizing the data daily.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend SPFFail = (tostring(parse_json(AuthenticationDetails).SPF) == \"fail\") \r\n| summarize SPFFail = sum(SPFFail) by bin (Timestamp,{Granularity})", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "SPFFail", + "color": "purpleDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish Auth SPF Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "4d66fe13-9904-45cf-8783-f3ee984f3a66" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spoof- Composite Authentication fails summarizing the data daily.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend CompAuthFail = (tostring(parse_json(AuthenticationDetails).CompAuth) == \"fail\") \r\n| summarize CompAuthFail = sum(CompAuthFail) by bin (Timestamp,{Granularity})", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "CompAuthFail", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish Auth CompAuth Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "0968b828-23fe-4fa2-a5ea-8ab39362457f" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections Top Sender Domains with DMARC Failures (Inbound)\r\n**Displays the top 10 sender domains (P1 and P2) for inbound emails where Spoof-DMARC detection triggered. Includes total inbound email volume and calculates DMARC fail traffic percentage per domain to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "text - Phish Auth DMARC Domains Header", + "id": "24d4689a-eb6d-49f5-85a8-fcadca409f7a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spoof-DMARC fails detections summarizing the data by the top 10 email sender P2 domain (SenderFromDomain) and sender P1 domain (SenderMailFromDomain). Adding additional insights for total inbound emails and DMARC fail traffic percentage for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalEmailCount = count(),\r\n DMARCFailCount = countif(set_has_element(parse_json(DetectionMethods).Phish, \"Spoof DMARC\")) by P1Sender=SenderMailFromDomain, P2Sender=SenderFromDomain\r\n| extend DMARCFail_Traffic_Percentage = todouble(round(DMARCFailCount / todouble(TotalEmailCount) * 100, 2))\r\n| where DMARCFailCount !=0\r\n| top 10 by DMARCFailCount\r\n| project ['P1 Sender'] = P1Sender, ['P2 Sender'] = P2Sender, ['DMARC Failures'] = DMARCFailCount, ['Total Inbound'] = TotalEmailCount, ['DMARC Fail %'] = DMARCFail_Traffic_Percentage", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "DMARCFail", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "DMARC Fail %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "40ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish Auth DMARC Domains", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "642814ad-9d24-4be9-ae10-3578e89da05b" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections Top Sender Domains with Spoof External Domain Detections (Inbound)\r\n**Displays the top 10 sender domains (P1 and P2) for inbound emails flagged for Spoof External Domain detection. Includes total inbound email volume and calculates spoof traffic percentage per domain to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "text - Phish Auth SpoofExt Domains Header", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "993fdc34-354b-412e-be39-facbde4f4f0e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish-Spoof-external domain detections summarizing the data by the top 10 email sender P2 domain (SenderFromDomain) and sender P1 domain (SenderMailFromDomain). Adding additional insights for total inbound emails and Spoof external domain detection traffic percentage for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalEmailCount = count(),\r\n SpoofExternalCount = countif(set_has_element(parse_json(DetectionMethods).Phish, \"Spoof external domain\")) by P1Sender=SenderMailFromDomain, P2Sender=SenderFromDomain\r\n| extend SpoofExternal_Traffic_Percentage = todouble(round(SpoofExternalCount / todouble(TotalEmailCount) * 100, 2))\r\n| where SpoofExternalCount !=0\r\n| top 10 by SpoofExternalCount\r\n| project ['P1 Sender'] = P1Sender, ['P2 Sender'] = P2Sender, ['Spoof External'] = SpoofExternalCount, ['Total Inbound'] = TotalEmailCount, ['Spoof External %'] = SpoofExternal_Traffic_Percentage", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spoof External", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spoof External %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "40ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "SpoofExternalFail", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true, + "sortBy": [ + { + "itemKey": "Spoof External %", + "sortOrder": 2 + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish Auth SpoofExt Domains", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "69ca3799-d2d5-4896-b3a5-1eeba46f0b46" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections Top Sender Domains with Spoof Internal Domain Detections (Inbound)\r\n**Displays the top 10 sender domains (P1 and P2) for inbound emails flagged for Spoof Internal Domain detection. Includes total inbound email volume and calculates spoof traffic percentage per domain to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "text - Phish Auth SpoofInt Domains Header", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3fa33c5d-0eba-471f-b47f-0c12c1f770d6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish-Spoof-internal domain detections summarizing the data by the top 10 email sender P2 domain (SenderFromDomain) and sender P1 domain (SenderMailFromDomain). Adding additional insights for total inbound emails and Spoof internal domain detection traffic percentage for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalEmailCount = count(),\r\n SpoofInternalCount = countif(set_has_element(parse_json(DetectionMethods).Phish, \"Spoof intra-org\")) by P1Sender=SenderMailFromDomain, P2Sender=SenderFromDomain\r\n| extend SpoofInternal_Traffic_Percentage = todouble(round(SpoofInternalCount / todouble(TotalEmailCount) * 100, 2))\r\n| where SpoofInternalCount !=0\r\n| top 10 by SpoofInternalCount\r\n| project ['P1 Sender'] = P1Sender, ['P2 Sender'] = P2Sender, ['Spoof Internal'] = SpoofInternalCount, ['Total Inbound'] = TotalEmailCount, ['Spoof Internal %'] = SpoofInternal_Traffic_Percentage", + "size": 3, + "showAnalytics": true, + "title": "Top 10 Spoof intra-org detections by Sender domain (P1/P2)", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spoof Internal", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spoof Internal %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "40ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "SpoofIntraorgFail", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish Auth SpoofInt Domains", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "ae0c65c7-68ea-4d50-b177-1effeaf1c045" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "name": "group - 8-Phish-SenderAuth", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "8077779a-4da8-46be-8032-626bd8c36dbd" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
First-Contact & New-Vendor Senders\r\n
\r\n\r\nExternal email senders and domains seen for the first time in the selected period. New/first-contact relationships - especially ones already carrying threats - are a common precursor to phishing, business email compromise (BEC), and supply-chain attacks.

**Recommended action:** Treat brand-new domains sending threats as high-priority review; verify any that claim to be a known brand or partner before trusting their messages." + }, + "name": "phish fc banner", + "id": "05b83435-c7ed-48a3-919e-388b2e599726" + }, + { + "type": 1, + "content": { + "json": "### First-contact external senders
\r\n\r\n**External email senders ordered by when they were first seen in the period (most recent first). In tenants with longer history this highlights genuinely new senders.**" + }, + "customWidth": "100", + "name": "phish fc senders header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "c57dffb4-dfdb-4a1e-93be-16fa9e856a0d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists external email senders seen for the first time in the selected period (most recent first), surfacing new/first-contact senders. In tenants with longer history this highlights genuinely new relationships - a common precursor to BEC and supply-chain attacks.\r\n// TIP: to hide your own accepted domains, uncomment the ExcludeDomains line and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"fabrikam.com\"]);\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| extend SenderDomain = tostring(split(SenderFromAddress, \"@\")[1])\r\n| where isnotempty(SenderFromAddress)\r\n//| where SenderDomain !in~ (ExcludeDomains)\r\n| summarize FirstSeen=min(Timestamp), Messages=count(), ThreatMessages=countif(isnotempty(ThreatTypes)) by SenderFromAddress, SenderDomain\r\n| top 20 by FirstSeen desc\r\n| project ['Sender']=SenderFromAddress, ['Sender Domain']=SenderDomain, ['First Seen']=FirstSeen, Messages, ['Threat Messages']=ThreatMessages", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "phish fc senders table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d1ceb0ac-2dad-49af-b416-a3376a7b8513" + }, + { + "type": 1, + "content": { + "json": "### New sender domains carrying threats
\r\n\r\n**External sender domains seen for the first time in the period that already carried threats, most-recent first. A brand-new domain sending threats to your users is a strong early-warning signal.**" + }, + "customWidth": "100", + "name": "phish fc domains header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "bd29bbe4-cde2-499c-a1d0-e2cc51f7733d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists external sender domains seen for the first time in the selected period that already carried threats, ranked by most-recently first seen. A brand-new domain sending threats to your users is a strong early-warning signal for phishing and BEC.\r\n// TIP: to hide your own accepted domains, uncomment the ExcludeDomains line and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"fabrikam.com\"]);\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| extend SenderDomain = tostring(split(SenderFromAddress, \"@\")[1])\r\n| where isnotempty(SenderDomain)\r\n//| where SenderDomain !in~ (ExcludeDomains)\r\n| summarize FirstSeen=min(Timestamp), LastSeen=max(Timestamp), Messages=count(), Senders=dcount(SenderFromAddress), Recipients=dcount(RecipientEmailAddress), ThreatMessages=countif(isnotempty(ThreatTypes)) by SenderDomain\r\n| where ThreatMessages > 0\r\n| top 20 by FirstSeen desc\r\n| project ['Sender Domain']=SenderDomain, ['First Seen']=FirstSeen, Messages, Senders, Recipients, ['Threat Messages']=ThreatMessages, ['Last Seen']=LastSeen", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Senders", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Recipients", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "phish fc domains table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "7da952d5-5ae2-4b2e-a5cf-c78b11bda4f8" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "customWidth": "100", + "name": "group - Phish First Contact", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "90e5248a-2c35-48f3-869c-c45c631c6fbf" + }, + { + "type": 1, + "content": { + "json": "# URL Detections and URL Click Insights\r\n\r\n---\r\nThis tab provides insights into **URL-based detections** in email messages and details about URL clicks performed by end users on URLs identified as **malicious**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "5" + }, + "name": "text - 24 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "2156430d-fec6-48bb-a9a8-3166182f6993" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//KPI summary of URL threat protection (Safe Links clicks and URLs seen in email) for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet clicks = UrlClickEvents;\r\nlet blocked = clicks | where ActionType in (\"ClickBlocked\",\"ClickBlockedByTenantPolicy\");\r\nlet allowed = clicks | where ActionType == \"ClickAllowed\";\r\nlet blockedTrend = toscalar(blocked | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet allowedTrend = toscalar(allowed | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet usersTrend = toscalar(clicks | make-series Trend = dcount(AccountUpn) default = 0 on Timestamp step gran | project Trend);\r\nlet urlsTrend = toscalar(EmailUrlInfo | make-series Trend = dcount(Url) default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(blocked | summarize count()), Details = \"Malicious Clicks Blocked\", Ord = 1, Trend = blockedTrend),\r\n(print Count = toscalar(allowed | summarize count()), Details = \"Clicks Allowed Through\", Ord = 2, Trend = allowedTrend),\r\n(print Count = toscalar(clicks | summarize dcount(AccountUpn)), Details = \"Users Clicking Links\", Ord = 3, Trend = usersTrend),\r\n(print Count = toscalar(EmailUrlInfo | summarize dcount(Url)), Details = \"Distinct URLs in Email\", Ord = 4, Trend = urlsTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "5" + }, + "name": "url kpi strip", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d5e2326a-a5dd-4217-bb75-0e337d75d306" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Insights on URL-Based Threat Detections\r\n
\r\n\r\nThis section consolidates key visuals that track and explain URL based threat detections in inbound email as identified by Microsoft Defender for Office 365 focusing on per-{Granularity} trends of URL-based threat detections, QR code detections, and URL scans activity by locations.

**Recommended action:** Confirm Safe Links is enabled for email and Teams; investigate QR-code and URL detection spikes for emerging campaigns." + }, + "name": "text - 13 - Copy", + "id": "ed3468e7-1936-45fd-9168-93010a662302" + }, + { + "type": 1, + "content": { + "json": "### Trend of URL-Based Malware Threat Detections
\r\n\r\n**This visual displays a per-{Granularity} trend of emails with URL based Malware threat detections identified by Microsoft Defender for Office 365. The line chart summarises the number of messages flagged for malware threats.**" + }, + "name": "text - 13 - Copy - Copy", + "id": "77e7bbac-d752-478b-bce9-06bb1bd12bfe" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections over time summarizing the data daily by various Malware URL threat based detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Malware'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand MalwareMethod = ParsedMethods.Malware\r\n| where MalwareMethod contains \"URL\"\r\n| summarize Count = count() by MalwareMethod = tostring(MalwareMethod), Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct MalwareMethod | extend d = 1) on d | project Timestamp, MalwareMethod\r\n| join kind=leftouter (agg) on Timestamp, MalwareMethod\r\n| project Timestamp, MalwareMethod, Count = coalesce(Count, 0)\r\n| sort by MalwareMethod asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 8 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "79ef5e7b-57a6-4519-9899-18fd8cae5e68" + }, + { + "type": 1, + "content": { + "json": "### Trend of URL-Based Phish Threat Detections
\r\n\r\n**This visual displays a per-{Granularity} trend of emails with URL based Phish threat detections identified by Microsoft Defender for Office 365. The line chart summarises the number of messages flagged for Phish threats.**" + }, + "name": "text - 13 - Copy - Copy - Copy", + "id": "48923812-5440-4f47-8881-273f14cbfb8e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phishing detections over time summarizing the data daily by various Phishing URL threat based detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Phish'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand PhishMethod = ParsedMethods.Phish\r\n| where PhishMethod contains \"URL\"\r\n| summarize Count = count() by PhishMethod = tostring(PhishMethod), Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct PhishMethod | extend d = 1) on d | project Timestamp, PhishMethod\r\n| join kind=leftouter (agg) on Timestamp, PhishMethod\r\n| project Timestamp, PhishMethod, Count = coalesce(Count, 0)\r\n| sort by PhishMethod asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 8 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b983b361-6c2e-47d5-b2c5-edd9caa6a55d" + }, + { + "type": 1, + "content": { + "json": "### Trend (per {Granularity}) of QR Code-Based Threat Detections
\r\n\r\n**Displays counts (per {Granularity}) of inbound emails containing QR codes flagged for Phish, Malware, or Spam via URL-based detection methods. Helps track QR code abuse patterns over time.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3d8b75e1-6e1d-44eb-b1fc-78d3db7feb71" + }, + { + "type": 1, + "content": { + "json": "### URL Scan activity by Location (per {Granularity})
\r\n\r\n**Displays counts (per {Granularity}) of URLs scanned from various locations within emails (e.g., body, attachments, QR codes). Helps identify where malicious URLs are most commonly embedded.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b275b28c-e441-4c19-9055-256d5d45c69c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where EmailDirection == \"Inbound\" \r\n| where DetectionMethods has \"Url\"\r\n| join EmailUrlInfo on NetworkMessageId\r\n| where UrlLocation == \"QRCode\"\r\n| summarize [\"Phish QR Detection\"]=countif(parse_json(DetectionMethods).Phish has \"URL\"), [\"Malware QR Detection\"]=countif(parse_json(DetectionMethods).Malware has \"URL\"), [\"Spam QR Detection\"]=countif(parse_json(DetectionMethods).Spam has \"URL\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, [\"Phish QR Detection\"]=coalesce([\"Phish QR Detection\"],0), [\"Malware QR Detection\"]=coalesce([\"Malware QR Detection\"],0), [\"Spam QR Detection\"]=coalesce([\"Spam QR Detection\"],0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "graphSettings": { + "type": 0 + }, + "chartSettings": { + "xAxis": "Timestamp", + "xSettings": { + "dateFormatSettings": { + "formatName": "shortDatePattern", + "showUtcTime": false + } + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 6", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6c2a7724-d3c2-42b2-b8da-7acbcd0666c6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises where URL's have been scanned identified from various locations in emails\r\nEmailUrlInfo\r\n| summarize count() by UrlLocation", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 5", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5640dbd5-4085-4f2a-8fb9-e4112233e99e" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "5" + }, + "name": "group - 9-URL detections", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "b572d79b-17a0-48ac-9a43-4f20324cf998" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Insights on URL Click-Based Threat Detections\r\n
\r\n\r\nThis section consolidates key visuals that track and explain URL click based threat detections in emails as identified by Microsoft Defender for Office 365 focusing on per-{Granularity} trend of blocked URL clicks, time-of-click URL scans by workload, malicious clicks allowed, top clicks on malicious URLs, and more.

**Recommended action:** For blocked-click spikes, verify Safe Links is set to not allow click-through; investigate workloads with high click-through activity." + }, + "name": "text - 13 - Copy - Copy", + "id": "6d37617e-911e-4ce6-a10d-4749486738ea" + }, + { + "type": 1, + "content": { + "json": "### Trend (per {Granularity}) of Blocked URL Click Events
\r\n\r\n**Shows the count (per {Granularity}) of blocked URL click attempts and click attempts on URLs with detections, grouped by threat types (e.g., Phish, Malware, Spam). Helps track user interaction with malicious links over time across various threat types.**" + }, + "name": "text - 13 - Copy - Copy - Copy", + "id": "9e477950-bedc-4cc0-9863-df07d124806c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// Generates a time-series analysis for blocked URL click events from the 'UrlClickEvents' table\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(UrlClickEvents\r\n| where isnotempty(ActionType)\r\n| where ActionType has_any(\"ClickBlocked\")\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, BlockedClicks = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "BlockedClicks", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "query - 4", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "366e80d9-f6ed-43af-91e5-3d04cdcf692d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of click attempts on URL's with detections split by the different threat types identified\r\nUrlClickEvents\r\n| where isnotempty(ThreatTypes)\r\n| summarize count() by ThreatTypes", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "query - 4", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a356eac3-62c2-4fc9-a4d9-3b05b13848df" + }, + { + "type": 1, + "content": { + "json": "### Trend (per {Granularity}) of URL Click Actions by Type
\r\n\r\n**Displays counts (per {Granularity}) of URL click events categorised by action type: Blocked, Allowed, Pending Verdict, Error Page, and Clicked Through. Helps identify risky user behaviour and policy gaps.**" + }, + "customWidth": "66", + "name": "text - 13 - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a91fe7a6-f507-48f7-bbcc-61dc4f998ba6" + }, + { + "type": 1, + "content": { + "json": "### URL Clicks by Workload
\r\n\r\n**Displays counts (per {Granularity}) of URL click events grouped by Workload (e.g., Outlook, Teams, Copilot, Office Apps: Word, Excel, PowerPoint) Helps identify which applications are most frequently used for URL interactions and potential risk exposure.**" + }, + "customWidth": "33", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "ce05fa08-6e68-4c02-a0bf-2be6cdfae935" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises different URL click event types by action (e.g., blocked, allowed, pending verdict, error pages, and clicked through), summarizing the data daily\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(UrlClickEvents\r\n| where isnotempty(ActionType)\r\n| summarize ClickBlocked=countif(ActionType has_any(\"ClickBlocked\")), ClickAllowed=countif(ActionType has_any(\"ClickAllowed\")), PendingVerdict=countif(ActionType has_any(\"UrlScanInProgress\")), ErrorPage=countif(ActionType has_any(\"UrlErrorPage\")), ClickedThrough=countif(IsClickedThrough == true) by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ClickBlocked=coalesce(ClickBlocked,0), ClickAllowed=coalesce(ClickAllowed,0), PendingVerdict=coalesce(PendingVerdict,0), ErrorPage=coalesce(ErrorPage,0), ClickedThrough=coalesce(ClickedThrough,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "query - 1", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a12b4c78-7d18-4adc-86e0-54395d6a996a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises where URL clicks scanned by the Workload the click happened from\r\nUrlClickEvents\r\n| summarize count() by Workload", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "query - 5 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3237cd55-1d5c-41a9-a8f2-1d46c61a709e" + }, + { + "type": 1, + "content": { + "json": "### Blocked URL Clicks by Workload (per {Granularity})
\r\n\r\n**Displays counts (per {Granularity}) of blocked URL click attempts grouped by Workload (Email, Teams, Office, Microsoft 365 Copilot). Helps identify which platforms are most exposed to malicious link interactions and where user awareness or policy enforcement should be strengthened.**" + }, + "customWidth": "66", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1f209a83-3d50-4bb8-9a79-a365a50a4142" + }, + { + "type": 1, + "content": { + "json": "### Click-Through Activity on Detected URLs by Workload
\r\n\r\n**Displays counts of click‑through actions on URLs already identified with detections, grouped by Workload where the click happened. Helps identify clients/platforms where users are most likely to proceed to risky URLs and prioritise awareness training or policy tuning for those workloads**" + }, + "customWidth": "33", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "33592db8-0ff5-4d8e-bd8f-0201b81a4584" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises blocked URL click event types by Workload (e.g., Email, Teams, Office, Microsoft 365 Copilot), summarizing the data daily\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(UrlClickEvents\r\n| where ActionType ==\"ClickBlocked\"\r\n| summarize Teams=countif(Workload==\"Teams\"), Office=countif(Workload==\"Office\"), Email=countif(Workload==\"Email\"), Copilot=countif(Workload==\"Copilot\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, Teams=coalesce(Teams,0), Office=coalesce(Office,0), Email=coalesce(Email,0), Copilot=coalesce(Copilot,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "query - 3", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "80241767-0f69-4e2e-9889-3bf1f48e4f02" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of click-through activities on URL's with detections split by the source client\r\nUrlClickEvents \r\n| where IsClickedThrough !=\"0\"\r\n| where isnotempty(ThreatTypes) \r\n| summarize count() by Workload", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "query - 2", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "fde29b46-2896-4bfc-bb61-09436696d738" + }, + { + "type": 1, + "content": { + "json": "### Top clicks on Malicious URLs
\r\n\r\n**Displays the top 20 URLs associated with detections that registered the highest number of clicks. Includes ThreatTypes, ActionType, and Workload to provide context on the nature of the threat and where user interaction occurred.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "22bda63a-626c-47de-9a76-ad665ef87862" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows the top 20 URL's that have a detection associated with the most ammount of clicks registered \r\nUrlClickEvents\r\n| where ThreatTypes !=\"\"\r\n| summarize count() by Url, ThreatTypes, ActionType, Workload\r\n| top 20 by count_\r\n| project ['URL']=Url, ['Threat Types']=ThreatTypes, ['Action Type']=ActionType, Workload, ['Click Count']=count_", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Click Count", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 10 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a044fd4e-7be6-4a11-974c-b54e417c2a81" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "5" + }, + "name": "group - 31-URL clicks", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "75e543f6-08c0-42ed-9869-ecd61b721d34" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Top Risky Users Clicking on URLs with Threats\r\n
\r\n\r\nThis section consolidates key visuals that track and identify users who have clicked on malicious URLs detected by Microsoft Defender for Office 365.

**Recommended action:** Enroll these users in security awareness training and verify Safe Links policy coverage for their mailboxes." + }, + "name": "text - 13 - Copy - Copy - Copy", + "id": "19487811-a94b-4537-877e-61ac7e287c21" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Users Clicking on URLs with Malware Threat
\r\n\r\n**Displays the top 10 user accounts with the highest number of click attempts on URLs flagged as Malware. Helps identify individuals at greater risk and prioritise targeted security awareness training.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "78e10621-0e98-44c4-8399-810c19f138c2" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top 10 users with click attempts on URL's with malware detections\r\nUrlClickEvents\r\n| summarize TotalClickCount=count(),MalwareClickCount = countif(ThreatTypes has \"Malware\") by AccountUpn\r\n| extend Bad_Click_Percentage = todouble(round(MalwareClickCount / todouble(TotalClickCount) *100, 2))\r\n| where MalwareClickCount !=0\r\n| sort by MalwareClickCount desc\r\n| top 15 by MalwareClickCount\r\n| project ['User']=AccountUpn, ['Malware Clicks']=MalwareClickCount, ['Total Clicks']=TotalClickCount, ['Bad Click %']=Bad_Click_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Malware Clicks", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "25ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Clicks", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Click %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "25ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "MalwareEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "TotalEmailCount", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad_Traffic_Percentage_Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 18 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a7ae8a75-ca7f-49be-8cad-d1451a3bd396" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Users Clicking on URLs with Phish Threat
\r\n\r\n**Displays the top 10 user accounts with the highest number of click attempts on URLs flagged as Phish. Helps identify individuals at greater risk and prioritise targeted security awareness training.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "90d9a0c3-970a-4998-be62-3b3b84bb0f37" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top 10 users with click attempts on URL's with Phish detections\r\nUrlClickEvents\r\n| summarize TotalClickCount=count(),PhishClickCount = countif(ThreatTypes has \"Phish\") by AccountUpn\r\n| extend Bad_Click_Percentage = todouble(round(PhishClickCount / todouble(TotalClickCount) *100, 2))\r\n| where PhishClickCount !=0\r\n| sort by PhishClickCount desc\r\n| top 15 by PhishClickCount\r\n| project ['User']=AccountUpn, ['Phish Clicks']=PhishClickCount, ['Total Clicks']=TotalClickCount, ['Bad Click %']=Bad_Click_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Phish Clicks", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "25ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Clicks", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Click %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "25ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "MalwareClickCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "MalwareEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "TotalEmailCount", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad_Traffic_Percentage_Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 18 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d46877d9-03af-463a-b406-bb4c601dffeb" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Users Clicking on URLs with Spam Threat
\r\n\r\n**Displays the top 10 user accounts with the highest number of click attempts on URLs flagged as Spam. Helps identify individuals at greater risk and prioritise targeted security awareness training.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "dc66e020-0932-4346-8e20-6a2dc78de7a9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top 10 users with click attempts on URL's with Spam detections\r\nUrlClickEvents\r\n| summarize TotalClickCount=count(),SpamClickCount = countif(ThreatTypes has \"Spam\") by AccountUpn\r\n| extend Bad_Click_Percentage = todouble(round(SpamClickCount / todouble(TotalClickCount) *100, 2))\r\n| where SpamClickCount !=0\r\n| sort by SpamClickCount desc\r\n| top 15 by SpamClickCount\r\n| project ['User']=AccountUpn, ['Spam Clicks']=SpamClickCount, ['Total Clicks']=TotalClickCount, ['Bad Click %']=Bad_Click_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spam Clicks", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "25ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Clicks", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Click %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "25ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "PhishClickCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "MalwareClickCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "MalwareEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "TotalEmailCount", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad_Traffic_Percentage_Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 18 - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "734ee45e-4dff-4ca1-b17d-02389086b17b" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "5" + }, + "name": "group - 32-Top clickers", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "ee6c3413-28be-49a1-a89d-bf5fce7acfa4" + }, + { + "type": 1, + "content": { + "json": "# Microsoft Teams Collaboration Protection\r\n\r\n---\r\nAs email defenses mature, attackers are shifting into **Microsoft Teams**, where messages bypass secure email gateways and carry the implicit trust of a colleague chat. Microsoft Threat Intelligence reports Teams-based phishing and voice phishing (vishing) rising steadily through 2026, most often as **IT help desk or technical-support impersonation** from external or newly-created tenants, used to steer users toward remote-access tools and credential theft.\r\n\r\nThis tab shows **Microsoft Defender for Office 365** protection for Microsoft Teams: threat detections and impersonation, suspicious external senders, malicious URLs and clicks, malicious files, post-delivery ZAP removals, and user and admin submissions across chats and channels.\r\n\r\n**Recommended action:** Treat unsolicited external help desk or IT support contact as suspicious. Restrict inbound chat from unmanaged and consumer tenants, allowlist trusted external domains, remove or restrict remote-support tools such as Quick Assist where they are not required, and enforce phishing-resistant MFA for all users (Conditional Access with authentication strength), prioritizing privileged and administrator accounts first.\r\n\r\n[

Disrupting threats targeting Microsoft Teams

](https://www.microsoft.com/en-us/security/blog/2025/10/07/disrupting-threats-targeting-microsoft-teams/)[

Cross-tenant helpdesk impersonation to data exfiltration: a human-operated intrusion playbook

](https://www.microsoft.com/en-us/security/blog/2026/04/18/crosstenant-helpdesk-impersonation-data-exfiltration-human-operated-intrusion-playbook/)[

Help on the line: how a Microsoft Teams support call led to compromise

](https://www.microsoft.com/en-us/security/blog/2026/03/16/help-on-the-line-how-a-microsoft-teams-support-call-led-to-compromise/)[

Email threat landscape: Q2 2026 trends and insights

](https://www.microsoft.com/en-us/security/blog/2026/07/23/email-threat-landscape-q2-2026-trends-and-insights/)" + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "text - teams description", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5c0f0100-0a11-4b22-9c33-000000000100" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Headline Microsoft Teams protection metrics for the selected period, with per-interval sparklines. Messages are de-duplicated to the latest record per Teams message.\r\nlet gran = {Granularity};\r\nlet msgs = materialize(MessageEvents | summarize arg_max(Timestamp, *) by TeamsMessageId);\r\nlet zap = materialize(MessagePostDeliveryEvents);\r\nunion\r\n(msgs | summarize Count = count() | extend Details = \"Teams Messages Scanned\", Ord = 1, Trend = toscalar(msgs | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where isnotempty(ThreatTypes) | summarize Count = count() | extend Details = \"Messages with Threats\", Ord = 2, Trend = toscalar(msgs | where isnotempty(ThreatTypes) | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where ThreatTypes has \"Phish\" | summarize Count = count() | extend Details = \"Phish Detections\", Ord = 3, Trend = toscalar(msgs | where ThreatTypes has \"Phish\" | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where ThreatTypes has \"Malware\" | summarize Count = count() | extend Details = \"Malware Detections\", Ord = 4, Trend = toscalar(msgs | where ThreatTypes has \"Malware\" | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where ThreatTypes has \"Spam\" | summarize Count = count() | extend Details = \"Spam Detections\", Ord = 5, Trend = toscalar(msgs | where ThreatTypes has \"Spam\" | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where SafetyTip == \"URLMessageWarning\" | summarize Count = count() | extend Details = \"Messages with URL Warning\", Ord = 6, Trend = toscalar(msgs | where SafetyTip == \"URLMessageWarning\" | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(zap | summarize Count = count() | extend Details = \"Post-Delivery ZAP Actions\", Ord = 7, Trend = toscalar(zap | make-series S = count() default = 0 on Timestamp step gran | project S))\r\n| sort by Ord asc\r\n| project Details, Count, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21 + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams kpi tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b2c476ca-4141-43b4-9d4e-98470aa432fc", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + } + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Microsoft Teams - Collaboration Protection Overview\r\n
\r\n\r\nMicrosoft Defender for Office 365 extends its protection to **Microsoft Teams**, detecting malicious messages, URLs, and files shared through chats and channels. This tab summarizes Teams message detections, link-safety warnings, post-delivery ZAP, file scanning, and user/admin submissions.

*Scope note: the Teams message tables surface metadata for external-conversation messages plus internal messages that contain URLs, so counts reflect that scope rather than the full volume of Teams messages.*" + }, + "name": "teams overview banner", + "id": "2f71360f-1673-480f-8361-5afc83aee67d" + }, + { + "type": 1, + "content": { + "json": "### Teams threat detections over time
\r\n\r\n**Volume (per selected interval) of Microsoft Teams messages detected with a threat by Microsoft Defender for Office 365. Spikes may indicate a targeted Teams-based campaign.**" + }, + "customWidth": "100", + "name": "teams trend header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "0ac71d4e-8ecb-4d17-9fd3-10754007ec07" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the number of Microsoft Teams messages detected with a threat over time, de-duplicated to the latest record per message and summarized per selected interval.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(MessageEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(MessageEvents | summarize max(Timestamp));\r\nlet agg = materialize(MessageEvents | where isnotempty(ThreatTypes) | summarize arg_max(Timestamp, *) by TeamsMessageId | summarize ThreatDetections = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ThreatDetections = coalesce(ThreatDetections, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "xAxis": "Timestamp", + "seriesLabelSettings": [ + { + "seriesName": "ThreatDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams detection trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "937f3bc6-21f5-4f4c-ab72-78f08f32c5bd" + }, + { + "type": 1, + "content": { + "json": "### Threat type breakdown
\r\n\r\n**Split of Microsoft Teams threat detections across Phish, Malware, and Spam.**" + }, + "customWidth": "50", + "name": "teams threat pie header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "645a39ae-843a-47db-8016-6082ef37744d" + }, + { + "type": 1, + "content": { + "json": "### Thread exposure
\r\n\r\n**De-duplicated Microsoft Teams messages split by whether the conversation includes external participants.**" + }, + "customWidth": "50", + "name": "teams thread header", + "id": "a1a48f9a-8593-4ab5-8824-5998c643e844" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query breaks down Microsoft Teams threat detections by threat type for the selected period, de-duplicated to the latest record per message. A message flagged for more than one threat type is counted under each, so the split can exceed the distinct message count.\r\nlet msgs = MessageEvents | where isnotempty(ThreatTypes) | summarize arg_max(Timestamp, *) by TeamsMessageId;\r\nunion\r\n(msgs | where ThreatTypes has \"Phish\" | summarize Count = count() | extend ThreatType = \"Phish\"),\r\n(msgs | where ThreatTypes has \"Malware\" | summarize Count = count() | extend ThreatType = \"Malware\"),\r\n(msgs | where ThreatTypes has \"Spam\" | summarize Count = count() | extend ThreatType = \"Spam\")\r\n| project ThreatType, Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams threat type pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "029b4ecc-cd95-4385-a251-8ab194add8f4" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows de-duplicated Microsoft Teams messages split by whether the thread includes external participants.\r\nMessageEvents\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| extend Thread = iif(IsExternalThread == true, \"External Thread\", \"Internal Thread\")\r\n| summarize Count = count() by Thread", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams thread pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1581f447-9b3e-4857-84b8-e78b5df65ac5" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Overview", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "283f36b2-5c54-4afe-9a87-33d4796bd5b7" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Teams Calls and Vishing (Voice Phishing)\r\n
\r\n\r\n**Voice phishing (vishing) over Microsoft Teams is the fastest-growing collaboration threat of 2026. Attackers impersonate IT help desk or support and call users directly, often after a chat lure, to talk them into granting remote access or entering credentials. Because a target must be online to answer, malicious calls cluster in working hours. This section surfaces Teams call activity, when calls happen, and callers using support or brand-impersonation identities.**

*Interim data source: Teams call activity is currently read from Microsoft Defender for Cloud Apps call telemetry (CloudAppEvents). The existing V4 logic retains this source while the dedicated CallActivityEvents implementation is evaluated separately.*

**Recommended action:** Treat unsolicited help desk or support calls as suspicious. Confirm any request through a known internal channel, and never grant remote access such as Quick Assist on the strength of an inbound Teams call. Restrict inbound calls and chat from unmanaged and consumer tenants." + }, + "customWidth": "100", + "name": "teams calls banner", + "id": "9815bdc9-9e10-4e84-9164-783092b4ccb0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Teams call and vishing headline metrics for the selected period, with per-interval sparklines. Interim source: Defender for Cloud Apps call telemetry (CloudAppEvents / CallParticipantDetail).\r\nlet gran = {Granularity};\r\nlet calls = materialize(CloudAppEvents | where ActionType == \"CallParticipantDetail\" | extend R = parse_json(RawEventData) | extend CallId = tostring(R.CallId), UId = tolower(tostring(R.UserId)));\r\nlet susp = calls | extend Local = tostring(split(UId, \"@\")[0]), Dom = tostring(split(UId, \"@\")[1]) | where Local matches regex @\"(?i)help ?desk|helpdesk|it ?support|service ?desk|sys ?admin|administrator|security|microsoft|google|apple|amazon|paypal|support|update|verif|account|password|mfa|maintenance\" or Dom endswith \".onmicrosoft.com\";\r\nlet reported = CloudAppEvents | where ActionType == \"CallReported\";\r\nunion\r\n(calls | summarize Count = dcount(CallId) | extend Details = \"Teams Calls\", Ord = 1, Trend = toscalar(calls | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(susp | summarize Count = dcount(UId) | extend Details = \"Impersonation-style Callers\", Ord = 2, Trend = toscalar(susp | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(reported | summarize Count = count() | extend Details = \"Reported Suspicious Calls\", Ord = 3, Trend = toscalar(reported | make-series S = count() default = 0 on Timestamp step gran | project S))\r\n| sort by Ord asc\r\n| project Details, Count, Trend", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21 + }, + "showBorder": true, + "size": "auto" + }, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams calls kpi", + "id": "be8946d9-1eae-405c-b8df-cee2242cb44d" + }, + { + "type": 1, + "content": { + "json": "### Teams call activity over time
\r\n**Distinct Microsoft Teams calls per selected interval. A sudden rise, or calls outside normal working hours, can indicate a vishing campaign in progress.**" + }, + "customWidth": "100", + "name": "teams calls trend header", + "id": "1b49c98f-e5d9-457c-b058-a195e89eac0e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Distinct Teams calls per interval (interim source: CloudAppEvents / CallParticipantDetail).\r\nCloudAppEvents\r\n| where ActionType == \"CallParticipantDetail\"\r\n| extend R = parse_json(RawEventData)\r\n| extend CallId = tostring(R.CallId)\r\n| summarize ['Teams Calls'] = dcount(CallId) by Timestamp = bin(Timestamp, {Granularity})\r\n| sort by Timestamp asc", + "size": 0, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "xAxis": "Timestamp", + "seriesLabelSettings": [ + { + "seriesName": "Teams Calls", + "color": "blueDark" + } + ] + }, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams calls trend", + "id": "7538b3ca-b96d-421a-9cdc-69b8aef4b185" + }, + { + "type": 1, + "content": { + "json": "### When calls happen (hour of day, UTC)
\r\n**Microsoft Teams calls by the hour of day they started (UTC), listed 00:00 through 23:00. The bar length is the number of calls that started in that hour across the selected period. Vishing calls cluster in working hours because the target must be online to answer, with the heaviest malicious-call activity between 14:00 and 20:00 UTC, Monday to Friday, according to Microsoft Threat Intelligence. Use this to baseline normal call timing and spot unusual off-hours spikes.**" + }, + "customWidth": "100", + "name": "teams calls hour header", + "id": "6bc095e9-fe0d-4f6f-81bd-f3374d758229" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Teams calls by start hour of day (UTC), all 24 hours 00:00..23:00 in order (interim source: CloudAppEvents / CallParticipantDetail).\r\nlet data = CloudAppEvents\r\n| where ActionType == \"CallParticipantDetail\"\r\n| extend R = parse_json(RawEventData)\r\n| extend JoinTime = todatetime(R.JoinTime), CallId = tostring(R.CallId)\r\n| where isnotempty(JoinTime) and isnotempty(CallId)\r\n| summarize CallStart = min(JoinTime) by CallId\r\n| extend HourUTC = hourofday(CallStart)\r\n| summarize Calls = count() by HourUTC;\r\nrange HourUTC from 0 to 23 step 1\r\n| join kind=leftouter (data) on HourUTC\r\n| extend Calls = coalesce(Calls, 0)\r\n| extend HourLabel = strcat(iif(HourUTC < 10, strcat(\"0\", tostring(HourUTC)), tostring(HourUTC)), \":00\")\r\n| order by HourUTC asc\r\n| project ['Hour of Day (UTC)'] = HourLabel, ['Teams Calls'] = Calls", + "size": 0, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Teams Calls", + "formatter": 3, + "formatOptions": { + "palette": "blueDark", + "customColumnWidthSetting": "360px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams calls hour", + "id": "c36a9909-5570-4fe7-8efc-1b9b4745713a" + }, + { + "type": 1, + "content": { + "json": "### Suspicious callers (support and helpdesk impersonation)
\r\n**Teams call participants whose display name or address looks like IT support, help desk, or a well-known brand (for example \"Microsoft IT support\", \"Help Desk\", \"Office 365 Support\"), or who dial in from a throwaway `.onmicrosoft.com` tenant. Origin shows whether the caller is external, an external throwaway tenant, or inside your own tenant. External and throwaway-tenant callers are the primary vishing risk; own-tenant matches are frequently a legitimate internal help desk and should be confirmed rather than assumed malicious.**

**Recommended action:** Prioritise External and `.onmicrosoft` callers, confirm none are legitimate, and warn the users they called. Genuine IT support does not cold-call staff over Teams to request remote access." + }, + "customWidth": "100", + "name": "teams calls susp header", + "id": "aa420b5f-efd2-4da5-ab41-192031f62ed1" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Suspicious Teams callers by impersonation-style DISPLAY NAME or address (Attendees[].DisplayName / UPN), with Origin from the org's own accepted (EmailEvents inbound) domains - no tenant-id anchor. Interim source: CloudAppEvents / CallParticipantDetail.\r\nlet suspRegex = @\"(?i)help ?desk|helpdesk|it ?support|service ?desk|sys ?admin|administrator|security|microsoft|google|apple|amazon|paypal|support|update|verif|account|password|mfa|maintenance\";\r\nlet ownDomains = toscalar(EmailEvents | where EmailDirection == \"Inbound\" | extend RD = tolower(tostring(split(RecipientEmailAddress, \"@\")[1])) | where isnotempty(RD) | summarize make_set(RD, 200));\r\nlet calls = CloudAppEvents\r\n| where ActionType == \"CallParticipantDetail\"\r\n| extend R = parse_json(RawEventData)\r\n| extend CallId = tostring(R.CallId), JoinTime = todatetime(R.JoinTime), Attendees = R.Attendees\r\n| where isnotempty(CallId);\r\nlet callAtt = calls | summarize Attendees = take_any(Attendees), JoinTime = min(JoinTime) by CallId;\r\ncallAtt\r\n| mv-expand Att = Attendees\r\n| extend Caller = tolower(tostring(Att.UPN)), CallerName = tostring(Att.DisplayName)\r\n| extend CallerDom = tostring(split(Caller, \"@\")[1])\r\n| where isnotempty(Caller)\r\n| extend SuspName = CallerName matches regex suspRegex or Caller matches regex suspRegex\r\n| where SuspName or CallerDom endswith \".onmicrosoft.com\"\r\n| extend Origin = case(CallerDom endswith \".onmicrosoft.com\", \"External (.onmicrosoft throwaway)\", set_has_element(ownDomains, CallerDom), \"Own tenant\", \"External\")\r\n| summarize CallsPlaced = dcount(CallId), FirstSeen = min(JoinTime), LastSeen = max(JoinTime) by CallerName, Caller, Origin\r\n| extend OriginRank = case(Origin == \"External (.onmicrosoft throwaway)\", 0, Origin == \"External\", 1, 2)\r\n| sort by OriginRank asc, CallsPlaced desc\r\n| take 10\r\n| project ['Caller Display Name'] = CallerName, ['Caller Address'] = Caller, ['Origin'] = Origin, ['Calls Placed'] = CallsPlaced, ['First Seen'] = FirstSeen, ['Last Seen'] = LastSeen", + "size": 0, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Calls Placed", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams calls susp table", + "id": "d1c4df7b-db07-4c4c-bc71-dfd8623cd704" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Calls and Vishing", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "1d133411-9b5c-4ede-8502-68b3b02262e4" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Teams Impersonation & Identity Deception\r\n
\r\n\r\nMicrosoft Defender for Office 365 flags Teams messages where a sender impersonates a brand, a specific person, or a trusted domain. Impersonation is the entry point for most Teams social-engineering: attackers pose as IT, executives, or Microsoft to build trust before delivering a malicious link or request. These visuals expose who is being impersonated, who is being targeted, and the infrastructure (display names, look-alike domains, and URLs) behind the campaigns so you can hunt IOCs and coach at-risk users.

**Recommended action:** Treat the impersonated display names and look-alike domains below as IOCs to hunt, and prioritize the Microsoft Defender alert *Microsoft Teams chat initiated by a suspicious external user*. Teach users that a Teams display name is not proof of identity: verify the real sender domain, and confirm any help desk, executive, or Microsoft support request through a known internal channel before acting." + }, + "name": "teams imp banner", + "id": "7ff04ff3-9f2d-4a49-8383-2b542d78fe9b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nunion\r\n(imp | summarize Count=count() | extend Details=\"Impersonation Detections\", Ord=1),\r\n(imp | summarize Count=dcount(FakeSenderAddress) | extend Details=\"Distinct Fake Senders\", Ord=2),\r\n(imp | summarize Count=dcount(TargetUser) | extend Details=\"Targeted Users\", Ord=3),\r\n(imp | summarize Count=dcount(ImpersonationType) | extend Details=\"Impersonation Types\", Ord=4)\r\n| sort by Ord asc | project Count, Details", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e37f94d5-9bcc-432e-aa66-25831603c228" + }, + { + "type": 1, + "content": { + "json": "### Impersonation over time, by type
\r\n\r\n**Trend of Brand, User, and Domain impersonation detections. A spike in a single type often marks the start of a targeted campaign.**" + }, + "customWidth": "100", + "name": "teams imp trend header", + "id": "09907f5b-5c20-4a7e-86d3-c89153c4df98" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp | summarize Count=count() by ImpersonationType, Timestamp=bin(Timestamp, {Granularity}) | sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp trend", + "id": "757204b1-e900-4217-a2ff-2224a033fdcc" + }, + { + "type": 1, + "content": { + "json": "### Suspicious external senders (impersonation and throwaway tenants)
\r\n**External Microsoft Teams senders flagged as likely impersonation: throwaway `.onmicrosoft.com` tenants and/or help desk, IT support, security, admin, or account/update-themed display names. Attackers rotate through many such identities (for example numbered `ithelpdesk@...` addresses) from newly-created or consumer tenants to pose as internal support, frequently before the Defender impersonation detector assigns a verdict. This heuristic complements that detector.**

**Recommended action:** Review high threat-rate senders, block the sending domains, and remind users that genuine IT support does not cold-contact them from an external tenant; verify any such request through a known internal channel." + }, + "customWidth": "100", + "name": "teams susp senders header", + "id": "5df4af86-49e9-4fc7-b6ad-76d3ef3f7da6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//External Teams senders flagged as likely impersonation: throwaway .onmicrosoft.com tenants and/or help desk / IT / admin / update-themed display names, ranked by messages carrying a threat.\r\nMessageEvents\r\n| where IsExternalThread == true\r\n| extend SenderDomain = tolower(tostring(split(SenderEmailAddress, \"@\")[1]))\r\n| extend IsOnMicrosoft = SenderDomain endswith \".onmicrosoft.com\"\r\n| extend SuspName = SenderDisplayName matches regex @\"(?i)help ?desk|helpdesk|it ?support|service ?desk|it team|administrator|sys ?admin|security|microsoft|maintenance|support|update|verif|account|password|mfa\"\r\n| where IsOnMicrosoft or SuspName\r\n| summarize TeamsMessages = count(), ThreatMessages = countif(isnotempty(ThreatTypes)), FirstSeen = min(Timestamp), LastSeen = max(Timestamp) by SenderDisplayName, SenderEmailAddress, SenderDomain, IsOnMicrosoft, SuspName\r\n| extend WhyFlagged = case(IsOnMicrosoft and SuspName, \"Throwaway .onmicrosoft tenant + helpdesk-style name\", IsOnMicrosoft, \"Throwaway .onmicrosoft tenant\", \"Helpdesk / IT-style display name\")\r\n| extend ThreatPct = round(todouble(ThreatMessages) * 100 / TeamsMessages, 1)\r\n| project ['Sender Display Name']=SenderDisplayName, ['Sender Address']=SenderEmailAddress, ['Why Flagged']=WhyFlagged, ['Teams Messages']=TeamsMessages, ['Threat Messages']=ThreatMessages, ['Threat %']=ThreatPct, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen\r\n| sort by ['Threat Messages'] desc, ['Teams Messages'] desc\r\n| take 10", + "size": 0, + "title": "", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Teams Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Threat %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 100 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams susp senders table", + "id": "dd1d79d8-f591-4aae-bd44-6ad23a3e0ae4" + }, + { + "type": 1, + "content": { + "json": "### Who is being targeted
\r\n\r\n**Internal users receiving the most impersonation attempts. Concentrated targeting of a few users is a strong signal of a deliberate campaign - prioritize these users for security awareness training.**" + }, + "customWidth": "100", + "name": "teams imp targets header", + "id": "43112ad1-ebc9-42fb-9ebd-0dbaa862ed45" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp | summarize Detections=count(), ['Distinct Fake Senders']=dcount(FakeSenderAddress), Types=make_set(ImpersonationType,3), ['Last Seen']=max(Timestamp) by ['Targeted User']=TargetUser | top 10 by Detections", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp targets", + "id": "cc4b3f98-bfcb-4741-9abb-9ff099eb946f" + }, + { + "type": 1, + "content": { + "json": "### Impersonating senders
\r\n\r\n**The identities behind the impersonation, grouped by fake display name, sender domain, and type. Attackers rotate through many sending addresses under a single display name - Distinct Sender Addresses exposes that rotation, and a high count is itself a strong bulk-campaign signal. Use First/Last Seen to scope the campaign window.**" + }, + "customWidth": "100", + "name": "teams imp senders header", + "id": "99859796-7b69-42e7-a27a-541e0ba86cb2" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the identities behind Teams impersonation, grouped by the fake display name, sender domain, and impersonation type. Attackers rotate through many sending addresses under one display name, so Distinct Sender Addresses reveals bulk campaigns that per-address ranking would hide.\r\nlet imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp\r\n| summarize Detections=count(), SenderAddresses=dcount(FakeSenderAddress), Targets=dcount(TargetUser), FirstSeen=min(Timestamp), LastSeen=max(Timestamp) by FakeDisplayName, FakeSenderDomain, ImpersonationType\r\n| top 10 by Detections\r\n| project ['Fake Display Name']=FakeDisplayName, ['Sender Domain']=FakeSenderDomain, ['Impersonation Type']=ImpersonationType, ['Distinct Sender Addresses']=SenderAddresses, Detections, ['Targeted Users']=Targets, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Distinct Sender Addresses", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp senders", + "id": "209439a0-5be3-4e41-abe9-695552730dc8" + }, + { + "type": 1, + "content": { + "json": "### Display names abused
\r\n\r\n**The identities attackers pretend to be (for example \"IT HelpDesk\", \"Microsoft Support\"). These are the trust anchors of the social-engineering lure.**" + }, + "customWidth": "100", + "name": "teams imp names header", + "id": "e645578b-7a52-4d38-9d83-f5c500bbfe1a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp | summarize Detections=count(), ['Targeted Users']=dcount(TargetUser), ['Distinct Senders']=dcount(FakeSenderAddress) by ['Fake Display Name']=FakeDisplayName | top 10 by Detections", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Distinct Senders", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp names", + "id": "d723d72b-4e7c-431b-ae7b-980879c8bd75" + }, + { + "type": 1, + "content": { + "json": "### Look-alike sender domains
\r\n\r\n**Sending domains used for impersonation - watch for typosquats (for example rnicrosoft.com for m→rn). Add confirmed domains to your Tenant Allow/Block List.**" + }, + "customWidth": "100", + "name": "teams imp domains header", + "id": "98040a5a-bbd5-4c95-b976-5630ce48b282" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp | summarize Detections=count(), ['Targeted Users']=dcount(TargetUser), ['Display Names Used']=dcount(FakeDisplayName) by ['Sender Domain']=FakeSenderDomain | top 10 by Detections", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Display Names Used", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp domains", + "id": "94b9fa45-c889-46a7-8b80-92e5d280ad3b" + }, + { + "type": 1, + "content": { + "json": "### URL IOCs from impersonation messages
\r\n\r\n**URL domains that appeared in messages sent by impersonating senders. Threat actors deliberately mix legitimate domains (for example microsoft.com or google.com) with their malicious ones to make the lure look trustworthy, so treat this as a review list - not a blocklist. Investigate the unfamiliar or look-alike domains and block only those you confirm malicious; never block a well-known legitimate domain from this list.**" + }, + "customWidth": "100", + "name": "teams imp ioc header", + "id": "d5f4886c-7c7e-4c6f-94ca-569cabda5ede" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists URL domains that appeared in messages sent by impersonating senders, with a breakdown of how many carried Malware, Phish, or Spam verdicts. Threat actors mix legitimate and malicious domains in a single lure, so review the unfamiliar or look-alike domains and block only confirmed-malicious ones.\r\nlet imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ChatThreadId = tostring(RD.ChatThreadId);\r\nlet impThreads = imp | distinct ChatThreadId;\r\nlet impMsgs = MessageEvents\r\n | where ThreadId in (impThreads)\r\n | summarize arg_max(Timestamp, *) by TeamsMessageId\r\n | project TeamsMessageId, ThreatTypes;\r\nMessageUrlInfo\r\n| where isnotempty(UrlDomain)\r\n| join kind=inner (impMsgs) on TeamsMessageId\r\n| summarize ['URL Count']=count(), Messages=dcount(TeamsMessageId), Malware=countif(ThreatTypes has \"Malware\"), Phish=countif(ThreatTypes has \"Phish\"), Spam=countif(ThreatTypes has \"Spam\") by ['URL Domain']=UrlDomain\r\n| top 10 by ['URL Count']", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "URL Count", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Malware", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Phish", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Spam", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp ioc", + "id": "958ac65c-d56d-4a80-ba83-2ab33e8b1e2e" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Impersonation", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "c49582db-6318-423f-b806-91cbeb625ea2" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Malicious URLs and Link Warnings in Teams\r\n
\r\n\r\nTracks URLs shared through Microsoft Teams, messages that triggered a Microsoft Defender for Office 365 URL safety-tip warning, and the outcome of Teams URL clicks (allowed versus blocked) captured in UrlClickEvents.

**Recommended action:** Enable Safe Links for Microsoft Teams so links are checked at click time, and prioritize *User clicked a malicious link in Teams chat* alerts for investigation. Treat a blocked click as an attempted compromise: check whether the user went on to share credentials or run a file, and reset credentials where warranted." + }, + "name": "teams url banner", + "id": "e3ec4d65-8d1f-4303-bd8f-eb1ae521da41" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query surfaces Microsoft Teams URL-sharing and link-warning metrics for the selected period. URL-warning messages carry the Microsoft Defender for Office 365 URL safety tip.\r\nlet msgs = materialize(MessageEvents | summarize arg_max(Timestamp, *) by TeamsMessageId);\r\nunion\r\n(msgs | where SafetyTip == \"URLMessageWarning\" | summarize Count = count() | extend Details = \"Messages with URL Warning\", Ord = 1),\r\n(MessageUrlInfo | summarize Count = count() | extend Details = \"URLs Shared in Messages\", Ord = 2),\r\n(MessageUrlInfo | summarize Count = dcount(TeamsMessageId) | extend Details = \"Messages Containing URLs\", Ord = 3),\r\n(MessageUrlInfo | summarize Count = dcount(UrlDomain) | extend Details = \"Distinct URL Domains\", Ord = 4)\r\n| sort by Ord asc\r\n| project Count, Details", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams url tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b71382c7-c0f7-4f9d-9d21-e0a8bf9504ff" + }, + { + "type": 1, + "content": { + "json": "### Teams URL click outcomes over time
\r\n\r\n**Allowed versus blocked Microsoft Teams URL clicks (per selected interval) from UrlClickEvents where the click happened in the Teams workload.**" + }, + "customWidth": "66", + "name": "teams click trend header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "30818e0d-6c4b-4868-896a-ac48cb3cef86" + }, + { + "type": 1, + "content": { + "json": "### Click outcomes
\r\n\r\n**Distribution of Microsoft Teams URL click actions by type.**" + }, + "customWidth": "33", + "name": "teams click pie header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "5a882138-2241-4527-80b8-9983c5807050" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Microsoft Teams URL click outcomes over time (allowed vs blocked) using the UrlClickEvents workload filter, summarizing the data per selected interval.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(UrlClickEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(UrlClickEvents | summarize max(Timestamp));\r\nlet agg = materialize(UrlClickEvents\r\n| where Workload == \"Teams\"\r\n| summarize ClickAllowed = countif(ActionType has \"ClickAllowed\"), ClickBlocked = countif(ActionType has \"ClickBlocked\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ClickAllowed = coalesce(ClickAllowed, 0), ClickBlocked = coalesce(ClickBlocked, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "teams click trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "7a2f5559-1e3e-412a-addf-c3bf6be98502" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows Microsoft Teams URL click outcomes by action type for the selected period.\r\nUrlClickEvents\r\n| where Workload == \"Teams\"\r\n| where isnotempty(ActionType)\r\n| summarize Count = count() by ActionType", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "teams click pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "889c6bb3-438b-4575-84f2-084c1b5fd1f4" + }, + { + "type": 1, + "content": { + "json": "### Top domains shared in Teams messages
\r\n\r\n**The 10 most-shared URL domains in Microsoft Teams messages, with the number of messages each appeared in.**" + }, + "customWidth": "100", + "name": "teams top domains header", + "id": "dcb8c87c-087e-4d69-b7b7-0329296293ff" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 URL domains shared in Microsoft Teams messages by volume for the selected period.\r\nMessageUrlInfo\r\n| where isnotempty(UrlDomain)\r\n| summarize UrlCount = count(), Messages = dcount(TeamsMessageId) by UrlDomain\r\n| top 10 by UrlCount\r\n| project ['URL Domain']=UrlDomain, ['URLs Shared']=UrlCount, ['Messages']=Messages", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "URLs Shared", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams top domains table", + "id": "7561adb0-1fbe-41ce-a924-a27bcd4c5c12" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Malicious URLs", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "6d47c309-be9e-4b21-940e-7c7b282e5dc2" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Targeted Users & Risky Senders\r\n
\r\n\r\nIdentifies who is most targeted in Microsoft Teams, and profiles the external senders and domains behind risky messages - URL safety-tip warnings, first-contact senders, threat-carrying domains, and low-reputation link infrastructure - so you can spot anomalous senders before they succeed.

**Recommended action:** Prioritize the most-targeted users for phishing-resistant MFA and awareness coaching, and treat first-contact external senders and low-reputation domains as IOCs. Restrict inbound chat from unmanaged and consumer tenants, and allowlist only trusted external domains so unsolicited outsiders cannot start a conversation." + }, + "name": "teams risky banner", + "id": "0aa13d73-2e13-487c-a7c4-d90464a554d4" + }, + { + "type": 1, + "content": { + "json": "### Top targeted users (messages with threats)
\r\n\r\n**The 10 users receiving the most Microsoft Teams messages that contained a threat, expanded from each message recipient list.**" + }, + "customWidth": "100", + "name": "teams targeted header", + "id": "827dc0f6-2bb2-49b9-acf8-d7b400238594" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 users receiving Microsoft Teams messages that contained a threat, expanded from the message recipient list, with each user's total Teams messages received and the share that carried a threat. Messages are de-duplicated to the latest record per message.\r\nlet expanded = MessageEvents\r\n | summarize arg_max(Timestamp, *) by TeamsMessageId\r\n | mv-expand rd = parse_json(RecipientDetails)\r\n | extend Recipient = tostring(rd.RecipientSmtpAddress)\r\n | where isnotempty(Recipient);\r\nlet totals = expanded | summarize TotalMessages = count() by Recipient;\r\nexpanded\r\n| where isnotempty(ThreatTypes)\r\n| summarize ThreatMessages = count() by Recipient\r\n| join kind=leftouter (totals) on Recipient\r\n| extend ThreatPct = round(100.0 * ThreatMessages / TotalMessages, 1)\r\n| top 10 by ThreatMessages\r\n| project ['Recipient']=Recipient, ['Threat Messages']=ThreatMessages, ['Total Messages']=TotalMessages, ['Threat %']=ThreatPct", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams targeted users table", + "id": "79481d1b-617e-46df-b555-9f7240932dd0" + }, + { + "type": 1, + "content": { + "json": "### Top senders of URL-warning messages
\r\n\r\n**Senders whose Microsoft Teams messages most often triggered a URL safety-tip warning.**" + }, + "customWidth": "50", + "name": "teams warn senders header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "ef71d7dd-4442-4992-977d-d550aad4533c" + }, + { + "type": 1, + "content": { + "json": "### Top domains in URL-warning messages
\r\n\r\n**URL domains most frequently present in Microsoft Teams messages that triggered a URL safety-tip warning.**" + }, + "customWidth": "50", + "name": "teams warn domains header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "6f41a4ba-f832-4947-ad27-cd6b8015bd63" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 senders whose Microsoft Teams messages triggered a URL safety-tip warning for the selected period, with each sender's total Teams messages and the share that carried a warning. Messages are de-duplicated to the latest record per message.\r\nlet dedup = MessageEvents | summarize arg_max(Timestamp, *) by TeamsMessageId;\r\nlet totals = dedup | summarize TotalMessages = count() by SenderEmailAddress;\r\ndedup\r\n| where SafetyTip == \"URLMessageWarning\"\r\n| summarize WarningMessages = count() by SenderEmailAddress\r\n| join kind=leftouter (totals) on SenderEmailAddress\r\n| extend WarningPct = round(100.0 * WarningMessages / TotalMessages, 1)\r\n| top 10 by WarningMessages\r\n| project ['Sender']=SenderEmailAddress, ['Warning Messages']=WarningMessages, ['Total Messages']=TotalMessages, ['Warning %']=WarningPct", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Warning Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams warn senders table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3fa023af-79e3-407f-ac20-b0aa6e3ba511" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 URL domains appearing in Microsoft Teams messages that triggered a URL safety-tip warning, with the domain's total message appearances and the share that carried a warning.\r\nlet warned = MessageEvents | where SafetyTip == \"URLMessageWarning\" | distinct TeamsMessageId;\r\nlet totals = MessageUrlInfo | where isnotempty(UrlDomain) | summarize TotalMessages = dcount(TeamsMessageId) by UrlDomain;\r\nMessageUrlInfo\r\n| where TeamsMessageId in (warned)\r\n| summarize WarningMessages = dcount(TeamsMessageId) by UrlDomain\r\n| join kind=leftouter (totals) on UrlDomain\r\n| extend WarningPct = round(100.0 * WarningMessages / TotalMessages, 1)\r\n| top 10 by WarningMessages\r\n| project ['URL Domain']=UrlDomain, ['Warning Messages']=WarningMessages, ['Total Messages']=TotalMessages, ['Warning %']=WarningPct", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Warning Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams warn domains table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "68811015-1383-48ad-86da-4f8f9d39e4c4" + }, + { + "type": 1, + "content": { + "json": "### First-contact external senders
\r\n\r\n**External Microsoft Teams senders ordered by when they were first seen in the period (most recent first). Note: some flows tag internal-domain senders as external - to hide your own tenant domains, edit the query and uncomment the ExcludeDomains filter.**" + }, + "customWidth": "100", + "name": "teams fc senders header", + "id": "0f131ff3-d6b2-4187-b86c-ca3493594b54" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists external Microsoft Teams senders by the date they were first seen in the selected period, surfacing recent first-contact senders. Messages are de-duplicated to the latest record per message. In tenants with longer history this highlights genuinely new senders.\r\n// TIP: IsExternalThread may still surface senders from your own accepted domains. To hide them,\r\n// uncomment the ExcludeDomains line below (add your tenant domains) and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"contoso.com\"]);\r\nMessageEvents\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| where IsExternalThread == true\r\n//| where tostring(split(SenderEmailAddress, \"@\")[1]) !in~ (ExcludeDomains)\r\n| summarize FirstSeen = min(Timestamp), Messages = count(), ThreatMessages = countif(isnotempty(ThreatTypes)) by SenderEmailAddress\r\n| top 10 by FirstSeen desc\r\n| project ['Sender']=SenderEmailAddress, ['First Seen']=FirstSeen, ['Messages']=Messages, ['Threat Messages']=ThreatMessages", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true, + "sortBy": [ + { + "itemKey": "Threat Messages", + "sortOrder": 2 + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams fc senders table", + "id": "4e10a78d-8858-4dbb-9db0-e7b7d7e7636c" + }, + { + "type": 1, + "content": { + "json": "### External sender-domain risk
\r\n\r\n**External sending domains ranked by threat volume, with the mix of conversation types (1:1 chat, group chat, channel), threat breakdown, threat rate, count of messages carrying low-reputation URLs (domains on commonly-abused TLDs such as .xyz, .top, .click, .shop, .zip), and first/last-seen. A domain that is new in the period, skews toward 1:1 chats, or shows a high threat rate is anomalous and warrants review. Note: to exclude your own tenant domains, edit the query and uncomment the ExcludeDomains filter.**" + }, + "customWidth": "100", + "name": "teams anomaly header", + "id": "a91295db-8192-4828-93c5-408436e4b0e1" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query ranks external sender domains in Microsoft Teams by threat volume for the selected period, split by conversation type (1:1 chat, group chat, channel), with threat-type breakdown, threat rate, and a count of messages carrying low-reputation URL TLDs. Messages are de-duplicated to the latest record per message. New, 1:1-skewed, or high-threat-rate domains are the anomalies to review.\r\n// TIP: IsExternalThread may still surface your own accepted domains. To hide them, uncomment the\r\n// ExcludeDomains line below (add your tenant domains) and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"contoso.com\"]);\r\nlet suspTlds = dynamic([\"top\",\"xyz\",\"click\",\"link\",\"shop\",\"online\",\"site\",\"live\",\"icu\",\"cyou\",\"sbs\",\"rest\",\"quest\",\"cfd\",\"bond\",\"buzz\",\"fun\",\"space\",\"monster\",\"work\",\"tk\",\"ml\",\"ga\",\"cf\",\"gq\",\"dev\",\"app\",\"zip\",\"mov\",\"info\",\"win\",\"loan\",\"men\",\"stream\",\"country\"]);\r\nlet suspUrlMsgs = MessageUrlInfo\r\n | where isnotempty(UrlDomain)\r\n | extend Tld = tostring(split(UrlDomain, \".\")[-1])\r\n | where Tld in (suspTlds)\r\n | distinct TeamsMessageId;\r\nMessageEvents\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| where IsExternalThread == true\r\n| extend SenderDomain = tostring(split(SenderEmailAddress, \"@\")[1])\r\n| where isnotempty(SenderDomain)\r\n//| where SenderDomain !in~ (ExcludeDomains)\r\n| extend ConvType = case(isnotempty(GroupId), \"Channel\", array_length(todynamic(RecipientDetails)) > 1, \"Group chat\", \"1:1 chat\")\r\n| extend HasSuspUrl = TeamsMessageId in (suspUrlMsgs)\r\n| summarize Messages=count(), Senders=dcount(SenderEmailAddress), OneToOne=countif(ConvType==\"1:1 chat\"), GroupChat=countif(ConvType==\"Group chat\"), ChannelMsgs=countif(ConvType==\"Channel\"), ThreatMessages=countif(isnotempty(ThreatTypes)), Malware=countif(ThreatTypes has \"Malware\"), Phish=countif(ThreatTypes has \"Phish\"), Spam=countif(ThreatTypes has \"Spam\"), SuspUrlMsgs=countif(HasSuspUrl), FirstSeen=min(Timestamp), LastSeen=max(Timestamp) by SenderDomain\r\n| where ThreatMessages > 0\r\n| extend ThreatRatePct = round(100.0 * ThreatMessages / Messages, 1)\r\n| top 10 by ThreatMessages desc\r\n| project ['Sender Domain']=SenderDomain, Messages, Senders, ['1:1']=OneToOne, ['Group']=GroupChat, ['Channel']=ChannelMsgs, ['Threat Msgs']=ThreatMessages, Malware, Phish, Spam, ['Threat Rate %']=ThreatRatePct, ['Low-Rep URL Msgs']=SuspUrlMsgs, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams anomaly table", + "id": "bcd6746d-8298-495d-9d6c-2fadc6cba569" + }, + { + "type": 1, + "content": { + "json": "### Suspicious new senders (no threat verdict yet)
\r\n\r\n**External sending domains with no threat verdict yet, but that are either sending low-reputation-URL messages or showing unusual volume. These slip past threat filters - watch for new domains skewing toward 1:1 chats, an early social-engineering signal. Note: to exclude your own tenant domains, edit the query and uncomment the ExcludeDomains filter.**" + }, + "customWidth": "100", + "name": "teams newdom header", + "id": "9e3844f4-befc-4b76-a8cd-ca53fdf51d41" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query surfaces external sender domains in Microsoft Teams that have NO threat verdict yet but are sending messages with low-reputation URL TLDs or unusual volume, split by conversation type. These are early-warning senders that have not tripped a detection. Messages are de-duplicated to the latest record per message.\r\n// TIP: IsExternalThread may still surface your own accepted domains. To hide them, uncomment the\r\n// ExcludeDomains line below (add your tenant domains) and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"contoso.com\"]);\r\nlet suspTlds = dynamic([\"top\",\"xyz\",\"click\",\"link\",\"shop\",\"online\",\"site\",\"live\",\"icu\",\"cyou\",\"sbs\",\"rest\",\"quest\",\"cfd\",\"bond\",\"buzz\",\"fun\",\"space\",\"monster\",\"work\",\"tk\",\"ml\",\"ga\",\"cf\",\"gq\",\"dev\",\"app\",\"zip\",\"mov\",\"info\",\"win\",\"loan\",\"men\",\"stream\",\"country\"]);\r\nlet suspUrlMsgs = MessageUrlInfo\r\n | where isnotempty(UrlDomain)\r\n | extend Tld = tostring(split(UrlDomain, \".\")[-1])\r\n | where Tld in (suspTlds)\r\n | distinct TeamsMessageId;\r\nMessageEvents\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| where IsExternalThread == true\r\n| extend SenderDomain = tostring(split(SenderEmailAddress, \"@\")[1])\r\n| where isnotempty(SenderDomain)\r\n//| where SenderDomain !in~ (ExcludeDomains)\r\n| extend ConvType = case(isnotempty(GroupId), \"Channel\", array_length(todynamic(RecipientDetails)) > 1, \"Group chat\", \"1:1 chat\")\r\n| extend HasSuspUrl = TeamsMessageId in (suspUrlMsgs)\r\n| summarize Messages=count(), Senders=dcount(SenderEmailAddress), OneToOne=countif(ConvType==\"1:1 chat\"), GroupChat=countif(ConvType==\"Group chat\"), ChannelMsgs=countif(ConvType==\"Channel\"), ThreatMessages=countif(isnotempty(ThreatTypes)), SuspUrlMsgs=countif(HasSuspUrl), FirstSeen=min(Timestamp), LastSeen=max(Timestamp) by SenderDomain\r\n| where ThreatMessages == 0\r\n| where SuspUrlMsgs > 0 or Messages >= 5\r\n| order by SuspUrlMsgs desc, Messages desc\r\n| take 10\r\n| project ['Sender Domain']=SenderDomain, Messages, Senders, ['1:1']=OneToOne, ['Group']=GroupChat, ['Channel']=ChannelMsgs, ['Low-Rep URL Msgs']=SuspUrlMsgs, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams newdom table", + "id": "8036a5b7-b5b3-4af4-912f-bb092bb01b89" + }, + { + "type": 1, + "content": { + "json": "### Low-reputation link domains in Teams (IOC radar)
\r\n\r\n**URL domains shared in Teams that use TLDs commonly abused for phishing and malware (for example .xyz, .top, .click, .zip, .shop). Ranked by message reach, with first/last-seen. Review these domains as potential indicators - .zip and .mov are especially deceptive because links read like file names.**" + }, + "customWidth": "100", + "name": "teams tld header", + "id": "d48921f4-233c-4e0f-a97b-83e1bcaed399" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists URL domains shared in Microsoft Teams that use low-reputation TLDs commonly abused for phishing and malware, ranked by the number of Teams messages they appeared in, with first- and last-seen. Treat high-reach or newly-seen domains as candidate indicators of compromise.\r\nlet suspTlds = dynamic([\"top\",\"xyz\",\"click\",\"link\",\"shop\",\"online\",\"site\",\"live\",\"icu\",\"cyou\",\"sbs\",\"rest\",\"quest\",\"cfd\",\"bond\",\"buzz\",\"fun\",\"space\",\"monster\",\"work\",\"tk\",\"ml\",\"ga\",\"cf\",\"gq\",\"dev\",\"app\",\"zip\",\"mov\",\"info\",\"win\",\"loan\",\"men\",\"stream\",\"country\"]);\r\nMessageUrlInfo\r\n| where isnotempty(UrlDomain)\r\n| extend Tld = tostring(split(UrlDomain, \".\")[-1])\r\n| where Tld in (suspTlds)\r\n| summarize Messages=dcount(TeamsMessageId), FirstSeen=min(Timestamp), LastSeen=max(Timestamp) by ['URL Domain']=UrlDomain, ['TLD']=Tld\r\n| top 10 by Messages desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams tld table", + "id": "30d5588e-010c-474a-9c53-74b73dcc9676" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Targeted Users & Risky Senders", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "6fef737b-cb4e-4a51-9ced-bf11754a6b33" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Teams File Protection\r\n
\r\n\r\nMicrosoft Defender for Office 365 scans files shared in Microsoft Teams. These visuals show files scanned versus malware detected, and list the malicious files found.

**Recommended action:** Investigate each malicious file below and confirm it was quarantined and removed from the SharePoint or OneDrive location backing the chat. Enable Safe Attachments for SharePoint, OneDrive, and Microsoft Teams, and use attack surface reduction rules to block executable content delivered through collaboration." + }, + "name": "teams file banner", + "id": "2f01c905-dd65-4a13-9f67-c70402b2c175" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query summarizes Microsoft Teams file protection by Microsoft Defender for Office 365 - files scanned, files with malware detected, and files scanned with no detection - for the selected period.\r\nlet base = FileMaliciousContentInfo | where Workload == \"MicrosoftTeams\";\r\nunion\r\n(base | summarize Count = count() | extend Details = \"Teams Files Scanned\", Ord = 1),\r\n(base | where isnotempty(ThreatTypes) | summarize Count = count() | extend Details = \"Files with Malware Detected\", Ord = 2),\r\n(base | where isempty(ThreatTypes) | summarize Count = count() | extend Details = \"Files Scanned - No Detection\", Ord = 3)\r\n| sort by Ord asc\r\n| project Count, Details", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams file tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "9f555c51-1680-47ef-94d4-b1f8cf9dce3b" + }, + { + "type": 1, + "content": { + "json": "### Malicious files shared in Teams
\r\n\r\n**Files shared in Microsoft Teams that were detected with malware, with owner and file details.**" + }, + "customWidth": "100", + "name": "teams file table header", + "id": "4cd3274e-0c61-4722-83b7-1fccf8a94a57" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists Microsoft Teams files detected with malware by Microsoft Defender for Office 365 for the selected period.\r\nFileMaliciousContentInfo\r\n| where Workload == \"MicrosoftTeams\"\r\n| where isnotempty(ThreatTypes)\r\n| top 10 by Timestamp desc\r\n| project ['Time']=Timestamp, ['File Name']=FileName, ['Threat Type']=tostring(ThreatTypes), ['Threat Names']=ThreatNames, ['File Location']=FolderPath, ['File Owner']=FileOwnerUpn, SHA256", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams file table", + "id": "135e0e7d-7110-40ee-a377-1a5992b2ef9d" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams File Protection", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "8ecc1bae-4a06-4b1c-8952-59fb434b7cbc" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Post-Delivery ZAP Insights (Teams)\r\n
\r\n\r\nZero-hour auto purge (ZAP) removes malicious Microsoft Teams messages after delivery. These visuals summarize ZAP volume, type, result, and the senders whose messages were most often removed.

**Recommended action:** Confirm zero-hour auto purge is enabled for Microsoft Teams so newly-weaponized messages are pulled after delivery. Investigate senders with repeated ZAP removals as likely compromised or malicious accounts and block or restrict them. A rising ZAP trend can signal an active campaign that slipped past delivery-time filtering." + }, + "name": "teams zap banner", + "id": "136cfb4e-d2a5-4db0-9771-6b6380011ba0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query summarizes Microsoft Teams post-delivery ZAP (zero-hour auto purge) activity by Microsoft Defender for Office 365 for the selected period.\r\nlet zap = materialize(MessagePostDeliveryEvents);\r\nunion\r\n(zap | summarize Count = count() | extend Details = \"Total ZAP Actions\", Ord = 1),\r\n(zap | where ActionType == \"Malware ZAP\" | summarize Count = count() | extend Details = \"Malware ZAP\", Ord = 2),\r\n(zap | where ActionType == \"Phish ZAP\" | summarize Count = count() | extend Details = \"Phish ZAP\", Ord = 3),\r\n(zap | where ActionResult == \"Success\" | summarize Count = count() | extend Details = \"Successful Actions\", Ord = 4),\r\n(zap | where ActionResult == \"Failed\" | summarize Count = count() | extend Details = \"Failed Actions\", Ord = 5),\r\n(zap | where Action == \"Moved to quarantine\" | summarize Count = count() | extend Details = \"Moved to Quarantine\", Ord = 6)\r\n| sort by Ord asc\r\n| project Count, Details", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams zap tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "06980411-5e6b-4aa4-a746-351cd2b12dae" + }, + { + "type": 1, + "content": { + "json": "### ZAP actions over time
\r\n\r\n**Microsoft Teams post-delivery ZAP actions (per selected interval) split by Malware ZAP and Phish ZAP.**" + }, + "customWidth": "66", + "name": "teams zap trend header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "7fc1cfcd-3a9f-45b1-9f39-3820fce23c03" + }, + { + "type": 1, + "content": { + "json": "### ZAP by action type
\r\n\r\n**Distribution of Microsoft Teams post-delivery ZAP actions by type.**" + }, + "customWidth": "33", + "name": "teams zap pie header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "9bc0d0a3-876a-49d7-9046-31764511ca38" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Microsoft Teams post-delivery ZAP actions over time by ZAP type, summarizing the data per selected interval.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(MessagePostDeliveryEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(MessagePostDeliveryEvents | summarize max(Timestamp));\r\nlet agg = materialize(MessagePostDeliveryEvents\r\n| summarize MalwareZAP = countif(ActionType == \"Malware ZAP\"), PhishZAP = countif(ActionType == \"Phish ZAP\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, MalwareZAP = coalesce(MalwareZAP, 0), PhishZAP = coalesce(PhishZAP, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "teams zap trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "c78a509e-324f-4a8c-b2e7-bce3e0d20667" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows Microsoft Teams post-delivery ZAP actions by type for the selected period.\r\nMessagePostDeliveryEvents\r\n| summarize Count = count() by ActionType", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "teams zap pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "cfc94695-fb02-4b6c-a223-f79f7b947379" + }, + { + "type": 1, + "content": { + "json": "### Top senders whose messages were removed by ZAP
\r\n\r\n**Senders whose Microsoft Teams messages were most often removed by post-delivery ZAP.**" + }, + "customWidth": "100", + "name": "teams zap senders header", + "id": "f8677ffe-007a-41ca-81de-1ae5dd19d06a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 senders whose Microsoft Teams messages were removed by post-delivery ZAP for the selected period.\r\nMessagePostDeliveryEvents\r\n| where isnotempty(SenderEmailAddress)\r\n| summarize ZapActions = count(), MalwareZAP = countif(ActionType == \"Malware ZAP\"), PhishZAP = countif(ActionType == \"Phish ZAP\") by SenderEmailAddress\r\n| top 10 by ZapActions\r\n| project ['Sender']=SenderEmailAddress, ['ZAP Actions']=ZapActions, ['Malware ZAP']=MalwareZAP, ['Phish ZAP']=PhishZAP", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "ZAP Actions", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams zap senders table", + "id": "50c9a883-6442-40dc-b84f-57adfbb46a38" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams ZAP", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "f5cc2425-e5ae-4520-9a97-2e4c2c447dcd" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Teams Message and Call Submissions\r\n
\r\n\r\nMicrosoft Teams messages and calls reported by users, and messages submitted by admins, for review by Microsoft. Sourced from the submission records in CloudAppEvents.

**Recommended action:** Encourage users to report suspicious Teams messages and calls so Microsoft can tune protection, and triage admin submissions promptly. A cluster of reports naming the same sender, display name, or call identity is an early signal of a targeted campaign: pivot those identities into the impersonation and risky-sender views above to scope it." + }, + "name": "teams sub banner", + "id": "54cbfb29-2626-4b65-8cb5-a42ff4b41e63" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query summarizes Microsoft Teams message and call submissions reported to Microsoft for the selected period, split by user and admin reports. Only completed submissions are counted (submission triage/timeout lifecycle records are excluded).\r\nlet sub = materialize(CloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType in (\"ChatMessage\", \"TeamsCall\"));\r\nunion\r\n(sub | where SubmissionContentType == \"ChatMessage\" and ActionType == \"UserSubmission\" | summarize Count = count() | extend Details = \"Messages Reported by Users\", Ord = 1),\r\n(sub | where SubmissionContentType == \"TeamsCall\" and ActionType == \"UserSubmission\" | summarize Count = count() | extend Details = \"Calls Reported by Users\", Ord = 2),\r\n(sub | where SubmissionContentType == \"ChatMessage\" and ActionType == \"AdminSubmission\" | summarize Count = count() | extend Details = \"Messages Submitted by Admins\", Ord = 3)\r\n| sort by Ord asc\r\n| project Count, Details", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams sub tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "419ed645-ebc1-4df1-b9f0-c744403ab494" + }, + { + "type": 1, + "content": { + "json": "### Submissions over time
\r\n\r\n**Microsoft Teams user and admin submissions (per selected interval).**" + }, + "customWidth": "66", + "name": "teams sub trend header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "6a795b0a-82e2-427a-8ac0-abfb5bb5e447" + }, + { + "type": 1, + "content": { + "json": "### Submission mix
\r\n\r\n**Microsoft Teams submissions split by content type (message or call) and reporter (user or admin).**" + }, + "customWidth": "33", + "name": "teams sub pie header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "1f4c55f8-7290-4b6f-b02a-e3134568b9ff" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Microsoft Teams message and call submissions over time, summarizing the data per selected interval. Only completed submissions are counted (submission triage/timeout lifecycle records are excluded).\r\nlet gran = {Granularity};\r\nlet sub = materialize(CloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType in (\"ChatMessage\", \"TeamsCall\"));\r\nlet minTime = toscalar(sub | summarize min(Timestamp));\r\nlet maxTime = toscalar(sub | summarize max(Timestamp));\r\nlet agg = materialize(sub\r\n| summarize UserReports = countif(ActionType == \"UserSubmission\"), AdminReports = countif(ActionType == \"AdminSubmission\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, UserReports = coalesce(UserReports, 0), AdminReports = coalesce(AdminReports, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "teams sub trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "7dcb03da-de96-4388-90a4-0a3f3ca98dc6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows the mix of Microsoft Teams submissions by content type and reporter for the selected period. Only completed user submissions (chat and call) and admin submissions (chat) are counted; submission triage/timeout lifecycle records are excluded.\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\"\r\n| where (SubmissionContentType == \"ChatMessage\" and ActionType == \"UserSubmission\")\r\n or (SubmissionContentType == \"TeamsCall\" and ActionType == \"UserSubmission\")\r\n or (SubmissionContentType == \"ChatMessage\" and ActionType == \"AdminSubmission\")\r\n| extend Reporter = iif(ActionType == \"AdminSubmission\", \"Admin\", \"User\")\r\n| summarize Count = count() by SubmissionType = strcat(SubmissionContentType, \" (\", Reporter, \")\")", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "teams sub pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "84a0141e-51de-4423-acb0-3c4342a49bf2" + }, + { + "type": 1, + "content": { + "json": "### False Negative (FN) User Submissions by submission State
\r\n\r\n**Microsoft Teams messages reported by users as missed detections, broken down by submission state (for example Rescaned, Graded). Tracks the processing status of user reports.**" + }, + "customWidth": "50", + "name": "teams sub state header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "1b2bdffd-69b0-41b0-bdda-b242b7faaec0" + }, + { + "type": 1, + "content": { + "json": "### False Negative (FN) User Submissions by Triage Verdict
\r\n\r\n**Microsoft Teams user submissions grouped by the verdict assigned during grading (for example Phishing, NotSpam, Spam). Shows how reported messages were graded and highlights detection gaps.**" + }, + "customWidth": "50", + "name": "teams sub verdict header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "bdb97e09-44d2-41ad-a99f-931e4a8169cc" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows Microsoft Teams user (false negative) message submissions by submission state (for example Rescaned, Graded), to track processing status.\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend SubmissionState = tostring(RD.SubmissionState)\r\n| summarize Count = count() by tostring(SubmissionState)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub state pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "139ce840-5fc2-44d1-9872-91b37a74f0e7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows Microsoft Teams user (false negative) message submissions by the triage verdict assigned during grading (for example Phishing, NotSpam, Spam).\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend TriageVerdict = tostring(parse_json(tostring(RD.GradingResult)).TriageVerdict)\r\n| where isnotempty(TriageVerdict)\r\n| summarize Count = count() by TriageVerdict", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub verdict pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "538ce4a3-a1ff-4b8d-a466-2173edbb2cd7" + }, + { + "type": 1, + "content": { + "json": "### Top 10 P2 sender domains in FN User Submissions
\r\n\r\n**The sender domains most often reported by users as missed Microsoft Teams threats. High-volume domains are candidate sources of malicious messaging.**" + }, + "customWidth": "50", + "name": "teams sub domains header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "9b8db0c7-2bf2-4077-ae20-60146001bf23" + }, + { + "type": 1, + "content": { + "json": "### Top 10 individual P2 senders in FN User Submissions
\r\n\r\n**The individual senders most often reported by users as missed Microsoft Teams threats.**" + }, + "customWidth": "50", + "name": "teams sub senders header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "ffbe90ab-129c-47fa-9dac-50cab528ad55" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 P2 (envelope) sender domains of Microsoft Teams messages reported by users as false negatives (missed detections).\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend P2SenderDomain = tostring(RD.P2SenderDomain)\r\n| where isnotempty(P2SenderDomain)\r\n| summarize Submissions = count() by ['P2 Sender Domain']=P2SenderDomain\r\n| top 10 by Submissions", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub domains table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b18192fb-26a8-4bd1-9b07-7aeab496eae3" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 individual P2 (envelope) senders of Microsoft Teams messages reported by users as false negatives (missed detections).\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend P2Sender = tostring(RD.P2Sender)\r\n| where isnotempty(P2Sender)\r\n| summarize Submissions = count() by ['P2 Sender']=P2Sender\r\n| top 10 by Submissions", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub senders table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "7ead0a01-2b56-4225-b625-554b09350013" + }, + { + "type": 1, + "content": { + "json": "### Top 10 users performing the most FN User Submissions
\r\n\r\n**The users who report the most Microsoft Teams messages as missed detections - useful for recognising engaged reporters and spotting over-reporting.**" + }, + "customWidth": "50", + "name": "teams sub topusers header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "fb893cdd-d6d3-431a-a1d2-87652571a10d" + }, + { + "type": 1, + "content": { + "json": "### Top 10 admins performing the most FN Admin Submissions
\r\n\r\n**The admins who submit the most Microsoft Teams messages as missed detections.**" + }, + "customWidth": "50", + "name": "teams sub topadmins header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "14fca69b-e152-4a5d-bd2c-020c34c2226a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 users who reported the most Microsoft Teams messages as false negatives (missed detections), with each submitter's email (from the submission record) to disambiguate users with similar names.\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend Submitter = tostring(RD.SubmitterDisplayName), SubmitterEmail = tostring(RD.UserId)\r\n| where isnotempty(Submitter) and SubmitterEmail has \"@\"\r\n| summarize Submissions = count() by ['Submitter']=Submitter, ['Email']=SubmitterEmail\r\n| top 10 by Submissions", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub topusers table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a171a35b-35b0-46ce-a916-052a54101126" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 admins who submitted the most Microsoft Teams messages as false negatives (missed detections). The admin's own email is not present in the submission record (that would require the Identity table), so the Submitter ID (object GUID) is shown to disambiguate admins with similar names.\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"AdminSubmission\"\r\n| extend Submitter = tostring(RD.SubmitterDisplayName), SubmitterId = tostring(RD.SubmitterId)\r\n| where isnotempty(Submitter)\r\n| summarize Submissions = count() by ['Admin']=Submitter, ['Submitter ID']=SubmitterId\r\n| top 10 by Submissions", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub topadmins table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8bf37c2b-067a-4341-a192-2aa45699c3f7" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Submissions", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "eeea53a4-69d9-426e-bf9f-1789cd73bfed" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Recent Threat Detail\r\n
\r\n\r\nThe most recent Microsoft Teams phishing and malware messages, de-duplicated to the latest record per message, for investigation." + }, + "name": "teams detail banner", + "id": "4bdd917c-721f-450b-b455-45cbd5f59cc5" + }, + { + "type": 1, + "content": { + "json": "### Last 10 Teams phishing messages
\r\n\r\n**Most recent Microsoft Teams messages detected as phishing, with sender, delivery action, safety tip, team/group, and subject. TeamsMessageId is included to pivot to Advanced Hunting.**" + }, + "customWidth": "100", + "name": "teams detail phish header", + "id": "9bcf96c1-a958-4515-b171-10ec2f3ba660" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the 10 most recent Microsoft Teams messages detected as phishing by Microsoft Defender for Office 365, de-duplicated to the latest record per message. TeamsMessageId is included so analysts can pivot to Advanced Hunting.\r\nMessageEvents\r\n| where ThreatTypes has \"Phish\"\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| top 10 by Timestamp desc\r\n| project ['Time']=Timestamp, ['Sender']=SenderEmailAddress, ['Threat Types']=ThreatTypes, ['Delivery Action']=DeliveryAction, ['Safety Tip']=SafetyTip, ['Team / Group']=GroupName, ['External Thread']=IsExternalThread, ['Subject']=MessageSubject, TeamsMessageId", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams detail phish table", + "id": "3675d08f-1165-4f47-a633-e432cf96e3d5" + }, + { + "type": 1, + "content": { + "json": "### Last 10 Teams malware messages
\r\n\r\n**Most recent Microsoft Teams messages detected as malware, with sender, delivery action, safety tip, team/group, and subject. TeamsMessageId is included to pivot to Advanced Hunting.**" + }, + "customWidth": "100", + "name": "teams detail mal header", + "id": "6b9d66d2-8d89-47b0-a72a-5ee8623082dc" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the 10 most recent Microsoft Teams messages detected as malware by Microsoft Defender for Office 365, de-duplicated to the latest record per message. TeamsMessageId is included so analysts can pivot to Advanced Hunting.\r\nMessageEvents\r\n| where ThreatTypes has \"Malware\"\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| top 10 by Timestamp desc\r\n| project ['Time']=Timestamp, ['Sender']=SenderEmailAddress, ['Threat Types']=ThreatTypes, ['Delivery Action']=DeliveryAction, ['Safety Tip']=SafetyTip, ['Team / Group']=GroupName, ['External Thread']=IsExternalThread, ['Subject']=MessageSubject, TeamsMessageId", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams detail mal table", + "id": "d6e76d0a-7eee-4c05-8e92-10f9622b5ab3" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Detail", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "1e9c879b-d6be-4d36-9068-b5438abf7dd2" + }, + { + "type": 1, + "content": { + "json": "# Top Attacked Users, Top Senders, and Automatic External Email Forwarding\r\n\r\n---\r\nThis tab provides insights into **Top attacked users, Top Senders** in inbound email messages and details about **automatic external email forwarding**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "6" + }, + "name": "text - 24 - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f1a60054-44b1-432e-be7a-9d7d114ff5c7" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Top Attacked Users and Top Senders Insights\r\n
\r\n\r\nThis section provides key visuals that highlight top attacked users – individuals most frequently targeted by inbound email threats as detected by Microsoft Defender for Office 365. Offers insights into top email senders and sender domains across inbound email traffic, helping identify patterns and potential risk sources.

**Recommended action:** Apply the Strict preset to the most-attacked users and review the top sender domains as possible block-list candidates." + }, + "name": "text - 13 - Copy - Copy", + "id": "ff220902-30b8-4aef-9b79-14c913a1b2d2" + }, + { + "type": 1, + "content": { + "json": "### Top Attacked Users
\r\n\r\n**Displays the top 10 recipient email addresses that received inbound emails flagged as Spam, Phishing, or Malware. Helps identify high-risk users for targeted security awareness and policy enforcement.**" + }, + "name": "text - 13 - Copy - Copy - Copy", + "id": "58f34b9f-824d-4fcf-b2aa-d7d380aa08d5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 users that are receiving Spam, Phishing or Malware emails\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\" and EmailDirection ==\"Inbound\"\r\n| extend MDO_detection = parse_json(DetectionMethods) \r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),MalwareEmailCount = countif(FirstDetection == \"Malware\"),PhishEmailCount = countif(FirstDetection == \"Phish\"),SpamEmailCount = countif(FirstDetection == \"Spam\") by RecipientEmailAddress\r\n| extend ThreatEmailCount=(MalwareEmailCount+PhishEmailCount+SpamEmailCount)\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(ThreatEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| top 15 by ThreatEmailCount\r\n| project ['Recipient']=RecipientEmailAddress, ['Total Emails']=TotalEmailCount, ['Threat Emails']=ThreatEmailCount, ['Malware']=MalwareEmailCount, ['Phish']=PhishEmailCount, ['Spam']=SpamEmailCount, ['Bad Traffic %']=Bad_Traffic_Percentage_Inbound", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Threat Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Malware", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spam", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + } + } + ], + "filter": true, + "sortBy": [ + { + "itemKey": "$gen_bar_Threat Emails_2", + "sortOrder": 2 + } + ] + }, + "sortBy": [ + { + "itemKey": "$gen_bar_Threat Emails_2", + "sortOrder": 2 + } + ], + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 28", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e9459e78-6b43-4ef2-9596-32169d95c610" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Senders of Inbound Emails
\r\n\r\n**Displays the top 10 sender email addresses from external sources delivering inbound emails. Helps identify high-volume external senders for monitoring and policy enforcement.**" + }, + "name": "text - 13 - Copy - Copy - Copy - Copy", + "id": "eb4590a7-57c7-4728-af62-3d798afe6f2d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 senders by inbound email sending volume\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\" and EmailDirection ==\"Inbound\"\r\n| extend MDO_detection = parse_json(DetectionMethods) \r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),MalwareEmailCount = countif(FirstDetection == \"Malware\"),PhishEmailCount = countif(FirstDetection == \"Phish\"),SpamEmailCount = countif(FirstDetection == \"Spam\") by SenderFromAddress\r\n| extend ThreatEmailCount=(MalwareEmailCount+PhishEmailCount+SpamEmailCount)\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(ThreatEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| top 15 by TotalEmailCount\r\n| project ['Sender']=SenderFromAddress, ['Total Emails']=TotalEmailCount, ['Threat Emails']=ThreatEmailCount, ['Malware']=MalwareEmailCount, ['Phish']=PhishEmailCount, ['Spam']=SpamEmailCount, ['Bad Traffic %']=Bad_Traffic_Percentage_Inbound", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Threat Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Malware", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spam", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + } + } + ], + "filter": true + }, + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 28 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e4272979-1073-4c1e-9b1b-b971bc3efc33" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains of Inbound Emails
\r\n\r\n**Displays the top 10 sender domains from external sources delivering inbound emails. Helps identify high-volume external sender domains for monitoring and policy enforcement.**" + }, + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "id": "7ab63415-17ce-47f1-a614-e5e6edbe472e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 senders by inbound email sending volume\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\" and EmailDirection ==\"Inbound\"\r\n| extend MDO_detection = parse_json(DetectionMethods) \r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),MalwareEmailCount = countif(FirstDetection == \"Malware\"),PhishEmailCount = countif(FirstDetection == \"Phish\"),SpamEmailCount = countif(FirstDetection == \"Spam\") by SenderFromDomain\r\n| extend ThreatEmailCount=(MalwareEmailCount+PhishEmailCount+SpamEmailCount)\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(ThreatEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| top 15 by TotalEmailCount\r\n| project ['Sender Domain']=SenderFromDomain, ['Total Emails']=TotalEmailCount, ['Threat Emails']=ThreatEmailCount, ['Malware']=MalwareEmailCount, ['Phish']=PhishEmailCount, ['Spam']=SpamEmailCount, ['Bad Traffic %']=Bad_Traffic_Percentage_Inbound", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Threat Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Malware", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spam", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + } + } + ], + "filter": true + }, + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 28 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b593da94-b735-4fe3-a82d-18c90156e506" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "6" + }, + "name": "group - 10-Top attacked users and top senders", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "3e41cc1a-166e-4094-bc66-7e26a918b2e9" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Automatic External Email Forwarding Insights\r\n
\r\n\r\n**Email forwarding can be useful, but can also pose a security risk due to the potential disclosure of information.**\r\n
\r\n\r\nUsers can configure [Inbox rules](https://support.microsoft.com/en-US/Outlook/mail/use-rules-to-automatically-forward-messages) in Outlook or set up [SMTP forwarding](https://support.microsoft.com/en-us/office/turn-on-automatic-forwarding-in-outlook-7f2670a1-7fff-4475-8a3c-5822d63b0c8e) to automatically forward messages to external recipients. You can control automatic external email forwarding from cloud mailboxes using [Outbound spam policies](https://learn.microsoft.com/en-us/defender-office-365/outbound-spam-policies-external-email-forwarding) in Microsoft Defender for Office 365. \r\n**Attackers might exploit this capability to compromise your organization or its partners.**

**Recommended action:** Investigate external auto-forwarding - it is a common data-exfiltration path. Consider disabling auto-forwarding via the outbound spam policy unless a business case is documented." + }, + "name": "text - 8", + "id": "b04d1590-98e3-4650-9172-33e75561e1e5" + }, + { + "type": 1, + "content": { + "json": "### Automatic Email Forwarding by Type
\r\n\r\n**Displays counts of outbound emails automatically forwarded to external addresses, grouped by forwarding type (e.g., SMTP forwarding, inbox rules). Helps identify forwarding behaviors that may pose data exfiltration risks.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "c7cb7917-eaf4-4a1e-989a-75f4b6182851" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Internal Users Forwarding Emails Externally
\r\n\r\n**Displays the top 10 internal user accounts that have automatically forwarded emails to external addresses (regardless of the forwarding type used). Helps identify potential data exfiltration risks and enforce forwarding policies.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5a5d5a8c-c195-45db-a878-e6ac908cc919" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises automatic email forwarding to external email addresses by forwarding type\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| summarize count() by ForwardingType\r\n| sort by count_ desc \r\n", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "15094d98-add2-4b50-a0df-ee91fd34c6fb" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 internal senders who are automatically forwarding emails to external email addresses\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| summarize TotalForwardedMessages = count() by ForwardingUser\r\n| sort by TotalForwardedMessages desc \r\n| top 10 by TotalForwardedMessages\r\n| project ['Forwarding User']=ForwardingUser, ['Forwarded Messages']=TotalForwardedMessages\r\n\r\n", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "TotalForwardedMessages" + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "73d66038-2ea0-449d-9aeb-a1bd4b207d7f" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Internal Users Forwarding Emails Using Mailbox Rules
\r\n\r\n**Displays the top 10 internal user accounts that have automatically forwarded outbound emails to external addresses using Mailbox Rules. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "9a7b5fc3-da23-4e95-87df-542a5e3f6320" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 internal senders who are automatically forwarding emails to external email addresses using Mailbox Rules\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| where ForwardingType ==\"MbxRule\"\r\n| summarize TotalForwardedMessages = count() by ForwardingUser\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Forwarding User']=ForwardingUser, ['Forwarded Messages']=TotalForwardedMessages", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "TotalForwardedMessages" + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 30 - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f8d7b85d-944a-493f-a143-7e18277846c9" + }, + { + "type": 1, + "content": { + "json": "### Top 10 External domains Receiving Auto-Forwarded Emails (Mailbox Rules)
\r\n\r\n**Displays the top 10 external recipient email domains that received automatically forwarded emails from internal users via Mailbox Rules. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "cda99a50-b7c4-4d95-ac61-7231080a3f5d" + }, + { + "type": 1, + "content": { + "json": "### Top 10 External Recipients Receiving Auto-Forwarded Emails (Mailbox Rules)
\r\n\r\n**Displays the top 10 external recipient email addresses that received automatically forwarded emails from internal users via Mailbox Rules. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "72b01575-c33e-457c-98db-ea755c003bf0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 external domains who are recieving automatically forwarded emails using Mailbox Rules\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser),RecipientDomain = tostring(split(RecipientEmailAddress, \"@\")[1])\r\n| where ForwardingType ==\"MbxRule\"\r\n| summarize TotalForwardedMessages = count() by RecipientDomain\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Recipient Domain']=RecipientDomain, ['Forwarded Messages']=TotalForwardedMessages", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "823dec28-48b5-4be3-8e68-04301a952a62" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 external recipients who are recieving automatically forwarded emails using Mailbox Rules\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| where ForwardingType ==\"MbxRule\"\r\n| summarize TotalForwardedMessages = count() by RecipientEmailAddress\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Recipient']=RecipientEmailAddress, ['Forwarded Messages']=TotalForwardedMessages", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "14804990-bfc9-43b7-8c8d-95c2cf32ee56" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Internal Users Forwarding Emails via SMTP Forwarding
\r\n\r\n**Displays the top 10 internal user accounts that have automatically forwarded outbound emails to external addresses using SMTP Forwarding. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "fa04b313-5756-4ff7-9ee8-ec61e6b382cc" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 internal senders who are automatically forwarding emails to external email addresses using SmtpForwarding\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| where ForwardingType ==\"SmtpForwarding\"\r\n| summarize count() by ForwardingUser\r\n| top 10 by count_ desc\r\n| project ['Forwarding User']=ForwardingUser, ['Forwarded Messages']=count_", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 30 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "bed8e717-4ea7-4f71-aaa7-b70a31f4dc88" + }, + { + "type": 1, + "content": { + "json": "### Top 10 External domains receiving Auto-Forwarded Emails (SMTP Forwarding)
\r\n\r\n**Displays the top 10 external recipient email domains that received automatically forwarded emails from internal users using SMTP Forwarding. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f76bc717-3cf8-4d8d-92fa-3f2024065f8f" + }, + { + "type": 1, + "content": { + "json": "### Top 10 External Recipients Receiving Auto-Forwarded Emails (SMTP Forwarding)
\r\n\r\n**Displays the top 10 external recipient email addresses that received automatically forwarded emails from internal users using SMTP Forwarding. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "2190c799-ab4f-4bd8-87e1-f9c5c224cca4" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 external recipients who are recieving automatically forwarded emails using SmtpForwarding\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser),RecipientDomain = tostring(split(RecipientEmailAddress, \"@\")[1])\r\n| where ForwardingType ==\"SmtpForwarding\"\r\n| summarize TotalForwardedMessages = count() by RecipientDomain\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Recipient Domain']=RecipientDomain, ['Forwarded Messages']=TotalForwardedMessages", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "c3be87b3-8ce8-40f2-ad92-0651bed71117" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 external recipients who are recieving automatically forwarded emails using SmtpForwarding\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| where ForwardingType ==\"SmtpForwarding\"\r\n| summarize TotalForwardedMessages = count() by RecipientEmailAddress\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Recipient']=RecipientEmailAddress, ['Forwarded Messages']=TotalForwardedMessages", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "fb6b0113-f5bb-46a7-994b-92ebc3c7881d" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "6" + }, + "name": "group - 34 - Automatic email forwarding", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "02c91ebb-4f92-4843-a73b-6dea7a6ac2bd" + }, + { + "type": 1, + "content": { + "json": "# Email detection action overrides\r\n\r\n---\r\n\r\nThis tab provides insights into admin or end-user configured **detection overrides** where the message was detected as a threat by Microsoft Defender for Office 365, however an admin-configured policy or end-user setting overrode the detection action.[

Learn more

](https://learn.microsoft.com/en-us/defender-office-365/step-by-step-guides/understand-overrides-in-email-entity) " + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "text - 13 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "ae594968-00b9-40b8-b5dd-052a27440afb" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Admin configured Detection Overrides (Allow)\r\n
\r\n\r\nThis section consolidates key visuals that track emails subject to administrator policies (e.g., Transport Rules, Tenant Allow/Block List) with an \"Allow\" action, overriding Microsoft Defender for Office 365 detections (excluding SecOps Mailbox overrides).

**Recommended action:** Review Allow overrides that later carried threats and remove stale or overly broad allow entries - they weaken protection." + }, + "name": "text - AdminOverridesAllowHeader", + "id": "3d70a304-c590-4156-a6d4-da147fe106ab" + }, + { + "type": 1, + "content": { + "json": "### Admin Overrides (Allow) Trend\r\n**Displays the count (per {Granularity}) of emails where an administrator policy with an \"Allow\" action overrode detections (excluding SecOps Mailbox). Helps track the frequency of admin overrides over time.**" + }, + "name": "text - AdminOverridesAllowTrend", + "id": "a4ee104a-a0a1-4725-a60f-deedcc91af70" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to an admin policy with action of allow independent of action taken, summarizing the data daily\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where isnotempty(OrgLevelPolicy) and OrgLevelPolicy!=\"SecOps Mailbox\" and OrgLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalAdminOverrides = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Admin Overrides'] = coalesce(TotalAdminOverrides, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Admin Overrides", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 3", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "79928e9e-48ed-4d08-8ff7-c21fe027550e" + }, + { + "type": 1, + "content": { + "json": "### Total Emails by Admin Override type (Allow)\r\n**Summarizes the total count of emails subject to administrator policies with an \"Allow\" action, grouped by the type of override. Helps identify which policies are most frequently allowing emails.**" + }, + "customWidth": "50", + "name": "text - AdminOverridesAllowByType", + "id": "855fce09-2000-4d16-8521-8b4eeddfae00" + }, + { + "type": 1, + "content": { + "json": "### Admin Overrides (Allow) by Override Type and Threat Type\r\n**Details the count of emails allowed by administrator policies, categorized by the override type and the detected threat type. Helps assess the risk associated with allowed emails.**" + }, + "customWidth": "50", + "name": "text - AdminOverridesAllowByTypeAndThreat", + "id": "a2613078-b427-4b23-aca0-21989b1944db" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails subject to an admin policy with action of allow, independent of action taken, summarizing the data by type of override\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelPolicy!=\"SecOps Mailbox\" and OrgLevelAction == \"Allow\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by OrgLevelPolicy", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 16", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b21a0329-8f52-45c2-81f2-6df65c134673" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to an admin policy with action of allow, independent of action taken, summarizing the data by type of override and threats type found\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelPolicy!=\"SecOps Mailbox\" and OrgLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by OrgLevelAction,OrgLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=OrgLevelAction, ['Override Policy']=OrgLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 2", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "0bf4cbe6-7c84-49d4-801c-d955762b5699" + }, + { + "type": 1, + "content": { + "json": "### SecOps Mailbox Overrides (Allow)\r\nThis section focuses on emails allowed specifically due to the SecOps Mailbox override policy, typically used for investigation and analysis.[

Learn more

](https://learn.microsoft.com/en-us/defender-office-365/advanced-delivery-policy-configure) " + }, + "name": "text - SecOpsOverridesHeader", + "id": "f582dc86-4c40-4cdd-ba0b-ec6ef8820a27" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails subject to the \r\nEmailEvents \r\n| where OrgLevelPolicy==\"SecOps Mailbox\" and OrgLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by OrgLevelPolicy", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "statSettings": { + "valueAggregation": "None", + "colorSettings": { + "type": "static", + "mode": "background", + "heatmapPalette": "greenRed", + "thresholdsGrid": [] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "tagText": "", + "valueFontStyle": "auto", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 1", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8ad2fea4-dcd0-454e-a4d4-b5275c86fd9b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails delivered to the SecOps Mailbox by threat type\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelPolicy==\"SecOps Mailbox\" and OrgLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by OrgLevelAction,OrgLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=OrgLevelAction, ['Override Policy']=OrgLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", + "size": 1, + "showAnalytics": true, + "title": " ", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 4", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "52c04df2-69b5-46e4-a000-7c6d212a132a" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "group - 15 - Admin Detection Overrides - Allow", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "9b9baf2f-fd5f-41b6-8368-b515f8de4fd4" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Admin configured Detection Overrides (Block)\r\n
\r\n\r\nThis section provides insights into email messages blocked by administrative policies (e.g. Tenant allow/block list, Antimalware policy file type block), overriding detection actions defined by Microsoft Defender for Office 365.

**Recommended action:** Confirm these blocks are still needed and consolidate them into the Tenant Allow/Block List where appropriate." + }, + "name": "text - AdminOverridesBlockHeader", + "id": "6157683b-cce7-4165-886f-0da73e25ce86" + }, + { + "type": 1, + "content": { + "json": "### Admin Overrides (Block) Trend\r\n**Displays the count (per {Granularity}) of emails where an administrator policy with a \"Block\" action overrode detections. Helps track the frequency of admin blocks over time.**" + }, + "name": "text - AdminOverridesBlockTrend", + "id": "699820b4-a984-45cc-ab2f-607c3c8569d4" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to an admin policy with action of block, summarizing the data daily\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where isnotempty(OrgLevelPolicy) and OrgLevelAction == \"Block\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalAdminOverrides = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Admin Overrides'] = coalesce(TotalAdminOverrides, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Admin Overrides", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 5", + "styleSettings": { + "margin": "10", + "padding": "10" + }, + "id": "9ef5e7fb-843e-439b-b4f3-9b0bb149e74b" + }, + { + "type": 1, + "content": { + "json": "### Total Emails by Admin Override Type (Block)\r\n**Summarizes the total count of emails subject to administrator policies with a \"Block\" action, grouped by the type of override.**" + }, + "customWidth": "50", + "name": "text - AdminOverridesBlockByType", + "id": "5694a7c0-1ee5-40b4-ae2b-263d189c4b4e" + }, + { + "type": 1, + "content": { + "json": "### Admin Overrides (Block) by Override Type and Threat Type\r\n**Details the count of emails blocked by administrator policies, categorized by the override type and the detected threat type.**" + }, + "customWidth": "50", + "name": "text - AdminOverridesBlockByTypeAndThreat", + "id": "6e309742-37c0-4ad5-9b9a-63643059bfaf" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails subject to an admin policy with action of block, summarizing the data by type of override\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelAction == \"Block\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by OrgLevelPolicy", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 6", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "eabc80ed-d0e9-43d2-ab13-a5af478f11c8" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to an admin policy with action of block, summarizing the data by type of override and threats type found\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelAction == \"Block\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by OrgLevelAction,OrgLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=OrgLevelAction, ['Override Policy']=OrgLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 7", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1661bfa6-d8fd-4387-a334-1bc027a3f6d1" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "group - 36-Admin Detection Overrides - Block", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "7d514e9a-f67f-45a6-ba1b-6492348cc18b" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
User configured Detection Overrides (Allow)\r\n
\r\n\r\nThis section consolidates key visuals that track email messages subject to user policies (e.g. [Safe Senders list defined in Outlook](https://learn.microsoft.com/en-us/defender-office-365/create-safe-sender-lists-in-office-365#use-outlook-safe-senders)) with an \"Allow\" action, overriding Microsoft Defender for Office 365 detections.

**Recommended action:** Educate users that safe-sender allows can bypass protection; review high-risk user allow entries." + }, + "name": "text - UserOverridesAllowHeader", + "id": "4d41c560-0e73-40c5-b610-33e9500e88c4" + }, + { + "type": 1, + "content": { + "json": "### User Overrides (Allow) Trend\r\n**Displays the count (per {Granularity}) of emails where a user policy with an \"Allow\" action overrode detections. Helps track the frequency of user overrides over time.**" + }, + "name": "text - UserOverridesAllowTrend", + "id": "9432efff-9f03-4d74-8781-02be8b2d07fa" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to a user type policy with action of allow, summarizing the data daily\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalUserOverrides = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['User Overrides'] = coalesce(TotalUserOverrides, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "User Overrides", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 3", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "02da1d33-e477-479d-bdd3-95ab1ad7c75c" + }, + { + "type": 1, + "content": { + "json": "### Total Emails by User Override Type (Allow)\r\n**Summarizes the total count of emails subject to user policies with an \"Allow\" action, grouped by the type of override.**" + }, + "customWidth": "50", + "name": "text - UserOverridesAllowByType", + "id": "006a2e87-b1b6-4cc3-a763-ceebaa86b340" + }, + { + "type": 1, + "content": { + "json": "### User Overrides (Allow) by Override Type and Threat Type\r\n**Details the count of emails allowed by user policies, categorized by the override type and the detected threat type. Helps assess the risk associated with user-allowed emails.**" + }, + "customWidth": "50", + "name": "text - UserOverridesAllowByTypeAndThreat", + "id": "7c34bb4b-46c0-4054-9596-3dfd010bb036" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails subject to a user type policy with action of allow, summarizing the data by type of override\r\nEmailEvents \r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Allow\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by UserLevelPolicy", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 16", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d1d9021d-e6bf-47b1-bdd2-438a212d2767" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to a user type policy with action of allow, summarizing the data by type of override and threats type found\r\nEmailEvents \r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Allow\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by UserLevelAction,UserLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=UserLevelAction, ['Override Policy']=UserLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 2", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1acd913c-c945-4a58-b04e-d008ca53ffe3" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "group - 15 - User Detection Overrides - Allow", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "c939060e-6a8b-49ff-951b-a3abddbd9fb4" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
User configured Detection Overrides (Block)\r\n
\r\n\r\nThis section provides insights into emails blocked by user-configured policies (e.g., [Blocked Senders list in Outlook](https://support.microsoft.com/en-us/office/block-or-unblock-senders-in-outlook-9bf812d4-6995-4d19-901a-76d6e26939b0)).

**Recommended action:** Use user block trends to identify unwanted senders that may warrant tenant-wide blocking." + }, + "name": "text - UserOverridesBlockHeader", + "id": "be6c6a3e-08ee-47c5-b8e7-6a1078dd17d1" + }, + { + "type": 1, + "content": { + "json": "### User Overrides (Block) Trend\r\n**Displays the count (per {Granularity}) of emails where a user policy with a \"Block\" action overrode detections. Helps track the frequency of user blocks over time.**" + }, + "name": "text - UserOverridesBlockTrend", + "id": "7cd77d54-2e2b-4d23-a6a9-4bd6bca2642a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to a user type policy with action of block, summarizing the data daily\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Block\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalUserOverrides = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['User Overrides'] = coalesce(TotalUserOverrides, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "User Overrides", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 5", + "styleSettings": { + "margin": "10", + "padding": "10" + }, + "id": "0b21b66c-001d-4b3d-b47f-f3a420ccaaf8" + }, + { + "type": 1, + "content": { + "json": "### Total Emails by User Override Type (Block)\r\n**Summarizes the total count of emails subject to user policies with a \"Block\" action, grouped by the type of override.**" + }, + "customWidth": "50", + "name": "text - UserOverridesBlockByType", + "id": "fd513501-5e9d-45d9-9d0d-cd546002b8cf" + }, + { + "type": 1, + "content": { + "json": "### User Overrides (Block) by Override Type and Threat Type\r\n**Details the count of emails blocked by user policies, categorized by the override type and the detected threat type.**" + }, + "customWidth": "50", + "name": "text - UserOverridesBlockByTypeAndThreat", + "id": "4fbfa876-47ed-4c3b-81ee-1c40b982cecd" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails subject to a user type policy with action of block, summarizing the data by type of override\r\nEmailEvents \r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Block\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by UserLevelPolicy", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 6", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d3fccaa6-80fd-419d-bb37-aedf67263419" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to a user type policy with action of block, summarizing the data by type of override and threats type found\r\nEmailEvents \r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Block\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by UserLevelAction,UserLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=UserLevelAction, ['Override Policy']=UserLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 7", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e5e74ce1-fa67-45ea-bc80-97237342e370" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "group - 37-User Detection Overrides - Block", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "0c1d327a-c2f1-4b9b-b210-53c808b53b48" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
User & Sender Override Detail (Allow)\r\n
\r\n\r\nInbound messages that Microsoft Defender for Office 365 **detected as threats but delivered anyway** because of an admin- or user-configured **Allow** override (phishing-simulation and SecOps Mailbox traffic excluded). **Total Threats** is all detected threats to that recipient / sender domain in the selected range; **Overridden Threats** and **Override %** are the portion delivered due to an Allow override, and **Override Types** names the specific overrides responsible. **User-configured** overrides come from the recipient's own mailbox junk-email settings in Outlook / Outlook on the web (the mailbox \"safelist collection\") — the **Safe Senders** and **Safe Recipients** lists and **trusted contacts** (\"Also trust email from my Contacts\"). **Admin-configured** overrides come from the **Tenant Allow/Block List, Exchange mail flow (transport) rules, the IP Allow List, or allowed sender/domain lists in anti-spam policies**. Use this to spot users or domains where overrides are letting threats through — candidates for policy review or a Tenant Allow/Block List (TABL) block.

**Recommended action:** Focus on the users and sender domains with the most allow overrides - these are the biggest protection gaps." + }, + "name": "Overrides - User Detail Header", + "id": "3b0e83f3-f340-4b95-85c5-831783e8abc2" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top recipients receiving threats that were delivered due to an admin or user override, with the share of their threats that were overridden and a breakdown of which override types caused them.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend OverrideType = case(\r\n OrgLevelAction == \"Allow\" and OrgLevelPolicy != \"\" and OrgLevelPolicy != \"SecOps Mailbox\", OrgLevelPolicy,\r\n UserLevelAction == \"Allow\", strcat(\"User: \", UserLevelPolicy),\r\n \"(none)\")\r\n| summarize PerType = count() by RecipientEmailAddress, OverrideType\r\n| summarize TotalThreats = sum(PerType),\r\n OverriddenThreats = sumif(PerType, OverrideType != \"(none)\"),\r\n OverrideTypes = strcat_array(make_set_if(strcat(OverrideType, \" (\", PerType, \")\"), OverrideType != \"(none)\"), \"; \")\r\n by RecipientEmailAddress\r\n| where OverriddenThreats > 0\r\n| extend OverridePercent = round(OverriddenThreats * 100.0 / TotalThreats, 1)\r\n| top 15 by OverriddenThreats\r\n| project ['Recipient']=RecipientEmailAddress, ['Total Threats']=TotalThreats, ['Overridden Threats']=OverriddenThreats, ['Override %']=OverridePercent, ['Override Types']=OverrideTypes", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Overridden Threats", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Override %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ] + }, + "graphSettings": { + "type": 2, + "topContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Value", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + }, + "nodeIdField": "StatisticName", + "sourceIdField": "Value", + "targetIdField": "Value", + "graphOrientation": 3, + "showOrientationToggles": false, + "nodeSize": null, + "staticNodeSize": 100, + "colorSettings": null, + "hivesMargin": 5, + "edgeColorSettings": null + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "Overrides - Top Users", + "id": "d7e169a2-808a-4bbf-86ee-5be561c690f7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top sender domains sending threats to users, with the share of those threats that were delivered because of an admin or user override and a breakdown of which override types caused them. High override rates are strong candidates for policy review or a Tenant Allow/Block List (TABL) block.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend OverrideType = case(\r\n OrgLevelAction == \"Allow\" and OrgLevelPolicy != \"\" and OrgLevelPolicy != \"SecOps Mailbox\", OrgLevelPolicy,\r\n UserLevelAction == \"Allow\", strcat(\"User: \", UserLevelPolicy),\r\n \"(none)\")\r\n| summarize PerType = count() by SenderFromDomain, OverrideType\r\n| summarize TotalThreats = sum(PerType),\r\n OverriddenThreats = sumif(PerType, OverrideType != \"(none)\"),\r\n OverrideTypes = strcat_array(make_set_if(strcat(OverrideType, \" (\", PerType, \")\"), OverrideType != \"(none)\"), \"; \")\r\n by SenderFromDomain\r\n| where OverriddenThreats > 0\r\n| extend OverridePercent = round(OverriddenThreats * 100.0 / TotalThreats, 1)\r\n| top 10 by OverriddenThreats\r\n| project ['Sender Domain']=SenderFromDomain, ['Total Threats']=TotalThreats, ['Overridden Threats']=OverriddenThreats, ['Override %']=OverridePercent, ['Override Types']=OverrideTypes", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Overridden Threats", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Override %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ] + }, + "graphSettings": { + "type": 2, + "topContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Value", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + }, + "nodeIdField": "StatisticName", + "sourceIdField": "Value", + "targetIdField": "Value", + "graphOrientation": 3, + "showOrientationToggles": false, + "nodeSize": null, + "staticNodeSize": 100, + "colorSettings": null, + "hivesMargin": 5, + "edgeColorSettings": null + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "Overrides - Top Sender Domains", + "id": "0eda3153-10ea-4d4e-80ca-7e5ad99e9883" + } + ] + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "Overrides - User & Sender Detail", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "d5f38e54-a3c7-4df6-b569-bbabe85e1a36" + }, + { + "type": 1, + "content": { + "json": "# False Negative(FN) Submissions insights\r\n\r\n---\r\n\r\nThis tab provides insights into email message **False Negative(FN) Submissions** performed by users or administrators in Microsoft Defender for Office 365 where the message reported to have **Malware, Phish or Spam threat** within its **content, URLs or attachments**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "8" + }, + "name": "text - 13 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3b243dca-89ce-41e6-bccb-9ceb0953aa2e" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
False Negative(FN) Admin submissions\r\n
\r\n\r\nThis section provides insights into email message **False Negative(FN) Submissions performed by administrators** in Microsoft Defender for Office 365 where the message reported to have Malware, Phish or Spam threat within its content, URLs or attachments.

**Recommended action:** Prioritise admin-submitted misses for policy tuning; recurring sender domains may be block-list candidates." + }, + "name": "fn admin - section header", + "id": "64420254-0dae-4495-bd55-fc49e5bc1ed0" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) Admin Submissions per-{Granularity} trend by submission types \r\n**Displays counts (per {Granularity}) of False Negative(FN) Admin Submissions grouped by submission type (Spam, Phish, Malware) and content type (Mail, URL, Attachment). Helps to monitor where detections were missed and later submitted by admins as false negatives to Microsoft.**" + }, + "name": "fn admin - trend heading", + "id": "5f2de929-6f32-4079-a031-cbf689c15b29" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of admin false negative submission by submission type.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(CloudAppEvents\r\n| where ActionType contains \"Submission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| summarize Admin_Malware_FN=countif(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"), Admin_Phish_FN=countif(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"), Admin_Spam_FN=countif(SubmissionType == \"0\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"), Admin_Malware_URL_FN=countif(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\"), Admin_Malware_Attach_FN=countif(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\"), Admin_Phish_URL_FN=countif(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\"), Admin_Phish_Attach_FN=countif(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Malware (Mail)']=coalesce(Admin_Malware_FN,0), ['Phish (Mail)']=coalesce(Admin_Phish_FN,0), ['Spam (Mail)']=coalesce(Admin_Spam_FN,0), ['Malware (URL)']=coalesce(Admin_Malware_URL_FN,0), ['Malware (Attachment)']=coalesce(Admin_Malware_Attach_FN,0), ['Phish (URL)']=coalesce(Admin_Phish_URL_FN,0), ['Phish (Attachment)']=coalesce(Admin_Phish_Attach_FN,0) | sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "TotalAdminSubmissions", + "color": "redDark" + }, + { + "seriesName": "Phish (Mail)", + "color": "redBright" + }, + { + "seriesName": "Spam (Mail)", + "color": "orange" + }, + { + "seriesName": "Malware (Mail)", + "color": "redDark" + }, + { + "seriesName": "Phish (URL)", + "color": "purple" + }, + { + "seriesName": "Malware (Attachment)", + "color": "yellowDark" + }, + { + "seriesName": "Phish (Attachment)", + "color": "purpleDark" + }, + { + "seriesName": "Malware (URL)", + "color": "yellow" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "fn admin - submissions trend", + "id": "1b61155b-92a1-4533-9561-2e85e9a4dbf8" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) Admin Submissions by submission types \r\n**Displays counts (per {Granularity}) of False Negative(FN) Admin Submissions grouped by submission type (Spam, Phish, Malware) and content type (Mail, URL, Attachment).**" + }, + "customWidth": "50", + "name": "fn admin - by-type heading", + "id": "bbaa9ff9-a95d-495a-a44c-6b4cae888a24" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) Admin Submissions by submission State\r\n**Displays the total count of False Negative(FN) Admin Submissions by submission State (e.g., Pending, Completed, Failed). Helps track the processing status of admin submissions and identify bottlenecks or errors.**" + }, + "customWidth": "50", + "name": "fn admin - by-state heading", + "id": "b060c706-342a-4b2e-b81a-920bf4d8c5d9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of admin false negative submission by submission type.\r\nCloudAppEvents \r\n| where ActionType contains \"Submission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| extend Admin_SubmissionType=\r\niff(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Malware (Mail)\",\r\niff(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\r\niff(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\",\"Malware (URL)\",\r\niff(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\",\"Malware (Attachment)\",\r\niff(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\",\"Phish (URL)\",\r\niff(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\",\"Phish (Attachment)\",\r\n\"Other\")))))))\r\n| where Admin_SubmissionType!=\"Other\"\r\n| summarize count() by Admin_SubmissionType", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn admin - by-type pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "9d9d714a-357b-4ac3-bcb7-33601d3c3108" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of admin false negative submissions by the state of the submission.\r\nCloudAppEvents \r\n| where ActionType contains \"AdminSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType in (\"0\",\"1\",\"2\")\r\n| summarize count() by tostring(SubmissionState)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn admin - by-state pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "169f0f1c-1f1e-44fb-965e-850733f01879" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN)/False Positive(FP) Admin Submissions by Triage Verdict\r\n**Displays the total count of False Negative(FN)/False Positive(FP) Admin Submissions grouped by TriageVerdict (e.g., Malware, Spam, Phish, Clean). Helps assess how submissions were graded during triage and identify detection gaps.**" + }, + "customWidth": "50", + "name": "fn admin - triage-verdict heading", + "id": "3df841be-c1b0-4d61-8e38-316a34a48bd1" + }, + { + "type": 1, + "content": { + "json": "### Top Admins Submitting False Negatives \r\n**Displays the top 15 admin accounts that submitted the highest number of false negative messages (missed detections) via AdminSubmission. Helps identify key contributors to threat remediation and potential patterns in detection gaps.**" + }, + "customWidth": "50", + "name": "fn admin - top-admins heading", + "id": "e1e966f4-1f4d-4377-97c6-e2077fc0b8fa" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of admin false negative or false positive submissions by the verdict of the submission grading.\r\nCloudAppEvents \r\n| where ActionType contains \"AdminSubmissionTriage\" \r\n| extend UserKey = (parse_json(RawEventData)).UserKey, SubmissionState = (parse_json(RawEventData)).SubmissionState, SubmissionId=(parse_json(RawEventData)).SubmissionId, TriageVerdict=(parse_json(RawEventData)).GradingResult.TriageVerdict \r\n| summarize count() by tostring(TriageVerdict)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn admin - triage-verdict pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6df0db72-f9db-444e-856a-4369921d199b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top admins performing false negative submissions\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend Record= (parse_json(RawEventData)).RecordType,SubmissionState = (parse_json(RawEventData)).SubmissionState, UserId = (parse_json(RawEventData)).UserId,SubmissionType = parse_json(RawEventData).SubmissionType \r\n| where Record == 29 and SubmissionType in (\"0\",\"1\",\"2\")\r\n| summarize ['Submissions']=count() by ['Admin']=tostring(UserId)\r\n| top 15 by ['Submissions'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn admin - top-admins pie", + "id": "b5ccb4a1-9783-47cf-bf21-ded924f1a200" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) Admin Submissions by Top Sender Domains\r\n**For each top sender domain that admins reported missed threats for, shows the domain's MDO-detected threat profile (emails with threats and the Malware/Phish/Spam breakdown), the count of admin FN submissions, and the submission rate (Admin Submission % = admin submissions / total inbound from the domain). A high rate can flag a domain whose mail is frequently reported as missed.**" + }, + "customWidth": "100", + "name": "fn admin - top-sender-domains heading", + "id": "1a481c97-ac85-4b62-a86d-51b33b5a8e68" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top 10 sender domains that admins reported false negatives (missed threats) for, with each domain's MDO-detected threat profile for context.\r\nlet subs = CloudAppEvents\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType), SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), P2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"2\",\"1\",\"0\")\r\n| summarize AdminSubmissions=count() by P2SenderDomain;\r\nlet domainProfile = EmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalInbound=count(), EmailsWithThreats=countif(isnotempty(ThreatTypes)), Malware=countif(ThreatTypes has \"Malware\"), Phish=countif(ThreatTypes has \"Phish\"), Spam=countif(ThreatTypes has \"Spam\") by SenderFromDomain;\r\nsubs\r\n| join kind=leftouter (domainProfile) on $left.P2SenderDomain == $right.SenderFromDomain\r\n| extend AdminSubmissionPct = round(AdminSubmissions * 100.0 / todouble(coalesce(TotalInbound, AdminSubmissions)), 2)\r\n| top 10 by AdminSubmissions desc\r\n| project ['Sender Domain']=P2SenderDomain, ['Emails With Threats']=coalesce(EmailsWithThreats,0), ['Malware']=coalesce(Malware,0), ['Phish']=coalesce(Phish,0), ['Spam']=coalesce(Spam,0), ['Admin Submissions']=AdminSubmissions, ['Admin Submission %']=AdminSubmissionPct", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails With Threats", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Malware", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Phish", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Spam", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Admin Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "120px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Admin Submission %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "110px" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn admin - top-sender-domains table", + "id": "e56bed92-b0fb-4b76-90f3-169f4206418b" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) Admin Submissions by admin Detection override types\r\n**Displays the top 10 cases where emails were submitted as false negatives by admins, even though they were initially detected by Microsoft Defender for Office 365 but delivered due to an admin policy override. Includes details on PolicyOverride, PolicySource, and DetectionVerdict for deeper insight into override behaviour.**" + }, + "customWidth": "100", + "name": "fn admin - override-types heading", + "id": "293c174c-0197-4cf8-bbce-36fe42e5cf1b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises emails submitted as false negatives by admins where emails where already detected by MDO but there was a admin policy override\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| extend Admin_SubmissionType=\r\niff(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Malware (Mail)\",\r\niff(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\"))),\r\nP2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain),NetworkMessageId=tostring((parse_json(RawEventData).ObjectId)),DetectionVerdict=tostring((parse_json(RawEventData)).DeliveryMessageInfo.FinalFilterVerdict),PolicyOverride=tostring((parse_json(RawEventData)).DeliveryMessageInfo.PolicyOverride),PolicyPolicyOverrideType=tostring((parse_json(RawEventData)).DeliveryMessageInfo.PolicySource)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"2\",\"1\",\"0\") and PolicyOverride !=\"NoOverride\"\r\n| summarize count() by PolicyOverride, PolicyPolicyOverrideType,DetectionVerdict,Admin_SubmissionType\r\n| top 10 by count_ desc\r\n| project ['Policy Override']=PolicyOverride, ['Override Source']=PolicyPolicyOverrideType, ['Detection Verdict']=DetectionVerdict, ['Submission Type']=Admin_SubmissionType, ['Emails']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn admin - override-types table", + "id": "97799422-53e0-4e3b-8103-297fd1c744eb" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "8" + }, + "name": "group - 11-Fn Admin Submissions", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "45a1c185-4fbf-4e83-832e-1f20af427796" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
False Negative(FN) User submissions\r\n
\r\n\r\nThis section provides insights into email message **False Negative(FN) Submissions performed by end users** in Microsoft Defender for Office 365 where the message reported as having Phish, Spam threat within its content, URLs or attachments.

**Recommended action:** Recognise engaged reporters, coach over-reporters, and use graded phishing verdicts to tune anti-phishing policy." + }, + "name": "fn user - section header", + "id": "ca0b48e6-8bd8-4f99-956a-f9c72cc870db" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions per-{Granularity} trend by submission types \r\n**Displays counts (per {Granularity}) of False Negative(FN) User Submissions grouped by submission type (Spam, Phish and Attack simulations) . Helps to monitor where detections were missed and later submitted by users as false negatives.**" + }, + "name": "fn user - trend heading", + "id": "60ac8608-7875-45e6-8c83-e6bd0c34af8b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of users false negative submission by submission type, including phish simulations reported by users.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(CloudAppEvents\r\n| where ActionType contains \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| summarize User_Phish_FN=countif(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\"), User_Spam_FN=countif(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\"), User_AttackSim_Submission=countif(ActionType == \"AttackSimUserSubmission\" and SubmissionContentType==\"Mail\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Phish (Mail)']=coalesce(User_Phish_FN,0), ['Spam (Mail)']=coalesce(User_Spam_FN,0), ['Attack simulation reported']=coalesce(User_AttackSim_Submission,0) | sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "TotalAdminSubmissions", + "color": "redDark" + }, + { + "seriesName": "Phish (Mail)", + "color": "redDark" + }, + { + "seriesName": "Attack simulation reported", + "color": "green" + }, + { + "seriesName": "Spam (Mail)", + "color": "orangeDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "fn user - submissions trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "29355816-6cba-4264-938e-b0b27afdcb12" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions by submission State\r\n**Displays the total count of False Negative(FN) User Submissions by submission State (e.g., Pending, Completed, Failed). Helps track the processing status of user submissions and identify bottlenecks or errors.**" + }, + "customWidth": "50", + "name": "fn user - by-state heading", + "id": "6a4b32cc-b7e4-47bb-b1b9-f415df7e629c" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions by Triage Verdict\r\n**Displays the total count of False Negative(FN)/False Positive(FP) User Submissions grouped by TriageVerdict (e.g., Malware, Spam, Phish, Clean). Helps assess how submissions were graded during triage and identify detection gaps.**" + }, + "customWidth": "50", + "name": "fn user - triage-verdict heading", + "id": "1427e34f-be44-4517-ae73-cc4776a49fe7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of user false negative submissions by the state of the submission.\r\nCloudAppEvents \r\n| where ActionType contains \"UserSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType in (\"0\",\"1\")\r\n| summarize count() by tostring(SubmissionState)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - by-state pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a6151271-e925-4804-a3c1-06afee27c026" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of user false negative or false positive submissions by the verdict of the submission grading.\r\nCloudAppEvents \r\n| where ActionType contains \"UserSubmissionTriage\" \r\n| extend UserKey = (parse_json(RawEventData)).UserKey, SubmissionState = (parse_json(RawEventData)).SubmissionState, SubmissionId=(parse_json(RawEventData)).SubmissionId, TriageVerdict=(parse_json(RawEventData)).GradingResult.TriageVerdict \r\n| summarize count() by tostring(TriageVerdict)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - triage-verdict pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6ff319ea-b5c5-4e33-9e5c-065aadbf465d" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions of already detected Emails (from Junk folder)\r\n**Displays the total count of False Negative(FN) User Submissions where the email message was already detected by Microsoft Defender for Office 365 and the detection action was configured to deliver the message into the Junk folder of the user mailbox. It breaks down the result based on the original detection verdict determined by Microsoft Defender for Office 365. Helps track the user submissions of messages that already had a detection. Consider changing the detection action to Quarantine to avoid these submissions.**" + }, + "name": "fn user - junk-folder heading", + "id": "d6338907-489d-4c88-b82f-260fc0f9d302" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of user false negative submissions that are already detected by MDO and already delivered in the junk folder\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where DeliveryLocation == \"Junk folder\"\r\n| summarize count() by ThreatTypes,User_SubmissionType\r\n| project ThreatTypes,User_SubmissionType, Emails = count_", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - junk-folder pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "c13452cb-e864-4f01-8623-51f3ea13bbbc" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of user false negative submissions that are already detected by MDO and already delivered in the junk folder\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId,UserId = (parse_json(RawEventData)).UserId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where DeliveryLocation == \"Junk folder\"\r\n| extend MDO_detection = parse_json(DetectionMethods) \r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n| summarize TotalJunkSubmittedEmailCount=count(),PhishEmailCount = countif(FirstDetection == \"Phish\"),SpamEmailCount = countif(FirstDetection == \"Spam\") by tostring(UserId)\r\n| top 15 by TotalJunkSubmittedEmailCount desc\r\n| project ['User']=UserId, ['Junk Submissions']=TotalJunkSubmittedEmailCount, ['Phish']=PhishEmailCount, ['Spam']=SpamEmailCount", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Junk Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spam", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - junk-folder table", + "id": "b242f301-c9f7-41f9-aa73-03848bd58eae" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions - Admin review status (Mark and Notify)\r\n**Displays counts of False Negative(FN) User Submissions that were reviewed by admins and marked with a notify action. The Mark and Notify action also can be taken automatically with Automated investigation and response (AIR). Helps track cases where admins confirmed user reports and communicated the outcome, supporting transparency and user trust.**" + }, + "customWidth": "50", + "name": "fn user - mark-notify heading", + "id": "784bf171-53ae-4907-b2b0-7fc5039df231" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions accuracy vs Admin review verdict\r\n**Displays counts of False Negative(FN) User Submissions (Phish, Junk, NotJunk) compared to admin review results. Highlights whether submissions were Correct, Not Correct, or misclassified comparing user submission type with the Admin decision using Mark and Notify action in Microsoft Defender for Office 365 (e.g., “Phish reported as Junk”, “Reported but not malicious”).**" + }, + "customWidth": "50", + "name": "fn user - accuracy heading", + "id": "3d137383-6436-4213-9824-72f424b67290" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises user submissions where admin also performed 'mark and notify' action on the submission\r\nlet ReviewResults = CloudAppEvents | where ActionType == \"SubmissionNotification\" \r\n| extend SubmissionId = tostring(parse_json(RawEventData).SubmissionId)\r\n| extend Properties = parse_json(RawEventData.ExtendedProperties)\r\n| mv-expand element = Properties\r\n| where element.Name == \"AdminReviewResult\"\r\n| project SubmissionId, AdminReviewResult = element.Value;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionId = tostring(parse_json(RawEventData).SubmissionId), SubmissionType = parse_json(RawEventData).SubmissionType\r\n| join kind=leftouter ReviewResults on SubmissionId\r\n| extend UserReportedAs=iif(SubmissionType == 1, \"Phish\",iif(SubmissionType == 2, \"Junk\",iif(SubmissionType == 3, \"NotJunk\",\"\")))\r\n| extend ReviewedAccuracy=iif(UserReportedAs==AdminReviewResult, 1,0)\r\n| extend Reviewed=iif(isempty(AdminReviewResult),\"Not Reviewed\",\"Reviewed\")\r\n| project SubmissionId,UserReportedAs,Reviewed,AdminReviewResult, ReviewedAccuracy\r\n| summarize count() by Reviewed", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - mark-notify pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "7bb7d116-bd61-4e46-81dd-d634a31e7369" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises user submissions type compared to admin review verdict. \r\n//Eg. User reporting a phish but admin review is 'not threat found'\r\nlet ReviewResults = CloudAppEvents | where ActionType == \"SubmissionNotification\" \r\n| extend SubmissionId = tostring(parse_json(RawEventData).SubmissionId)\r\n| extend Properties = parse_json(RawEventData.ExtendedProperties)\r\n| mv-expand element = Properties\r\n| where element.Name == \"AdminReviewResult\"\r\n| project SubmissionId, AdminReviewResult = element.Value;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionId = tostring(parse_json(RawEventData).SubmissionId), SubmissionType = parse_json(RawEventData).SubmissionType\r\n| join kind=leftouter ReviewResults on SubmissionId\r\n| extend UserReportedAs=iif(SubmissionType == 1, \"Phish\",iif(SubmissionType == 2, \"Junk\",iif(SubmissionType == 3, \"NotJunk\",\"\")))\r\n| extend ReviewedAccuracy=iif(AdminReviewResult==UserReportedAs, \"Correct\", iif(AdminReviewResult==\"Phish\" and UserReportedAs == \"Junk\", \"Phish reported as junk\",iif(AdminReviewResult==\"Junk\" and UserReportedAs == \"Phish\",\"Junk reported as Phish\",iif(AdminReviewResult==\"NotJunk\",\"Reported but not malicious or spam\",iif(isempty(AdminReviewResult),\"Not Reviewed\",\"Not correct\")))))\r\n| extend Reviewed=iif(isempty(AdminReviewResult),\"Not Reviewed\",\"Reviewed\")\r\n| project SubmissionId,UserReportedAs,Reviewed,AdminReviewResult, ReviewedAccuracy\r\n| where Reviewed==\"Reviewed\"\r\n| summarize count() by ReviewedAccuracy", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - accuracy pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8af1b9f0-995c-4c58-9960-8e69c6960987" + }, + { + "type": 1, + "content": { + "json": "### Top 10 P2 Email Senders domains in False Negative(FN) User Submissions \r\n**Displays the top 10 P2 email sender domains of inbound emails reported by users as false negatives (missed detections). Includes total inbound email volume and calculates the percentage of user submissions per domain to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "fn user - top-p2-domains heading", + "id": "78dab1f9-09ec-46e2-aee4-f256e368cdd5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises top 10 sender domains of inbound emails submitted as false negatives by users.\r\nlet TotalInboundbySender=\r\nEmailEvents\r\n| where EmailDirection ==\"Inbound\"\r\n| summarize count() by SenderFromDomain;\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType),RecipientObjectId=AccountObjectId,NetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\"\r\n| summarize UserSubmissions=count() by SenderFromDomain\r\n| join TotalInboundbySender on SenderFromDomain\r\n| extend UserSubmissions_Percentage = todouble(round(UserSubmissions / todouble(count_) * 100, 2))\r\n| top 10 by UserSubmissions desc\r\n| project ['Sender Domain']=SenderFromDomain, ['User Submissions']=UserSubmissions, ['Total Inbound']=count_, ['User Submission %']=UserSubmissions_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "User Submission %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "12ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - top-p2-domains table", + "id": "6e6a59d4-70e1-4d85-bebb-6bb23d25d2d9" + }, + { + "type": 1, + "content": { + "json": "### Top 10 P2 Individual Email Senders in False Negative(FN) User Submissions \r\n**Displays the top 10 P2 individual email sender addresses of inbound emails reported by users as false negatives (missed detections). Includes total inbound email volume and calculates the percentage of user submissions per sender to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "fn user - top-p2-senders heading", + "id": "a6e8fda5-dd05-49ed-87e2-16443495396e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises top 10 sender email addresses of inbound emails submitted as false negatives by users.\r\nlet TotalInboundbySender=\r\nEmailEvents\r\n| where EmailDirection ==\"Inbound\"\r\n| summarize count() by SenderFromAddress;\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType),P2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain),RecipientObjectId=AccountObjectId,NetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\"\r\n| summarize UserSubmissions=count() by SenderFromAddress\r\n| join TotalInboundbySender on SenderFromAddress\r\n| extend UserSubmissions_Percentage = todouble(round(UserSubmissions / todouble(count_) * 100, 2))\r\n| top 10 by UserSubmissions desc\r\n| project ['Sender Address']=SenderFromAddress, ['User Submissions']=UserSubmissions, ['Total Inbound']=count_, ['User Submission %']=UserSubmissions_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "User Submission %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "12ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - top-p2-senders table", + "id": "878fd15f-2607-4d6d-b919-0b4bea6a1850" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Intra-org Email Senders in False Negative(FN) User Submissions \r\n**Displays the top 10 email senders of intra-org emails reported by users as false negatives (missed detections). Includes total intra-org email volume and calculates the percentage of user submissions per sender to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "fn user - intraorg-senders heading", + "id": "87a51814-7f01-42e3-aea2-4136c869d39d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises top 10 sender email address of intra-org emails submitted as false negatives by users.\r\nlet TotalInboundbySender=\r\nEmailEvents\r\n| where EmailDirection ==\"Intra-org\"\r\n| summarize count() by SenderFromAddress;\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType),P2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain),RecipientObjectId=AccountObjectId,NetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Intra-org\"\r\n| summarize UserSubmissions=count() by SenderFromAddress\r\n| join TotalInboundbySender on SenderFromAddress\r\n| extend UserSubmissions_Percentage = todouble(round(UserSubmissions / todouble(count_) * 100, 2))\r\n| top 10 by UserSubmissions desc\r\n| project ['Sender Address']=SenderFromAddress, ['User Submissions']=UserSubmissions, ['Total Intra-org']=count_, ['User Submission %']=UserSubmissions_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Intra-org", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "User Submission %", + "formatter": 4, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "12ch" + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - intraorg-senders table", + "id": "38edca4b-a403-41e8-8c2b-7c0595e93b7a" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Intra-org Email Subjects in False Negative(FN) User Submissions \r\n**Displays the top 10 Email Subjects of intra-org emails reported by users as false negatives (missed detections). Helps to highlight high-risk intra-org email sources.**" + }, + "customWidth": "100", + "name": "fn user - intraorg-subjects heading", + "id": "52b0bc5b-7e54-4a5b-a487-8a736a8c2397" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises top 10 subjects of intra-org emails submitted as false negatives by users.\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Intra-org\"\r\n| summarize count() by Subject\r\n| top 10 by count_ desc\r\n| project ['Subject']=Subject, ['User Submissions']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Subject", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "70ch" + } + }, + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - intraorg-subjects table", + "id": "ee2c1d2e-3d4e-4024-8422-985b22cb7475" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Detection Overrides defined by Admins in False Negative(FN) User Submissions \r\n**Displays the top 10 use cases where users submitted emails as false negatives (Spam or Phish) that were already detected by Microsoft Defender for Office 365 but delivered due to an admin-defined policy override. Includes details on OrgLevelAction, OrgLevelPolicy, and ThreatTypes for deeper insight into override behaviour.**" + }, + "customWidth": "100", + "name": "fn user - admin-override heading", + "id": "0dd9b3ce-9716-42bb-93de-495f0af2d075" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises emails submitted as false negatives by users where emails where already detected by MDO but there was an admin definded policy override.\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where ThreatTypes !=\"\"and OrgLevelAction!=\"\"\r\n| summarize count() by OrgLevelAction, OrgLevelPolicy,ThreatTypes,User_SubmissionType\r\n| top 10 by count_ desc\r\n| project ['Override Action']=OrgLevelAction, ['Override Policy']=OrgLevelPolicy, ['Threat Type']=ThreatTypes, ['Submission Type']=User_SubmissionType, ['User Submissions']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Override Policy", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "48ch" + } + }, + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - admin-override table", + "id": "100de6ca-beb0-44d7-a715-449a389e9e8a" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Detection Overrides defined by Users in False Negative(FN) User Submissions \r\n**Displays the top 10 use cases where users submitted emails as false negatives (Spam or Phish) that were already detected by Microsoft Defender for Office 365 but delivered due to a user-defined override. Includes details on UserLevelAction, UserLevelPolicy, and ThreatTypes for deeper insight into override behaviour.**" + }, + "customWidth": "100", + "name": "fn user - user-override heading", + "id": "67057c7d-c0af-4373-b23a-4001fbced888" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises emails submitted as false negatives by users where emails where already detected by MDO but there was an policy override.\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where ThreatTypes !=\"\"and UserLevelAction!=\"\"\r\n| summarize count() by UserLevelAction, UserLevelPolicy,ThreatTypes,User_SubmissionType\r\n| top 10 by count_ desc\r\n| project ['Override Action']=UserLevelAction, ['Override Policy']=UserLevelPolicy, ['Threat Type']=ThreatTypes, ['Submission Type']=User_SubmissionType, ['User Submissions']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Override Policy", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "48ch" + } + }, + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - user-override table", + "id": "1b97f7d2-152d-4eb0-bfac-e161fbfa4046" + }, + { + "type": 1, + "content": { + "json": "### Top 10 users performing the most False Negative(FN) User Submissions\r\n**Displays the Top 10 user accounts that performed the highest number of False Negative(FN) User Submissions (missed detections). Helps identify individuals most engaged in reporting suspicious, malicious messages and potential patterns in detection gaps.**" + }, + "customWidth": "100", + "name": "fn user - top-users heading", + "id": "7799a0a0-a835-4080-b59a-736b08ad809e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top 10 users performing false negative submissions\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType in (\"0\",\"1\")\r\n| extend UserId = (parse_json(RawEventData)).UserId\r\n| summarize ['Submissions']=count() by ['User']=tostring(UserId)\r\n| top 10 by ['Submissions'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - top-users pie", + "id": "44838734-43a0-4301-9ddb-a644c7ec509a" + }, + { + "type": 1, + "content": { + "json": "### Top 10 users performing the most User Submissions of Attack simulation messages\r\n**Displays the top 10 user accounts that reported phishing simulation emails during cyber security awareness campaigns. Supports evaluation of cyber security awareness programme effectiveness and identifies highly engaged users.**" + }, + "customWidth": "100", + "name": "fn user - attacksim-users heading", + "id": "8a96e90f-765f-40c0-8476-30c97d43c328" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top users reporting the phishing simulation emails.\r\nCloudAppEvents \r\n| extend Record= (parse_json(RawEventData)).RecordType \r\n| extend SubmissionState = (parse_json(RawEventData)).SubmissionState \r\n| extend UserId = (parse_json(RawEventData)).UserId\r\n| where Record == 29\r\n| where ActionType == \"AttackSimUserSubmission\" \r\n| summarize ['Submissions']=count() by ['User']=tostring(UserId)\r\n| top 10 by ['Submissions'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - attacksim-users pie", + "id": "ab648c4a-4c46-4c73-96f0-784c9bcef961" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "8" + }, + "name": "group - 11 - FN User submissions", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "348ce24a-7cbc-4b66-a471-dfe3827bed2d" + }, + { + "type": 1, + "content": { + "json": "# False Positive(FP) Submissions insights\r\n\r\n---\r\n\r\nThis tab provides insights into email message **False Positive(FP) Submissions** performed by users or administrators in Microsoft Defender for Office 365 where the message was flagged as a threat by Microsoft Defender for Office 365 but was later reported as No Threat by administrators or users." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "10" + }, + "name": "fp - tab description", + "id": "78e2df52-a0d2-499a-95fe-708f67db5ad6" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
False Positive(FP) Admin Submissions\r\n
\r\n\r\nAdministrator submissions represent escalated false positive reports submitted by security team members rather than end users. These typically involve more complex cases requiring expert review, such as recurring issues affecting multiple users, business-critical communications being blocked, or suspected policy misconfigurations. Admin submissions carry higher priority and can result in actions as allow-list additions or global policy changes to prevent widespread user impact.

**Recommended action:** Review recurring false-positive sender domains and consider allow entries or policy tuning to reduce business disruption." + }, + "name": "fp admin - section header", + "id": "02d54e9c-e989-4cde-a128-68a6381ed9d7" + }, + { + "type": 1, + "content": { + "json": "### Admin Submission Volume and Type Breakdown\r\n\r\n**These charts track the volume and composition of administrator-initiated false positive submissions. The trend chart shows submission patterns (per {Granularity}) across Email, URL, and Attachment types, while the pie chart reveals the distribution among these categories. Spikes in admin submissions often signal systemic issues requiring immediate policy review, as admins typically escalate only the most impactful or recurring problems.**" + }, + "name": "fp admin - volume/type heading", + "id": "103b8362-a10f-4b46-a757-8290c4269a5c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of admin false positive submission by submission type.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(CloudAppEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(CloudAppEvents | summarize max(Timestamp));\r\nlet agg = materialize(CloudAppEvents\r\n| where ActionType contains \"Submission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| summarize Admin_Email_FP=countif(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"), Admin_URL_FP=countif(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\"), Admin_Attach_FP=countif(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Email']=coalesce(Admin_Email_FP,0), ['URL']=coalesce(Admin_URL_FP,0), ['Attachment']=coalesce(Admin_Attach_FP,0) | sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "TotalAdminSubmissions", + "color": "redDark" + }, + { + "seriesName": "Admin_Phish_FN", + "color": "redBright" + }, + { + "seriesName": "Admin_Spam_FN", + "color": "orange" + }, + { + "seriesName": "Admin_Malware_FN", + "color": "redDark" + }, + { + "seriesName": "Admin_Phish_URL_FN", + "color": "purple" + }, + { + "seriesName": "Admin_Malware_Attach_FN", + "color": "yellowDark" + }, + { + "seriesName": "Admin_Phish_Attach_FN", + "color": "purpleDark" + }, + { + "seriesName": "Admin_Malware_URL_FN", + "color": "yellow" + }, + { + "seriesName": "Admin_Email_FP", + "color": "redDark" + }, + { + "seriesName": "Admin_URL_FP", + "color": "orangeDark" + }, + { + "seriesName": "Admin_Attach_FP", + "color": "yellow" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "fp admin - submissions trend", + "id": "326762ca-1f2b-48e9-90d6-ff2aa6a75e95" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of admin false positive submission by submission type.\r\nCloudAppEvents \r\n| where ActionType contains \"Submission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| extend Admin_SubmissionType=\r\niff(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Email\",\r\niff(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\",\"URL\",\r\niff(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\",\"Attachment\",\r\n\"Other\")))\r\n| where Admin_SubmissionType!=\"Other\"\r\n| summarize count() by Admin_SubmissionType", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "fp admin - by-type pie", + "id": "be925c4c-5718-4385-8e82-59c57b975ac5" + }, + { + "type": 1, + "content": { + "json": "### False Positive(FP) Admin Submissions by submission state
\r\n\r\n**Displays the total count of False Positive(FP) Admin Submissions by submission State (e.g., Pending, Completed, Failed). Helps track the processing status of admin submissions and identify bottlenecks or errors.**" + }, + "customWidth": "50", + "name": "fp admin - by-state heading", + "id": "2b2acb67-c070-48bd-acf1-025c05aae8b5" + }, + { + "type": 1, + "content": { + "json": "### Top Admins Submitting False Positives
\r\n\r\n**Displays the top 15 admin accounts that submitted the highest number of false positive messages via AdminSubmission.**" + }, + "customWidth": "50", + "name": "fp admin - top-admins heading", + "id": "52206f40-fae9-460f-97b8-2cf9b633098f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of admin false positive submissions by the state of the submission.\r\nCloudAppEvents \r\n| where ActionType contains \"AdminSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType == \"3\"\r\n| summarize count() by tostring(SubmissionState)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp admin - by-state pie", + "id": "96133d9e-24fb-417e-a3cd-df98dda4c60a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top admins performing false positive submissions.\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend Record= (parse_json(RawEventData)).RecordType,SubmissionState = (parse_json(RawEventData)).SubmissionState, UserId = (parse_json(RawEventData)).UserId,SubmissionType = parse_json(RawEventData).SubmissionType \r\n| where Record == 29 and SubmissionType ==\"3\"\r\n| summarize ['Submissions']=count() by ['Admin']=tostring(UserId)\r\n| top 15 by ['Submissions'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp admin - top-admins pie", + "id": "da7b4c89-904d-4917-b6cd-04b32e02d4a1" + }, + { + "type": 1, + "content": { + "json": "### Admin Submission False Positive Malware Detection Breakdown\r\n**Shows the count of administrator-submitted false positive reports (legitimate emails flagged as malware) grouped by the detection method that flagged them. Helps identify which filtering technologies most often misclassify valid messages as malware.**" + }, + "customWidth": "100", + "name": "fp admin - malware-detection heading", + "id": "69d649e0-86fd-4c08-afd4-e6c200b11c86" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Admin false positive submissions whose original verdict was Malware, grouped by the detection method that flagged them. A high count means that method most often misclassifies legitimate mail as Malware.\r\nlet total = toscalar(CloudAppEvents\r\n | where ActionType == \"AdminSubmissionSubmitted\"\r\n | extend R = parse_json(RawEventData)\r\n | where tostring(R.SubmissionContentType) == \"Mail\" and tostring(R.SubmissionType) == \"3\" and tostring(R.DeliveryMessageInfo.FinalFilterVerdict) == \"Malware\"\r\n | count);\r\nCloudAppEvents\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), DetectionMethod = tostring(R.DeliveryMessageInfo.FinalFilterVerdictControlSource), DetectionVerdict = tostring(R.DeliveryMessageInfo.FinalFilterVerdict), P2SenderDomain = tostring(R.P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\" and DetectionVerdict == \"Malware\"\r\n| extend DetectionMethod = iif(isempty(DetectionMethod), \"Not specified\", DetectionMethod)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(P2SenderDomain) by DetectionMethod\r\n| extend Pct = iif(total == 0, 0.0, round(FPSubmissions * 100.0 / total, 1))\r\n| sort by FPSubmissions desc\r\n| project ['Detection Method'] = DetectionMethod, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains, ['% of Malware FPs'] = Pct", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "% of", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp admin - malware-detection table", + "id": "607eb19b-1ded-488d-98db-8b23f9e90967" + }, + { + "type": 1, + "content": { + "json": "### Admin Submission False Positive Phish Detection Breakdown\r\n**Shows the count of administrator-submitted false positive reports (legitimate emails flagged as phishing) grouped by the detection method that flagged them. Helps identify which filtering technologies most often misclassify valid messages as phishing.**" + }, + "customWidth": "100", + "name": "fp admin - phish-detection heading", + "id": "c1f1e12f-d0aa-4023-9172-8182772b3331" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Admin false positive submissions whose original verdict was Phish, grouped by the detection method that flagged them. A high count means that method most often misclassifies legitimate mail as Phish.\r\nlet total = toscalar(CloudAppEvents\r\n | where ActionType == \"AdminSubmissionSubmitted\"\r\n | extend R = parse_json(RawEventData)\r\n | where tostring(R.SubmissionContentType) == \"Mail\" and tostring(R.SubmissionType) == \"3\" and tostring(R.DeliveryMessageInfo.FinalFilterVerdict) == \"Phish\"\r\n | count);\r\nCloudAppEvents\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), DetectionMethod = tostring(R.DeliveryMessageInfo.FinalFilterVerdictControlSource), DetectionVerdict = tostring(R.DeliveryMessageInfo.FinalFilterVerdict), P2SenderDomain = tostring(R.P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\" and DetectionVerdict == \"Phish\"\r\n| extend DetectionMethod = iif(isempty(DetectionMethod), \"Not specified\", DetectionMethod)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(P2SenderDomain) by DetectionMethod\r\n| extend Pct = iif(total == 0, 0.0, round(FPSubmissions * 100.0 / total, 1))\r\n| sort by FPSubmissions desc\r\n| project ['Detection Method'] = DetectionMethod, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains, ['% of Phish FPs'] = Pct", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "% of", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp admin - phish-detection pie", + "id": "b6c074f9-affa-41a3-802a-53541394ae73" + }, + { + "type": 1, + "content": { + "json": "### Admin Submission False Positive Spam Detection Breakdown\r\n**Shows the count of administrator-submitted false positive reports (legitimate emails flagged as spam) grouped by the detection method that flagged them. Helps identify which filtering technologies most often misclassify valid messages as spam.**" + }, + "customWidth": "100", + "name": "fp admin - spam-detection heading", + "id": "f0f2adb9-34af-4df0-90e6-087a265bedf6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Admin false positive submissions whose original verdict was Spam, grouped by the detection method that flagged them. A high count means that method most often misclassifies legitimate mail as Spam.\r\nlet total = toscalar(CloudAppEvents\r\n | where ActionType == \"AdminSubmissionSubmitted\"\r\n | extend R = parse_json(RawEventData)\r\n | where tostring(R.SubmissionContentType) == \"Mail\" and tostring(R.SubmissionType) == \"3\" and tostring(R.DeliveryMessageInfo.FinalFilterVerdict) == \"Spam\"\r\n | count);\r\nCloudAppEvents\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), DetectionMethod = tostring(R.DeliveryMessageInfo.FinalFilterVerdictControlSource), DetectionVerdict = tostring(R.DeliveryMessageInfo.FinalFilterVerdict), P2SenderDomain = tostring(R.P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\" and DetectionVerdict == \"Spam\"\r\n| extend DetectionMethod = iif(isempty(DetectionMethod), \"Not specified\", DetectionMethod)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(P2SenderDomain) by DetectionMethod\r\n| extend Pct = iif(total == 0, 0.0, round(FPSubmissions * 100.0 / total, 1))\r\n| sort by FPSubmissions desc\r\n| project ['Detection Method'] = DetectionMethod, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains, ['% of Spam FPs'] = Pct", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "% of", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp admin - spam-detection pie", + "id": "e877d9c9-3bd3-4368-997e-945f18ffcf5f" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains for Admin False Positive Submissions
\r\n\r\n**Lists the top 10 sender domains of emails reported as false positives by administrators (legitimate messages incorrectly flagged as spam or phishing). Helps identify domains frequently misclassified.**" + }, + "customWidth": "50", + "name": "fp admin - top-sender-domains heading", + "id": "37680101-7e4b-4bcc-9e7e-0ccd2d914881" + }, + { + "type": 1, + "content": { + "json": "### Admin False Positive Submissions by Original Threat Verdict
\r\n\r\n**Displays all administrator-submitted false positive emails by their original filter verdict (e.g., spam, phishing) and policy override details. Helps identify which threat categories are most often misclassified.**" + }, + "customWidth": "50", + "name": "fp admin - by-verdict heading", + "id": "879e81ad-00a6-4a10-bcb6-56879133bb9f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top 10 sender domains of emails which are submitted as false positive by admins\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType),P2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType ==\"3\"\r\n| summarize count() by P2SenderDomain\r\n| top 10 by count_ desc\r\n| project ['Sender Domain']=P2SenderDomain, ['Emails']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp admin - top-sender-domains table", + "id": "42844dc9-4418-487b-a5ad-31e1f6b4b487" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises all emails submitted as false positive by admins summarizing by the original filter verdict threat type\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| extend Admin_SubmissionType=\r\niff(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\" ,\"Email\",\r\n\"Other\"),\r\nP2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain),NetworkMessageId=tostring((parse_json(RawEventData).ObjectId)),DetectionVerdict=tostring((parse_json(RawEventData)).DeliveryMessageInfo.FinalFilterVerdict),PolicyOverride=tostring((parse_json(RawEventData)).DeliveryMessageInfo.PolicyOverride),PolicyPolicyOverrideType=tostring((parse_json(RawEventData)).DeliveryMessageInfo.PolicySource)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| summarize count() by PolicyOverride,DetectionVerdict,Admin_SubmissionType\r\n| top 10 by count_ desc\r\n| project ['Policy Override']=PolicyOverride, ['Detection Verdict']=DetectionVerdict, ['Submission Type']=Admin_SubmissionType, ['Emails']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp admin - by-verdict table", + "id": "3ebbd402-06ef-45a7-b4ee-c5938b98b540" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "10" + }, + "name": "fp admin - group", + "styleSettings": { + "showBorder": true + }, + "id": "b6215b53-c181-4693-a14f-441809f65f38" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
False Positive (FP) User Submissions\r\n
\r\n\r\nThis section provides insights into email message False Postive(FP) Submissions performed by end users in Microsoft Defender for Office 365 where the message was flagged as a threat by Microsoft Defender for Office 365 but was later reported as No Threat by users. User submissions are critical feedback mechanisms that help security teams identify overly aggressive detection rules, refine security policies, and reduce user friction. High false positive rates can erode user trust and lead to security fatigue, so monitoring these metrics helps balance protection with productivity.

**Recommended action:** High user false-positive volume suggests over-aggressive filtering - review the affected senders and adjust policy." + }, + "name": "fp user - section header", + "id": "0d93d7ee-a61e-43b7-bdcd-172bd79ad050" + }, + { + "type": 1, + "content": { + "json": "### User Submission Trend\r\n\r\n**Displays the volume (per {Granularity}) of false positive submissions from end users. A sudden spike may indicate a new detection rule causing widespread misclassification, while a declining trend suggests improving detection accuracy. Monitoring this trend helps security teams respond quickly to detection issues before they impact user productivity.**" + }, + "name": "fp user - trend heading", + "id": "c3f8ae45-0498-4fa8-b9d1-35e926932639" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of user false positive submission by submission type.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(CloudAppEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(CloudAppEvents | summarize max(Timestamp));\r\nlet agg = materialize(CloudAppEvents\r\n| where ActionType contains \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where SubmissionType == \"3\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\"\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['User FP Submissions'] = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "User FP Submissions", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - submissions trend", + "id": "847032f5-56a8-4681-9665-9e917c7c9355" + }, + { + "type": 1, + "content": { + "json": "### User False Positive Submissions by State
\r\n\r\n**Displays the total number of user-reported false positive email submissions grouped by their processing state (e.g., pending, completed). Helps track submission workflow and resolution progress.**" + }, + "customWidth": "50", + "name": "fp user - by-state heading", + "id": "7bd03278-7734-4fbf-a502-95b42e90160e" + }, + { + "type": 1, + "content": { + "json": "### Top Users Performing False Positive Submissions
\r\n\r\n**Lists the top 15 users who reported emails as false positives (legitimate messages incorrectly flagged as threats). Helps identify frequent reporters and potential training or policy adjustment needs.**" + }, + "customWidth": "50", + "name": "fp user - top-users heading", + "id": "7e2b987b-325d-4f69-8d6b-fafd6676a03a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of user false positive submission by submission state.\r\nCloudAppEvents \r\n| where ActionType contains \"UserSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType == \"3\"\r\n| summarize count() by tostring(SubmissionState)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp user - by-state pie", + "id": "df79d08b-3eac-4101-a3f2-3a4a3bf450ce" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top users performing false positive submissions.\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType == \"3\"\r\n| extend UserId = (parse_json(RawEventData)).UserId\r\n| summarize ['Submissions']=count() by ['User']=tostring(UserId)\r\n| top 15 by ['Submissions'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp user - top-users pie", + "id": "ec7505d8-3a70-4bde-a985-baf5a0c4ec34" + }, + { + "type": 1, + "content": { + "json": "### User Submission False Positive Malware Detection Breakdown\r\n**Shows the count of user-submitted false positive reports (legitimate emails flagged as malware) grouped by the detection technique that flagged them. Malware quarantine is admin-only by default, so this table only populates when a custom quarantine policy lets users view and report their own malware detections - it is usually empty.**" + }, + "customWidth": "100", + "name": "fp user - malware-verdict heading", + "id": "693b1072-5ddd-49d0-a0f5-2bba4c287edf" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//User false positive submissions whose email was originally flagged as Malware, by the detection technique that flagged it. A high count means that technique most often misclassifies legitimate mail as Malware.\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has \"Malware\"\r\n| mv-expand Technique = parse_json(DetectionMethods).Malware to typeof(string)\r\n| where isnotempty(Technique)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(SenderFromDomain) by Technique\r\n| sort by FPSubmissions desc\r\n| project ['Detection Technique'] = Technique, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "22ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - malware-verdict table", + "id": "10ea55bd-937e-454d-b6cc-a9dccfdf3417" + }, + { + "type": 1, + "content": { + "json": "### User Submission False Positive Phish Detection Breakdown\r\n**Shows the count of user-submitted false positive reports (legitimate emails flagged as phishing) grouped by the detection technique that flagged them. Helps identify which filtering technologies most often misclassify valid messages as phishing.**" + }, + "customWidth": "100", + "name": "fp user - phish-verdict heading", + "id": "6dd14abb-2772-4271-89d8-8c0dcdbfd9e5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//User false positive submissions whose email was originally flagged as Phish, by the detection technique that flagged it. A high count means that technique most often misclassifies legitimate mail as Phish.\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has \"Phish\"\r\n| mv-expand Technique = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Technique)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(SenderFromDomain) by Technique\r\n| sort by FPSubmissions desc\r\n| project ['Detection Technique'] = Technique, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "22ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - phish-verdict pie", + "id": "57049aad-eb17-4e65-a8a4-b5d05b0501cd" + }, + { + "type": 1, + "content": { + "json": "### User Submission False Positive Spam Detection Breakdown\r\n**Shows the count of user-submitted false positive reports (legitimate emails flagged as spam) grouped by the detection technique that flagged them. Helps identify which filtering technologies most often misclassify valid messages as spam.**" + }, + "customWidth": "100", + "name": "fp user - spam-verdict heading", + "id": "5479b2ed-b629-41e7-9857-c91191b09c8f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//User false positive submissions whose email was originally flagged as Spam, by the detection technique that flagged it. A high count means that technique most often misclassifies legitimate mail as Spam.\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has \"Spam\"\r\n| mv-expand Technique = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Technique)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(SenderFromDomain) by Technique\r\n| sort by FPSubmissions desc\r\n| project ['Detection Technique'] = Technique, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "22ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - spam-verdict pie", + "id": "45a2122e-0281-4602-906d-a0406ed20d54" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains for User False Positive Submissions
\r\n\r\n**Lists the top 10 sender domains of emails reported as false positives by users (legitimate messages incorrectly flagged as threats). Helps identify domains frequently misclassified.**" + }, + "customWidth": "100", + "name": "fp user - top-sender-domains heading", + "id": "2751fca4-3ac5-45fe-a965-8c811018926a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top 10 sender domains reported as false positives by users, with each domain's total inbound volume and the share of it reported as FP (a high rate flags a domain whose legitimate mail is most often misclassified).\r\nlet totalByDomain = EmailEvents | where EmailDirection == \"Inbound\" | summarize TotalInbound = count() by SenderFromDomain;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), P2SenderDomain = tostring(R.P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| summarize FPSubmissions = count() by P2SenderDomain\r\n| join kind=leftouter (totalByDomain) on $left.P2SenderDomain == $right.SenderFromDomain\r\n| extend FPPct = iif(isnull(TotalInbound) or TotalInbound == 0, 0.0, round(FPSubmissions * 100.0 / TotalInbound, 2))\r\n| top 10 by FPSubmissions desc\r\n| project ['Sender Domain'] = P2SenderDomain, ['FP Submissions'] = FPSubmissions, ['Total Inbound'] = coalesce(TotalInbound, 0), ['FP Submission %'] = FPPct", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "18ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "FP Submission %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - top-sender-domains table", + "id": "c69b126d-9f25-44a0-b96d-601d89a563f1" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Senders in User False Positive Submissions
\r\n\r\n**Displays the top 10 email senders whose messages were reported as false positives by users (legitimate emails incorrectly flagged as threats). Helps identify senders frequently misclassified.**" + }, + "customWidth": "100", + "name": "fp user - top-senders heading", + "id": "b39966ad-2b40-4144-ae3f-c7ac6b9fb97c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top 10 email senders reported as false positives by users, with each sender's total inbound volume and the share reported as FP.\r\nlet totalBySender = EmailEvents | where EmailDirection == \"Inbound\" | summarize TotalInbound = count() by SenderMailFromAddress;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\"\r\n| summarize FPSubmissions = count() by SenderMailFromAddress\r\n| join kind=leftouter (totalBySender) on SenderMailFromAddress\r\n| extend FPPct = iif(isnull(TotalInbound) or TotalInbound == 0, 0.0, round(FPSubmissions * 100.0 / TotalInbound, 2))\r\n| top 10 by FPSubmissions desc\r\n| project ['Sender Address'] = SenderMailFromAddress, ['FP Submissions'] = FPSubmissions, ['Total Inbound'] = coalesce(TotalInbound, 0), ['FP Submission %'] = FPPct", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "18ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "FP Submission %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - top-senders table", + "id": "077ab610-58ed-4d23-886c-dbf912cef2d7" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Subjects in User False Positive Submissions
\r\n\r\n**Displays the top 10 email subjects reported as false positives by users (legitimate messages incorrectly flagged as threats). Helps identify common patterns in misclassified emails.**" + }, + "customWidth": "100", + "name": "fp user - top-subjects heading", + "id": "a5b939e1-0fbf-4ee1-a6a3-01fa7639af3a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top 10 email subjects reported as false positives by users, with how many distinct recipients reported each (a subject reported by many users is a broad misclassification pattern).\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\"\r\n| summarize FPSubmissions = count(), DistinctRecipients = dcount(RecipientObjectId) by Subject\r\n| top 10 by FPSubmissions desc\r\n| project ['Subject'] = Subject, ['FP Submissions'] = FPSubmissions, ['Distinct Recipients'] = DistinctRecipients", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Subject", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "70ch" + } + }, + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Recipients", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "18ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - top-subjects table", + "id": "71d5c290-f5d0-493c-b821-b5345dbe7312" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Intra-Org Senders in User False Positive Submissions
\r\n\r\n**Displays the top 10 internal senders whose emails were reported as false positives by users (legitimate intra-org messages incorrectly flagged as threats). Helps identify internal communication patterns causing misclassification.**" + }, + "customWidth": "100", + "name": "fp user - intraorg-senders heading", + "id": "1d38f458-dfde-4608-ad7d-ee8628e85ee7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top 10 internal senders whose emails were reported as false positives by users, with total intra-org volume and the share reported as FP.\r\nlet totalBySender = EmailEvents | where EmailDirection == \"Intra-org\" | summarize TotalIntraOrg = count() by SenderMailFromAddress;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Intra-org\"\r\n| summarize FPSubmissions = count() by SenderMailFromAddress\r\n| join kind=leftouter (totalBySender) on SenderMailFromAddress\r\n| extend FPPct = iif(isnull(TotalIntraOrg) or TotalIntraOrg == 0, 0.0, round(FPSubmissions * 100.0 / TotalIntraOrg, 2))\r\n| top 10 by FPSubmissions desc\r\n| project ['Sender Address'] = SenderMailFromAddress, ['FP Submissions'] = FPSubmissions, ['Total Intra-org'] = coalesce(TotalIntraOrg, 0), ['FP Submission %'] = FPPct", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Intra-org", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "18ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "FP Submission %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - intraorg-senders table", + "id": "b6699a7f-897a-4016-ae2c-d816f3a9492b" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "10" + }, + "name": "fp user - group", + "styleSettings": { + "showBorder": true + }, + "id": "2ad3311e-e92b-4a49-bdd0-775f085c4587" + }, + { + "type": 1, + "content": { + "json": "# File Malware Detections (SharePoint, Teams and OneDrive)\r\n\r\n---\r\n\r\nThis tab provides insights into malicious file detections across Microsoft collaboration platforms such as SharePoint, OneDrive, and Teams.\r\n\r\n[

Safe Attachments for SharePoint, OneDrive, and Microsoft Teams

](https://learn.microsoft.com/en-us/defender-office-365/safe-attachments-for-spo-odfb-teams-about)\r\n[

Built-in virus protection in SharePoint, SharePoint Embedded, OneDrive, and Microsoft Teams

](https://learn.microsoft.com/en-us/defender-office-365/anti-malware-protection-for-spo-odfb-teams-about) " + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "9" + }, + "name": "filemal - tab description", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "cefcac88-f373-4748-b0ea-e7600f63edd7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Microsoft Defender for Office 365 value for files in SharePoint / OneDrive / Teams: total files processed, how many had a malware detection, and how many were scanned with no detection. A per-period Trend series feeds the tile sparkline.\r\nlet gran = {Granularity};\r\nlet base = FileMaliciousContentInfo;\r\nlet counts = union\r\n(base | summarize Count = count() | extend Cat = \"Total Files Processed (SPO/ODB/Teams)\", Ord = 1),\r\n(base | where isnotempty(ThreatTypes) | summarize Count = count() | extend Cat = \"Files with Malware Detected\", Ord = 2),\r\n(base | where isempty(ThreatTypes) | summarize Count = count() | extend Cat = \"Files Scanned - No Detection\", Ord = 3);\r\nlet tagged = union\r\n(base | extend Cat = \"Total Files Processed (SPO/ODB/Teams)\"),\r\n(base | where isnotempty(ThreatTypes) | extend Cat = \"Files with Malware Detected\"),\r\n(base | where isempty(ThreatTypes) | extend Cat = \"Files Scanned - No Detection\");\r\nlet trends = tagged | make-series Trend = count() default = 0 on Timestamp step gran by Cat;\r\ncounts\r\n| join kind=leftouter (trends) on Cat\r\n| sort by Ord asc\r\n| project Count, Details = Cat, Trend", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "filemal - MDO value tiles", + "id": "843e58a9-6324-4a90-a652-bfb0549e79dc", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "9" + } + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
File Malware Detection (SharePoint, OneDrive, and Teams)\r\n
\r\n\r\nThis section monitors malware detections in files stored across Microsoft 365 collaboration platforms. Microsoft Defender for Office 365 and built-in SharePoint Online antivirus work together to scan files uploaded to SharePoint, OneDrive, and Teams. Understanding file-based malware patterns helps protect collaborative workspaces and identify potential security risks in shared content.

**Recommended action:** For repeat file owners or sites, investigate possible compromise and confirm Safe Attachments for SharePoint, OneDrive and Teams is enabled." + }, + "name": "filemal - section header", + "id": "373fe4e5-fc90-49cf-93ba-c8b100efce57" + }, + { + "type": 1, + "content": { + "json": "### File Malware Detection Trend
\r\n\r\n**This visual tracks the volume (per {Granularity}) of malware detections in files across all Microsoft 365 workloads. Spikes in detection activity may indicate targeted attacks or emerging malware campaigns affecting collaborative platforms. Regular monitoring helps identify unusual patterns that require investigation.**" + }, + "name": "filemal - trend heading", + "id": "30145585-8998-443a-b6ec-062d136c621f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total files located on SharePoint, OneDrive and Teams with Malware detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(FileMaliciousContentInfo\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Files']=coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "tileSettings": { + "showBorder": false + }, + "graphSettings": { + "type": 0 + }, + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Files", + "color": "blueDark" + } + ], + "showDataPoints": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "filemal - detection trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d39cea9b-75a8-4c29-bfdb-2e0db855e98a" + }, + { + "type": 1, + "content": { + "json": "### Malware Family Analysis - Defender for Office 365\r\n**Provides a breakdown of malware detections in files scanned by Microsoft Defender for Office 365 (Safe Attachments detonation) across SharePoint, OneDrive, and Teams. The table lists each malware family with total detections, distinct files, affected locations and when it was last seen, helping identify dominant threats and their spread across collaboration platforms.**" + }, + "customWidth": "100", + "name": "filemal - family MDO heading", + "id": "4e330873-f732-4d37-a7b0-dced08b019b0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query summarizes File malware detections by Microsoft Defender for Office 365 (Safe Attachments detonation) into a per-family table: total detections, distinct files, affected locations (file owner or site) and when the family was last seen.\r\nFileMaliciousContentInfo\r\n| where tostring(DetectionMethods) contains \"detonation\"\r\n| extend Owner = iff(isnotempty(FileOwnerUpn), FileOwnerUpn, strcat(\"Site: \", tostring(split(FolderPath, \"/\")[4])))\r\n| summarize ['Files']=count(), ['Distinct Files']=dcount(SHA256), ['Affected Locations']=dcount(Owner), ['Last Seen']=max(Timestamp) by ThreatNames\r\n| sort by ['Files'] desc\r\n| project ['Threat Name']=ThreatNames, ['Files'], ['Distinct Files'], ['Affected Locations'], ['Last Seen']", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "tileSettings": { + "showBorder": false, + "titleContent": { + "columnMatch": "RawinfoVirusInfo", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "count_", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "graphSettings": { + "type": 0, + "topContent": { + "columnMatch": "RawinfoVirusInfo", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "count_", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "chartSettings": { + "xAxis": "RawinfoVirusInfo", + "createOtherGroup": 15 + }, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Files", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "filemal - family MDO table", + "id": "c3fbb1c9-be67-43b9-9a32-7fb265a84ffc" + }, + { + "type": 1, + "content": { + "json": "### Malware Family Analysis - SharePoint AV\r\n**Provides a breakdown of malware detections in files across SharePoint, OneDrive, and Teams caught by the built-in SharePoint antivirus (Antimalware engine). The table lists each malware family with total detections, distinct files, affected locations and when it was last seen, helping identify prevalent threats and their spread across collaboration environments.**" + }, + "customWidth": "100", + "name": "filemal - family SPO-AV heading", + "id": "331a8361-6e81-4615-b33a-97ebb3e31529" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query summarizes File malware detections by the built-in SharePoint antivirus (Antimalware engine) into a per-family table: total detections, distinct files, affected locations (file owner or site) and when the family was last seen.\r\nFileMaliciousContentInfo\r\n| where tostring(DetectionMethods) contains \"Antimalware engine\"\r\n| extend Owner = iff(isnotempty(FileOwnerUpn), FileOwnerUpn, strcat(\"Site: \", tostring(split(FolderPath, \"/\")[4])))\r\n| summarize ['Files']=count(), ['Distinct Files']=dcount(SHA256), ['Affected Locations']=dcount(Owner), ['Last Seen']=max(Timestamp) by ThreatNames\r\n| sort by ['Files'] desc\r\n| project ['Threat Name']=ThreatNames, ['Files'], ['Distinct Files'], ['Affected Locations'], ['Last Seen']", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "chartSettings": { + "xAxis": "RawinfoVirusInfo", + "createOtherGroup": 10 + }, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Files", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "filemal - family SPO-AV table", + "id": "bbcdccd9-eedb-476a-a0e7-8504f8770229" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by Location
\r\n\r\n**Displays the number of malware detections grouped by specific SharePoint sites or OneDrive locations. Helps identify which sites have the highest volume of detected threats for targeted remediation and security hardening.**" + }, + "customWidth": "50", + "name": "filemal - by-location heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "c5668d6e-7c0e-4ce3-9509-ca93dda3efad" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by Application
\r\n\r\n**Summarizes malware detections across Microsoft collaboration apps, including SharePoint, OneDrive, and Teams. Helps identify which applications experience the highest volume of detected threats for targeted security measures.**" + }, + "customWidth": "50", + "name": "filemal - by-application heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "07e64ca9-04a2-44b2-a044-e927bc73ef1b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists total Malware detections of files on SharePoint, OneDrive and Teams by the location (site or personal path) where the file resides.\r\nFileMaliciousContentInfo\r\n| extend ['Site / Location'] = tostring(split(FolderPath, '/')[4])\r\n| summarize ['Detections'] = count() by ['Site / Location']\r\n| sort by ['Detections'] desc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "filemal - by-location table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3ce3ea65-a4df-450f-871c-8956d59818a9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total Malware detections of files located on SharePoint, OneDrive and Teams summarizing the data by the Microsoft collaboration application (workload).\r\nFileMaliciousContentInfo\r\n| summarize count() by Workload\r\n| sort by count_ desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "filemal - by-application pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "003afc8e-0403-4aa9-9084-a3c2e435216a" + }, + { + "type": 1, + "content": { + "json": "### Top File Owners Holding Malware\r\n**Lists the users (or the SharePoint/Teams site, when a file has no individual owner) whose files in SharePoint, OneDrive or Teams were flagged as malware, with the count of malicious files, distinct files, affected workloads and sample threat names. Helps pinpoint the accounts and collaboration locations most affected by malicious content for targeted remediation.**" + }, + "customWidth": "100", + "name": "filemal - top-owners heading", + "id": "c2f8d3b5-0a4e-4b7c-9d23-8e6f0a1b2c34" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top file owners (or the SharePoint/Teams site, when a file has no user owner) whose SharePoint/OneDrive/Teams files were flagged as malware, with distinct files, workloads and sample threat names.\r\nFileMaliciousContentInfo\r\n| extend Owner = iff(isnotempty(FileOwnerUpn), FileOwnerUpn, strcat(\"Site: \", tostring(split(FolderPath, \"/\")[4])))\r\n| summarize ['Malicious Files'] = count(),\n ['Distinct Files'] = dcount(SHA256),\n ['Workloads'] = make_set(Workload, 3),\n ['Sample Threats'] = make_set_if(ThreatNames, isnotempty(ThreatNames), 5),\n ['Last Seen'] = max(Timestamp)\n by ['Owner']=Owner\n| top 20 by ['Malicious Files']", + "size": 0, + "title": "Top File Owners Holding Malware", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Malicious Files", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Distinct Files", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "filemal - top-owners table", + "id": "36d9a683-9f9d-4a70-84d9-ec351542f827" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "9" + }, + "name": "filemal - group", + "styleSettings": { + "showBorder": true + }, + "id": "50886cd9-87bf-4a84-bd80-d7f44441b3f7" + }, + { + "type": 1, + "content": { + "json": "# Post-Delivery & Quarantine Insights\r\n\r\n---\r\nThis tab covers what happens to threats **after delivery**: Zero-hour Auto Purge (ZAP) remediation of malicious messages already in mailboxes, and quarantine management - what is held, released, and by whom. Together they show how effectively post-delivery response contains threats that reached the inbox." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "11" + }, + "name": "postdelivery - tab description", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "93371620-d968-4987-bddd-6c9b9e5a0344" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Post Delivery Protection offered by ZAP\r\n
\r\n\r\nThis section provides insights into Microsoft Defender for Office 365's post-delivery protection capabilities through Zero-Hour Auto Purge (ZAP). ZAP is a critical security feature that continuously monitors delivered emails and automatically removes messages that are later identified as malicious. These visuals help track ZAP effectiveness, response times, and remediation patterns.

**Recommended action:** High post-delivery ZAP volume means threats are reaching inboxes before being caught - review pre-delivery filtering and detection latency." + }, + "name": "postdelivery - section header", + "id": "b22ee5f1-a2dc-4509-92a3-1dbcad3a6ee7" + }, + { + "type": 1, + "content": { + "json": "### ZAP Post-Delivery Actions (per {Granularity})
\r\n\r\n**Shows the count (per {Granularity}) of emails that were remediated post-delivery by Zero-Hour Auto Purge (ZAP). Helps track how often threats are detected and removed after reaching user mailboxes.**" + }, + "customWidth": "50", + "name": "postdelivery - zap-actions heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "af1aa73f-d952-4827-bcc9-b97a19016829" + }, + { + "type": 1, + "content": { + "json": "### ZAP Actions by Detection Type (per {Granularity})
\r\n\r\n**Visualizes the count (per {Granularity}) of post-delivery remediation actions performed by Zero-Hour Auto Purge (ZAP), broken down by detection type (Spam ZAP, Phish ZAP, Malware ZAP). Helps track which threat categories are most frequently remediated after delivery.**" + }, + "customWidth": "50", + "name": "postdelivery - by-detection-type heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8eb38cb1-4e2d-435a-81be-e661c9b89ff4" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of emails that had a post delivery action from zero-hour auto purge.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailPostDeliveryEvents \r\n| where ActionType has \"ZAP\"\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Zapped Emails'] = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Zapped Emails", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "postdelivery - zap-actions trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "dd60fd71-4e14-4b38-ad22-39f1e3e3f55a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of emails that had a post delivery action from zero-hour auto purge, summarizing by phish,spam or malware detection action\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailPostDeliveryEvents\r\n| where ActionType has \"ZAP\"\r\n| summarize [\"Spam ZAP\"]=countif(ActionType has 'Spam ZAP'), [\"Phish ZAP\"]=countif(ActionType has 'Phish ZAP'), [\"Malware ZAP\"]=countif(ActionType has 'Malware ZAP') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, [\"Spam ZAP\"]=coalesce([\"Spam ZAP\"],0), [\"Phish ZAP\"]=coalesce([\"Phish ZAP\"],0), [\"Malware ZAP\"]=coalesce([\"Malware ZAP\"],0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "postdelivery - by-detection-type trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "511f4a43-9f56-48ad-a644-b72722af82d7" + }, + { + "type": 1, + "content": { + "json": "### ZAP Remediation by Destination
\r\n\r\n**This visual shows where ZAP moves malicious emails during remediation. Post-delivery actions can send emails to different locations: Quarantine (isolated for admin review), Deleted Items (soft delete), Junk Email folder, or back to Inbox (for false positive corrections). Understanding these patterns helps evaluate ZAP policy configurations and ensures malicious content is properly isolated from users.**" + }, + "name": "postdelivery - by-destination heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "dc7b9b6c-36fb-4ae4-a3e8-ff11da681c97" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails that had a post delivery action, summarizing the data daily by the final location as a result of the action\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailPostDeliveryEvents\r\n| where ActionType contains \"ZAP\"\r\n| summarize Quarantine=countif(DeliveryLocation has 'Quarantine'), ['Deleted Items']=countif(DeliveryLocation has 'Delete'), Junk=countif(DeliveryLocation has 'Junk'), Inbox=countif(DeliveryLocation has 'Inbox') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, Quarantine=coalesce(Quarantine,0), ['Deleted Items']=coalesce(['Deleted Items'],0), Junk=coalesce(Junk,0), Inbox=coalesce(Inbox,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "name": "postdelivery - by-destination trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "cbb737ef-1c7e-4b3e-af26-a553fe6147c9" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "11" + }, + "name": "postdelivery - group", + "styleSettings": { + "showBorder": true + }, + "id": "e436ecee-8886-4179-a578-9e4a42e75b9e" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Quarantine Management and Insights\r\n
\r\n\r\nThis section provides comprehensive insights into quarantine operations, including release patterns, detection methods, and threat categorization. It helps security teams understand what types of threats are being quarantined and monitor quarantine release activity to identify potential false positives or security policy effectiveness.

**Recommended action:** Investigate high release rates - they indicate false positives or risky user releases; review quarantine policies and release permissions." + }, + "name": "quarantine - section header", + "id": "c4862977-6670-4716-8109-252a361d7478" + }, + { + "type": 1, + "content": { + "json": "### Quarantine Release Trend
\r\n\r\n**This visual displays the per-{Granularity} trend of emails released from quarantine by administrators. Monitoring this metric helps identify patterns in quarantine management and potential areas where policy adjustments may be needed to reduce unnecessary quarantines.**" + }, + "name": "quarantine - release-trend heading", + "id": "8526a5e0-c6a4-44e3-b00a-5e135374f58e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of emails released from quarantine\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailPostDeliveryEvents\r\n| where ActionTrigger has \"AdminAction\" and Action has 'Quarantine release'\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Quarantine Releases'] = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Quarantine Releases", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - release trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3625d1f1-f34a-4cbf-a78f-eb2e5506bad4" + }, + { + "type": 1, + "content": { + "json": "### Quarantine Release Percentage
\r\n\r\n**Calculates the percentage of quarantined emails that were successfully released compared to the total quarantined messages. This metric helps measure engagement with quarantine and assess the effectiveness of quarantine policies.**" + }, + "customWidth": "40", + "name": "quarantine - release-pct heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e3a9502c-9030-4621-b248-55cdf69f81ae" + }, + { + "type": 1, + "content": { + "json": "### Quarantine Release Analysis by Detection Type
\r\n\r\n**For each detection technology, this shows the share of its quarantined emails that were later released from quarantine (Release % = released / quarantined). A high release rate flags a detector that may be over-flagging legitimate mail - a strong candidate for policy or rule tuning. The Released count shows the volume behind each rate.**" + }, + "customWidth": "60", + "name": "quarantine - release-by-detection heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "976fc90f-bf46-4315-b05e-4e501b37b869" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the percentage of emails released from quarantine out of the total ammount of quarantined emails\r\nlet Quarantine_Releases = toscalar(EmailPostDeliveryEvents\r\n| where Action == \"Quarantine release\"\r\n| join kind=leftouter (EmailEvents | where DeliveryLocation == \"Quarantine\") on NetworkMessageId\r\n| summarize count());\r\nlet Quarantined_Mailflow = toscalar(EmailEvents | where DeliveryLocation == \"Quarantine\"\r\n| summarize count());\r\nprint\r\nQuarantine_Releases = toreal(Quarantine_Releases),\r\nQuarantined_Mailflow = toreal(Quarantined_Mailflow),\r\nRelease_Percentage = abs(round(((toreal(Quarantine_Releases)/toreal(Quarantined_Mailflow))*100),2))", + "size": 0, + "showAnalytics": true, + "title": " ", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "tileSettings": { + "titleContent": { + "columnMatch": "Release_Percentage", + "formatter": 12, + "formatOptions": { + "palette": "none" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + "showBorder": true, + "sortCriteriaField": "Release_Percentage", + "size": "auto" + }, + "statSettings": { + "valueField": "Release_Percentage", + "valueAggregation": "None", + "colorSettings": { + "type": "thresholds", + "mode": "foreground", + "heatmapPalette": "greenRed", + "thresholdsGrid": [ + { + "operator": "<", + "thresholdValue": "5", + "representation": "green" + }, + { + "operator": ">", + "thresholdValue": "5", + "representation": "redDark" + } + ] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "numberFormatSettings": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "tagText": "Quarantine Release Percentage", + "valueFontStyle": "mega", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "40", + "name": "quarantine - release-pct stat", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "64e157ce-2f6a-423f-9ce5-eade8b6f41d5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Per detection technology: the share of its quarantined emails that were later released from quarantine.\r\n//Release % = released / quarantined for that detection technology - a high rate flags a detector that may be over-flagging legitimate mail (potential false positives). Detectors with fewer than 10 quarantined emails are excluded so the rate is statistically meaningful.\r\nEmailEvents\r\n| where DeliveryLocation == \"Quarantine\"\r\n| extend MDO_detection = parse_json(DetectionMethods)\r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0]))\r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\")\r\n| where FirstSubcategory contains \"Malware\" or FirstSubcategory contains \"Phish\" or FirstSubcategory contains \"Spam\"\r\n| join kind=leftouter (\r\n EmailPostDeliveryEvents\r\n | where Action == \"Quarantine release\"\r\n | distinct NetworkMessageId\r\n | extend ReleasedFlag = \"yes\"\r\n ) on NetworkMessageId\r\n| summarize Quarantined = dcount(NetworkMessageId), Released = dcountif(NetworkMessageId, ReleasedFlag == \"yes\") by FirstSubcategory\r\n| where Quarantined >= 10 and Released > 0\r\n| extend ReleaseRate = round(Released * 100.0 / Quarantined, 2)\r\n| project ['Detection Type']=FirstSubcategory, ['Quarantined Emails']=Quarantined, ['Released']=Released, ['Release %']=ReleaseRate\r\n| order by ['Release %'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Quarantined Emails", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Released", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Release %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "60", + "name": "quarantine - release-by-detection pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "9a6d21b7-7542-4ae5-8f3f-b18474b52a20" + }, + { + "type": 1, + "content": { + "json": "### Malware Email Quarantine Analysis
\r\n\r\n**These visuals break down quarantined malware emails by their specific detection methods. Microsoft Defender for Office 365 employs multiple malware detection techniques including file detonation, file reputation analysis, and advanced filters. Understanding which detection methods are most frequently triggered helps optimize anti-malware policies and identify emerging malware tactics.
The line chart shows per-{Granularity} trends across all malware detection methods, while the table provides an overall distribution of detection reasons.**" + }, + "name": "quarantine - malware heading", + "id": "59f84161-a010-44c2-aec1-b72ed98ccdff" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of malware emails that are quarantined, summarized daily by the detection method\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has \"Malware\" and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Details = parse_json(DetectionMethods).Malware to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - malware trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a54a8daf-0be2-4c0e-a8d7-4ff0e0879fd2" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of malware emails that are quarantined, summarized by the detection method\r\n//(QA 2026-07-14) mv-expand over DetectionMethods.Malware (matching the sibling line chart) so each slice is a clean single method name instead of a bracketed JSON array.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has 'Malware' and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Malware = parse_json(DetectionMethods).Malware to typeof(string)\r\n| where isnotempty(Malware)\r\n| summarize count() by Malware\r\n| sort by count_ desc\r\n| project ['Detection Technology']=Malware, ['Detections']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - malware table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b5d0d022-cf41-47e5-ae06-cf2176b47758" + }, + { + "type": 1, + "content": { + "json": "### Phishing Email Quarantine Analysis
\r\n\r\n**These visuals break down quarantined phishing emails by their specific detection methods. Microsoft Defender for Office 365 employs multiple phishing detection techniques including impersonation protection, URL detonation, spoof detection, and advanced filters. Understanding which detection methods are most frequently triggered helps optimize anti-phishing policies and identify emerging phishing tactics.
The line chart shows per-{Granularity} trends across all phishing detection methods, while the table provides an overall distribution of detection reasons.**" + }, + "name": "quarantine - phish heading", + "id": "aca50104-cb68-4a8f-82ee-ea8eee25fe14" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of phish emails that are quarantined, summarized daily by the detection method\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has \"Phish\" and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - phish trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "57151360-0577-45ce-8fc6-10a3790865ce" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of phish emails that are quarantined, summarized by the detection method\r\n//(QA 2026-07-14) mv-expand over DetectionMethods.Phish (matching the sibling line chart) so each slice is a clean single method name instead of a bracketed JSON array.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has 'Phish' and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Phish = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Phish)\r\n| summarize count() by Phish\r\n| sort by count_ desc\r\n| project ['Detection Technology']=Phish, ['Detections']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - phish pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "df78c64b-76f6-4980-80df-d0d432e780a5" + }, + { + "type": 1, + "content": { + "json": "### Spam Email Quarantine Analysis
\r\n\r\n**These visuals provide detailed insights into quarantined spam emails categorized by detection methods. Spam detection technologies include advanced filters, general filters, bulk email filtering, reputation-based systems (IP, domain, URL), and mixed analysis detection. Analyzing spam quarantine patterns helps fine-tune spam filtering policies to balance security with user productivity and reduce false positives.
The line chart displays per-{Granularity} trends for each spam detection method, while the table shows the overall distribution.**" + }, + "name": "quarantine - spam heading", + "id": "e131910f-0233-474a-a9b8-9f70a49246cf" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of spam emails that are quarantined, summarized daily by the detection method\r\nlet gran = {Granularity};\r\nlet baseQuery = EmailEvents\r\n| where DetectionMethods has \"Spam\" and DeliveryLocation == \"Quarantine\";\r\nlet agg = materialize(baseQuery\r\n| mv-expand Details = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - spam trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5762bcc7-bbda-4a3d-91cf-de18fbdd2775" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of spam emails that are quarantined, summarized by the detection method\r\n//(QA 2026-07-14) mv-expand over DetectionMethods.Spam (matching the sibling line chart) so each slice is a clean single method name instead of a bracketed JSON array.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has 'Spam' and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Spam = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Spam)\r\n| summarize count() by Spam\r\n| sort by count_ desc\r\n| project ['Detection Technology']=Spam, ['Detections']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - spam pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "2995f55b-17f9-458b-8630-e0370d14522a" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "11" + }, + "name": "quarantine - group", + "id": "430294af-c68f-4427-8b55-d552a3d89d42", + "styleSettings": { + "showBorder": true + } + }, + { + "type": 1, + "content": { + "json": "# Security Operations Center (SOC) Insights \r\n\r\n---\r\n\r\nThis tab provides a view for security operations. Combines incident response metrics with investigation insights to evaluate the effectiveness of both automated systems and manual interventions." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "13" + }, + "name": "soc - tab description", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "fd65243c-514c-4813-978f-fb908226d049" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Security Incident Response Metrics\r\n
\r\n\r\n**Operational efficiency insights.** Tracks incident volume, resolution speed, automation efficacy, and classification accuracy to evaluate SOC performance.

**Recommended action:** Track mean time to close by severity against your SLA and investigate any severity trending upward." + }, + "name": "soc - incident-metrics section header", + "id": "f92c3e24-3e0f-4f4c-8ee9-3ec60832f7b1" + }, + { + "type": 1, + "content": { + "json": "### Email Security Incidents
\r\n\r\n**These visuals display the per-{Granularity} trend of email-related security incidents, as well as the proportion of email incidents compared to the total number of incidents in Defender.**" + }, + "name": "soc - email-incidents heading", + "id": "c1cf6796-6071-4d2e-bf2c-c5e8d2a99a12" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "customWidth": "75", + "name": "soc - email-incidents trend", + "id": "e23cfcda-1017-4fd0-ac71-8a861c450f71" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "customWidth": "25", + "name": "soc - incident-category pie", + "id": "baae2150-1b04-43b4-9713-48fd3cc6247f" + }, + { + "type": 1, + "content": { + "json": "### Average Incident Time To Close (minutes)\r\n**This visual displays the average time, in minutes, to close email-related security incidents (per {Granularity}), split by severity, so you can see how resolution speed changes over time. Reference SLA targets: High 60, Medium 120, Low 240, Informational 480 minutes.**" + }, + "name": "soc - time-to-close heading", + "id": "e23ccc6c-b0f0-407b-8e01-d8b69c40a745" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "name": "soc - sla-by-severity trend", + "id": "3f7d1f17-8d2f-4a1b-a97e-17973812ca6f" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "### Closed Incident Classification (True Positive vs False Positive)\r\n\r\nThis visual shows the distribution of closed email-related incidents classified as True Positive versus False Positive. It helps assess detection accuracy and provides insight into validation trends." + }, + "customWidth": "33.3", + "name": "soc - classification heading", + "styleSettings": { + "margin": "10px" + }, + "id": "48db10ce-8246-4f5e-8b68-f618d9c7f77c" + }, + { + "type": 1, + "content": { + "json": "### True Positive Incident Classification Rate\r\n\r\nThis visual displays the percentage of email-related incidents confirmed as True Positive. It offers a clear measure of classification accuracy and highlights changes in detection effectiveness over time." + }, + "customWidth": "33.3", + "name": "soc - tp-rate heading", + "styleSettings": { + "margin": "10px" + }, + "id": "34a84dbf-609a-407f-afef-f1592eb4a92b" + }, + { + "type": 1, + "content": { + "json": "### Incidents Automated vs Manual Closure\r\n\r\nThis visual illustrates the proportion of email-related incidents closed automatically versus manually. It provides visibility into operational efficiency and the impact of automation on incident resolution.\r\n
⚠️ *You will have to review the underlying query and add any automation system specific to your organization.*" + }, + "customWidth": "33.3", + "name": "soc - auto-vs-manual-closure heading", + "styleSettings": { + "margin": "10px" + }, + "id": "a1fd9136-7a12-4d80-b3e1-e2704a84f734" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "customWidth": "33.3", + "name": "soc - classification pie", + "styleSettings": { + "margin": "10px" + }, + "id": "cfa5b7c5-50cc-4b3b-8bba-1a93c57bff43" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "customWidth": "33.3", + "name": "soc - tp-rate stat", + "styleSettings": { + "margin": "10px" + }, + "id": "eca235aa-38aa-46dd-a569-74dd8f83b2f0" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "customWidth": "33.3", + "name": "soc - closure pie", + "styleSettings": { + "margin": "10px" + }, + "id": "a4bc160f-1ba6-4779-86cd-ef44422f1e29" + } + ] + }, + "name": "soc - incident-insights group", + "id": "3083ac4d-0bdd-4db7-a5f0-0d41cb67a4eb" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "13" + }, + "name": "soc - incident-metrics group", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "18ff8970-e5f6-4c51-918a-aa693a45d18f" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Investigation & Response Actions\r\n
\r\n\r\n**Remediation efficacy analysis.** Compares automated (AIR) and manual admin actions to evaluate response times and investigation outcomes.\r\n

**Recommended action:** Reduce AIR pending-action latency by reviewing why approvals take long, and increase automation where it is safe to do so." + }, + "name": "soc - air section header", + "id": "5e0b06c8-7774-4eb4-8b7f-572b3732de84" + }, + { + "type": 1, + "content": { + "json": "### Automated Investigation and Response (AIR) Actions (per {Granularity})\r\n\r\nThis visual shows the per-{Granularity} trend of Automated Investigation and Response (AIR) actions, including the number of successful and failed attempts (because of prior remediation)." + }, + "customWidth": "100", + "name": "soc - air-actions heading", + "styleSettings": { + "margin": "10px" + }, + "id": "05f14dec-e76c-413c-83a0-31a05dce65e7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query attempts to show AIR Efficiency Over Time by displaying the number of successes and failures over time\r\nEmailPostDeliveryEvents\r\n| where ActionType =~ \"Automated Remediation\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Count = count() by bin(Timestamp, {Granularity}), ActionResult", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "graphSettings": { + "type": 0, + "topContent": { + "columnMatch": "AlertId", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Count", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "soc - air-efficiency trend", + "styleSettings": { + "margin": "10px" + }, + "id": "ae2a1850-5b7e-49f7-bac4-d888053ab49b" + }, + { + "type": 1, + "content": { + "json": "### Automated Investigation and Response (AIR) Response Time After Email Delivery (per {Granularity})\r\n\r\nThis visual displays the average (per {Granularity}), 80th percentile (p80), 90th percentile (p90) and 99th percentile (p99) time needed, measured in minutes, from email delivery to AIR action. It serves as a SOC metric to monitor responsiveness (security team members reviewing and manually approving AIR Pending Actions) and identify potential latency in automated incident handling. If the latency is high focus on reviewing why reviwing AIR Pending Actions takes longer time for admins and consider auto-aproval of URL, Files and Email clusters. \r\n" + }, + "customWidth": "100", + "name": "soc - air-response-time heading", + "styleSettings": { + "margin": "10px" + }, + "id": "98c66d9e-efdf-40fc-b8b0-be35d7fd97a9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// SOC metric: Daily average/p75 delay (in minutes) from email delivery to AIR action\r\nlet deliveries = EmailEvents\r\n | where DeliveryAction == \"Delivered\"// delivered emails\r\n | extend MsgKey = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n | summarize FirstDelivery = min(Timestamp) by MsgKey, Threat = tostring(ThreatTypes);\r\nlet remediations = EmailPostDeliveryEvents\r\n | where ActionType =~ \"Automated Remediation\"// automated remediation events\r\n | extend MsgKey = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n | summarize FirstRemediation = min(Timestamp) by MsgKey;\r\ndeliveries\r\n| join kind=inner remediations on MsgKey\r\n| extend DelayMinutes = datetime_diff(\"minute\", FirstRemediation, FirstDelivery)\r\n| where DelayMinutes >= 0\r\n| summarize ['Avg (min)'] = avg(DelayMinutes),\r\n ['P80 (min)'] = percentile(DelayMinutes, 80),\r\n ['P90 (min)'] = percentile(DelayMinutes, 90),\r\n ['P99 (min)'] = percentile(DelayMinutes, 99),\r\n CountEmails = count()\r\n by bin(FirstRemediation, 1d) ", + "size": 0, + "aggregation": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "gridSettings": { + "sortBy": [ + { + "itemKey": "FirstRemediation", + "sortOrder": 1 + } + ] + }, + "sortBy": [ + { + "itemKey": "FirstRemediation", + "sortOrder": 1 + } + ], + "chartSettings": { + "xAxis": "FirstRemediation", + "yAxis": [ + "P99 (min)", + "P90 (min)", + "P80 (min)", + "Avg (min)" + ], + "showLegend": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "soc - air-latency area", + "styleSettings": { + "margin": "10px" + }, + "id": "900383f1-6443-4d50-b15d-26e4ac11b255" + }, + { + "type": 1, + "content": { + "json": "### Automated Investigation and Response (AIR) Investigation Results Trend\r\n\r\nThis visual displays the per-{Granularity} trend of AIR investigation outcomes, categorized as **Threat Detected** or **Clean**. It helps track the effectiveness of automated investigations over time and highlights patterns in threat detection." + }, + "customWidth": "67", + "name": "soc - air-outcomes heading", + "styleSettings": { + "margin": "10px" + }, + "id": "d1cabfbe-6040-4b6e-9ce5-f48e9973dfc9" + }, + { + "type": 1, + "content": { + "json": "### Investigation Actions Taken: Automated Investigation and Response (AIR) vs Manual (Human)\r\n\r\nThis visual shows whether actions taken after an Automated Investigation and Response (AIR) required manual approval by an administrator or were executed automatically. It provides insight into the level of automation versus human intervention in post-investigation remediation." + }, + "customWidth": "33", + "name": "soc - air-auto-vs-manual heading", + "styleSettings": { + "margin": "10px" + }, + "id": "2f98514b-0172-4c4e-ba25-9a5e4138c570" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// AIR investigation outcomes by day: ThreatDetected vs. Clean\r\n\r\n// Step 1: Deduplicate automated remediation events by message and recipient\r\nlet AutoRemediations = \r\n EmailPostDeliveryEvents\r\n | where ActionType == \"Automated Remediation\"\r\n | summarize arg_max(Timestamp, ActionResult) by NetworkMessageId, RecipientEmailAddress\r\n | project NetworkMessageId, RecipientEmailAddress, Timestamp;\r\n\r\n// Step 2: Derive threat verdicts using AlertEvidence\r\nlet EvidenceVerdicts =\r\n AlertEvidence\r\n | where EntityType in (\"MailMessage\", \"MailCluster\")\r\n | extend extra = todynamic(AdditionalFields)\r\n // If this is a mail cluster, use provided NetworkMessageIds array; otherwise wrap NetworkMessageId as a single-item array\r\n | extend networkIds = iff(\r\n isnull(extra.NetworkMessageIds) or array_length(extra.NetworkMessageIds) == 0,\r\n pack_array(NetworkMessageId), // create a single-element array using pack_array\r\n extra.NetworkMessageIds // use the array as-is if it exists\r\n )\r\n | mv-expand nmID = networkIds // expand to individual message IDs\r\n // Derive verdict from LastVerdict, ThreatAnalysisSummary, and ThreatIntelligence\r\n | extend \r\n lastVerdict = tolower(tostring(extra.LastVerdict)),\r\n threatAIList = extra.ThreatAnalysisSummary,\r\n threatInt = extra.ThreatIntelligence\r\n | extend verdictFromAnalysis = iff(array_length(threatAIList) > 0, tolower(tostring(threatAIList[0].Verdict)), \"\"),\r\n verdictTI = iff(array_length(threatInt) > 0, \"malicious\", \"\") // any item in ThreatIntelligence indicates malicious\r\n // Mark as threat-detected if verdict is malicious/suspicious or threat evidence is present\r\n | extend ThreatDetectedFlag = \r\n case(\r\n lastVerdict in (\"malicious\",\"suspicious\") or verdictFromAnalysis in (\"malicious\",\"suspicious\")\r\n or verdictTI == \"malicious\",\r\n true,\r\n false\r\n )\r\n // Weight mail clusters by MailCount; default to 1 for single messages\r\n | extend MailCountInt = toint(extra.MailCount)\r\n | extend Weight = iff(EntityType == \"MailCluster\", \r\n coalesce(MailCountInt, 1), // default to 1 if MailCount is missing\r\n 1)\r\n | summarize IsThreatDetected = any(ThreatDetectedFlag), \r\n WeightSum = sum(Weight) \r\n by nmID = tostring(nmID);\r\n\r\n// Step 3: Join remediation events with verdicts and aggregate by day\r\nAutoRemediations\r\n| join kind=leftouter EvidenceVerdicts on $left.NetworkMessageId == $right.nmID\r\n| extend isThreat = coalesce(IsThreatDetected, false), \r\n effectiveWeight= coalesce(WeightSum, 1)\r\n| extend InvestigationOutcome = iif(isThreat, \"Threat Detected\", \"Clean\")\r\n| summarize PreventionCount = sum(effectiveWeight) by Day = bin(Timestamp, {Granularity}), InvestigationOutcome\r\n| order by Day asc, InvestigationOutcome asc", + "size": 0, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "67", + "name": "soc - air-outcomes trend", + "styleSettings": { + "margin": "10px" + }, + "id": "18552ccb-d8d4-45c4-a3cf-072203df9325" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows if the action taken after an Automated Investigation required manual approval by and admin or was automatically taken\r\nEmailPostDeliveryEvents\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ActionType == \"Automated Remediation\"\r\n| summarize count() by ActionTrigger", + "size": 3, + "showAnalytics": true, + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "soc - air-auto-vs-manual pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "03bc6e3c-05de-426d-91d8-b48a36b4ea74" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "### Post-Delivery Actions by Admin\r\n\r\nThis visual displays the number (per {Granularity}) of emails where an administrator performed a post-delivery action. Actions are summarized by type, including **Soft Delete**, **Hard Delete**, **Moved to Junk Folder**, **Moved to Inbox**, and **Quarantine Release**, providing insight into manual intervention trends after email delivery." + }, + "name": "soc - post-delivery-by-admin heading", + "styleSettings": { + "margin": "10px" + }, + "id": "a0961ca9-da58-49c4-9a1c-873c5569bed9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of emails that had an admin post delivery action, summarizing the data by action type\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailPostDeliveryEvents\r\n| where ActionTrigger has \"AdminAction\"\r\n| summarize [\"Soft Delete\"]=countif(Action has 'Soft Delete'), [\"Hard Delete\"]=countif(Action has 'Hard Delete'), [\"Moved to junk folder\"]=countif(Action has 'Moved to junk folder'), [\"Moved to inbox\"]=countif(Action has 'Moved to inbox'), [\"Quarantine release\"]=countif(Action has 'Quarantine release') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, [\"Soft Delete\"]=coalesce([\"Soft Delete\"],0), [\"Hard Delete\"]=coalesce([\"Hard Delete\"],0), [\"Moved to junk folder\"]=coalesce([\"Moved to junk folder\"],0), [\"Moved to inbox\"]=coalesce([\"Moved to inbox\"],0), [\"Quarantine release\"]=coalesce([\"Quarantine release\"],0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "name": "soc - post-delivery-by-admin trend", + "styleSettings": { + "margin": "10px" + }, + "id": "d2ea8eac-a3db-46b0-bcb4-3abbb95ba4ad" + } + ] + }, + "customWidth": "100", + "name": "soc - post-delivery group", + "id": "ebca14d5-954d-4e35-a225-cb0f8a3ea81b" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "13" + }, + "name": "soc - air group", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "0a05394d-f813-4408-ac4d-8f481ae34c0b" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Top Malicious Email Campaigns (Clustered)\r\n
\r\n\r\n**Groups malicious inbound emails into campaigns (attack waves) using the Email Cluster ID assigned by Microsoft Defender for Office 365, showing one row per campaign with the message count, distinct recipients, sender domains, threat mix and sample subjects. Helps the SOC understand the scale and shape of coordinated attacks rather than viewing individual messages in isolation.**

**Recommended action:** Pivot on the top campaign clusters to hunt related messages and consider blocking shared sender infrastructure." + }, + "name": "soc - campaigns heading", + "id": "d3a9e4c6-1b5f-4c8d-ae34-9f7a1b2c3d45" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Largest malicious inbound email campaigns clustered by EmailClusterId - one row per attack wave (messages, recipients, URL clicks, sender domains, threat mix, sample subjects).\r\n//URL Clicks = clicks by recipients on URLs within the campaign's messages (UrlClickEvents joined via NetworkMessageId).\r\nlet clicksByCluster = UrlClickEvents\r\n| join kind=inner (EmailEvents | where EmailClusterId > 0 | distinct NetworkMessageId, EmailClusterId) on NetworkMessageId\r\n| summarize UrlClicks = count() by EmailClusterId;\r\nlet qrClusters = EmailUrlInfo\r\n| where UrlLocation == \"QRCode\"\r\n| join kind=inner (EmailEvents | where EmailClusterId > 0 | distinct NetworkMessageId, EmailClusterId) on NetworkMessageId\r\n| summarize QrMessages = dcount(NetworkMessageId) by EmailClusterId;\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and EmailClusterId > 0\r\n| where OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Messages = count(),\r\n Recipients = dcount(RecipientEmailAddress),\r\n SenderDomains = dcount(SenderFromDomain),\r\n SampleSenderDomains = make_set(SenderFromDomain, 5),\r\n ThreatTypesRaw = make_set(ThreatTypes, 50),\r\n SampleSubjects = make_set(Subject, 5),\r\n FirstSeen = min(Timestamp),\r\n LastSeen = max(Timestamp)\r\n by EmailClusterId\r\n| join kind=leftouter (clicksByCluster) on EmailClusterId\r\n| extend UrlClicks = coalesce(UrlClicks, 0)\r\n| join kind=leftouter (qrClusters) on EmailClusterId\r\n| extend ['QR Code'] = iif(coalesce(QrMessages, 0) > 0, \"QR code\", \"\")\r\n| extend ThreatMix = array_sort_asc(set_union(split(strcat_array(ThreatTypesRaw, \", \"), \", \"), dynamic([])))\r\n| top 20 by Messages\r\n| project ['Email Cluster ID']=EmailClusterId, ['Messages']=Messages, ['Recipients']=Recipients, ['URL Clicks']=UrlClicks, ['Sender Domains']=SenderDomains, ['Sample Sender Domains']=SampleSenderDomains, ['Threat Mix']=ThreatMix, ['QR Code']=['QR Code'], ['Sample Subjects']=SampleSubjects, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", + "size": 0, + "title": "", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Recipients", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "URL Clicks", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "soc - campaigns table", + "id": "a2a391e1-0e26-4e0e-a8d3-26e3c7132079" + }, + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Most-Clicked Email Campaigns (Recipient Engagement)\r\n
\r\n\r\n**Ranks malicious inbound campaigns by recipient URL clicks, surfacing the attack waves that reached a mailbox and drew engagement regardless of raw message volume. The highest-volume campaigns are usually quarantined before delivery, so the clusters that draw clicks are often smaller, targeted waves. A non-zero URL Clicks count means a recipient opened a URL within the campaign's messages. Because attackers often mix legitimate URLs with malicious ones to build credibility, and a per-URL threat verdict is not available here, treat these as clicks on potentially malicious URLs that warrant review rather than confirmed malicious clicks.**

**Recommended action:** Focus on these clusters for user follow-up (awareness and, where credentials may be exposed, password reset) and hunt for related messages sharing sender infrastructure." + }, + "name": "soc - mostclicked heading", + "id": "e9e41b47-0434-42e5-8b04-4170ab061b81" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Malicious inbound campaigns ranked by recipient URL clicks - the attack waves that reached a mailbox and drew engagement, regardless of message volume.\r\n//URL Clicks = clicks by recipients on URLs within the campaign's messages (UrlClickEvents joined via NetworkMessageId).\r\nlet clicksByCluster = UrlClickEvents\r\n| join kind=inner (EmailEvents | where EmailClusterId > 0 | distinct NetworkMessageId, EmailClusterId) on NetworkMessageId\r\n| summarize UrlClicks = count() by EmailClusterId;\r\nlet qrClusters = EmailUrlInfo\r\n| where UrlLocation == \"QRCode\"\r\n| join kind=inner (EmailEvents | where EmailClusterId > 0 | distinct NetworkMessageId, EmailClusterId) on NetworkMessageId\r\n| summarize QrMessages = dcount(NetworkMessageId) by EmailClusterId;\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and EmailClusterId > 0\r\n| where OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Messages = count(),\r\n Recipients = dcount(RecipientEmailAddress),\r\n SenderDomains = dcount(SenderFromDomain),\r\n SampleSenderDomains = make_set(SenderFromDomain, 5),\r\n ThreatTypesRaw = make_set(ThreatTypes, 50),\r\n SampleSubjects = make_set(Subject, 5),\r\n FirstSeen = min(Timestamp),\r\n LastSeen = max(Timestamp)\r\n by EmailClusterId\r\n| join kind=inner (clicksByCluster) on EmailClusterId\r\n| where UrlClicks > 0\r\n| join kind=leftouter (qrClusters) on EmailClusterId\r\n| extend ['QR Code'] = iif(coalesce(QrMessages, 0) > 0, \"QR code\", \"\")\r\n| extend ThreatMix = array_sort_asc(set_union(split(strcat_array(ThreatTypesRaw, \", \"), \", \"), dynamic([])))\r\n| top 20 by UrlClicks\r\n| project ['Email Cluster ID']=EmailClusterId, ['URL Clicks']=UrlClicks, ['Messages']=Messages, ['Recipients']=Recipients, ['Sender Domains']=SenderDomains, ['Sample Sender Domains']=SampleSenderDomains, ['Threat Mix']=ThreatMix, ['QR Code']=['QR Code'], ['Sample Subjects']=SampleSubjects, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", + "size": 0, + "title": "", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "URL Clicks", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Recipients", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "soc - mostclicked table", + "id": "1ffe8f97-ad79-47d9-9598-dd73ee54cd8d" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "13" + }, + "name": "soc - campaigns group", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "b8f2a1c4-5d6e-4a7b-9c8d-0e1f2a3b4c5d" + } + ], + "isLocked": false, + "fallbackResourceIds": [], + "$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json", + "contentProvenance": { + "packageId": "azuresentinel.azure-sentinel-solution-microsoftdefenderforo365", + "packageVersion": "3.2.0", + "contentId": "55a394cc-f0af-55c1-8ff2-ec483e3e68a3", + "contentVersion": "3.2.0" + } + } + } + } + } + } + }, + "condition": "[parameters('DeployDefenderWorkbook')]" + }, + { + "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", + "apiVersion": "2023-04-01-preview", + "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-dwb-',uniqueString('55a394cc-f0af-55c1-8ff2-ec483e3e68a3')))]", + "location": "[parameters('workspace-location')]", + "dependsOn": [ + "[resourceId('Microsoft.Resources/deployments', 'DefenderWorkbook-fcbb3d6973f129d54269dbefb1a96dea')]", + "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" + ], + "properties": { + "description": "Defender Workbook: Microsoft Defender for Office 365 Detections and Insights - ISOC", + "mainTemplate": { + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "languageVersion": "2.0", + "contentVersion": "1.0.0.0", + "imports": { + "MicrosoftSecurity": { + "provider": "MicrosoftSecurity", + "version": "1.0.0" + } + }, + "resources": { + "workbook": { + "import": "MicrosoftSecurity", + "type": "Microsoft.Security/workbooks@2026-06-01-preview", + "properties": { + "id": "0eba4431-9e8b-5ffb-9623-2a0391db7b01", + "name": "Microsoft Defender for Office 365 Detections and Insights - ISOC", + "content": { + "version": "Notebook/1.0", + "items": [ + { + "type": 1, + "content": { + "json": "# Microsoft Defender for Office 365 Detections and Insights\n\nThis workbook provides email and collaboration security insights directly in Microsoft Defender using Advanced Hunting. It is designed for customers using workspace-less Workbooks in the Integrated Security Operations Center (ISOC) and does not require Microsoft Sentinel or a Log Analytics workspace.\n\n[Learn about Integrated Security Operations Center in Microsoft Defender](https://techcommunity.microsoft.com/blog/microsoftthreatprotectionblog/integrated-security-operations-center-in-microsoft-defender/4559097)\n\n- The time selector is bounded by the Defender data available to this tenant.\n- The default range is 7 days and the maximum selectable range is 90 days.\n- Subscription, workspace, cross-workspace, and MSSP selectors are not available in the workspace-less experience.\n- Incident visuals that depend on Microsoft Sentinel tables show an explicit ISOC workspace-required notice." + }, + "name": "text - 2", + "id": "d2b45ab8-a1c1-43d2-853d-290640bf4c94" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "2e238f92-709c-410b-93e0-60eab6150a75", + "version": "KqlParameterItem/1.0", + "name": "TimeRange", + "type": 4, + "isRequired": true, + "isGlobal": true, + "typeSettings": { + "selectableValues": [ + { + "durationMs": 3600000 + }, + { + "durationMs": 14400000 + }, + { + "durationMs": 43200000 + }, + { + "durationMs": 86400000 + }, + { + "durationMs": 172800000 + }, + { + "durationMs": 259200000 + }, + { + "durationMs": 604800000 + }, + { + "durationMs": 1209600000 + }, + { + "durationMs": 2592000000 + }, + { + "durationMs": 5184000000 + }, + { + "durationMs": 7776000000 + } + ], + "allowCustom": true + }, + "timeContext": { + "durationMs": 86400000 + }, + "value": { + "durationMs": 604800000 + }, + "key": "2e238f92-709c-410b-93e0-60eab6150a75" + }, + { + "id": "165f2f4a-e49f-4561-adc5-d0527a4caf32", + "version": "KqlParameterItem/1.0", + "name": "Granularity", + "label": "Trend interval", + "type": 2, + "isRequired": true, + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "jsonData": "[[{\"value\":\"1d\",\"label\":\"Daily (1d)\",\"selected\":true},{\"value\":\"7d\",\"label\":\"Weekly (7d)\",\"selected\":false},{\"value\":\"30d\",\"label\":\"Monthly (30d)\",\"selected\":false},{\"value\":\"90d\",\"label\":\"Quarterly (90d)\",\"selected\":false}]", + "timeContext": { + "durationMs": 86400000 + }, + "value": "1d" + } + ], + "style": "pills" + }, + "name": "parameters - 1", + "id": "0021e733-42b4-461f-8f6c-14e6e765389d" + }, + { + "type": 11, + "content": { + "version": "LinkItem/1.0", + "style": "tabs", + "links": [ + { + "id": "3d26d949-bba8-486c-9af7-2b85bd5c8ab0", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Executive Summary", + "subTarget": "1", + "style": "link", + "key": "3d26d949-bba8-486c-9af7-2b85bd5c8ab0" + }, + { + "id": "a5f95467-84c1-4d8b-858c-7819339af748", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Email - Malware", + "subTarget": "2", + "style": "link", + "key": "a5f95467-84c1-4d8b-858c-7819339af748" + }, + { + "id": "b6c93de8-16d9-4c90-999b-837935de5645", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Email - Phish", + "subTarget": "3", + "style": "link", + "key": "b6c93de8-16d9-4c90-999b-837935de5645" + }, + { + "id": "9e006e81-4fd4-40b9-9d20-3705dd6c17ad", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Email - Impersonation & BEC", + "subTarget": "15", + "style": "link", + "key": "75f1e28f-e95a-4810-af40-6b47b35cda46" + }, + { + "id": "df2c53b4-b6ed-4151-95fb-b3f08b849b84", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Email - Spam", + "subTarget": "4", + "style": "link", + "key": "df2c53b4-b6ed-4151-95fb-b3f08b849b84" + }, + { + "id": "fd2006c9-39b5-43ac-b05d-47309ee22deb", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Teams & Collaboration", + "subTarget": "14", + "style": "link", + "key": "fd2006c9-39b5-43ac-b05d-47309ee22deb" + }, + { + "id": "ee01f95a-c5f7-4864-82e8-54a164741ba2", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "File - Malware (SharePoint, Teams and OneDrive)", + "subTarget": "9", + "style": "link", + "key": "ee01f95a-c5f7-4864-82e8-54a164741ba2" + }, + { + "id": "9df30067-3266-48a8-b9e3-d65952098d46", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "URL & Clicks", + "subTarget": "5", + "style": "link", + "key": "9df30067-3266-48a8-b9e3-d65952098d46" + }, + { + "id": "b4be0ac3-3f48-44a8-b4b6-b46e17c710cd", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Top Users & Exfiltration", + "subTarget": "6", + "style": "link", + "key": "b4be0ac3-3f48-44a8-b4b6-b46e17c710cd" + }, + { + "id": "e1d34091-7b3c-4e2d-a032-8be82a989313", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Email - Detection Overrides", + "subTarget": "7", + "style": "link", + "key": "e1d34091-7b3c-4e2d-a032-8be82a989313" + }, + { + "id": "a1e6264d-8f85-4a94-9ffd-eee36c04a0d5", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Post-Delivery & Quarantine", + "subTarget": "11", + "style": "link", + "key": "a1e6264d-8f85-4a94-9ffd-eee36c04a0d5" + }, + { + "id": "08c43a4f-f502-4813-9b8d-3f6b0b62b2fd", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "False Negative(FN) Submissions", + "subTarget": "8", + "style": "link", + "key": "08c43a4f-f502-4813-9b8d-3f6b0b62b2fd" + }, + { + "id": "638d931f-f319-4914-b72d-8d68e914c7d4", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "False Positive(FP) Submissions", + "subTarget": "10", + "style": "link", + "key": "638d931f-f319-4914-b72d-8d68e914c7d4" + }, + { + "id": "b2920bee-c32a-4fdd-9d32-b004db2f3ac8", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Security Operations Center (SOC) Insights", + "subTarget": "13", + "style": "link", + "key": "b2920bee-c32a-4fdd-9d32-b004db2f3ac8" + } + ] + }, + "name": "links - 14", + "id": "5c9a1d6b-c248-432b-a1c0-496337635775" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Defender for Office 365 - Protection Insights\r\n
\r\n\r\n**Microsoft Defender for Office 365** is a comprehensive security solution designed to protect organizations from advanced threats targeting their email and collaboration tools. It leverages a multi-layered approach to safeguard against phishing, malware, business email compromise (BEC), and other sophisticated attacks.\r\n" + }, + "name": "text - 13", + "styleSettings": { + "margin": "0", + "padding": "0" + }, + "id": "46119f93-fad9-413c-8e10-7615c6fdde2f" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows the number behind the effectiveness of phish and malware false positives including post delivery events but without edge data detections.\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\n\r\n// Get all mailflow detected as clean at time of delivery \r\nlet EmailEventsClean = materialize( \r\n EmailEvents \r\n | where Timestamp between (toscalar(minTime) .. toscalar(maxTime)) and EmailDirection == \"Inbound\" \r\n // | where ThreatTypes !contains \"Phish\" and ThreatTypes !contains \"Malware\" // Streaming-SIEM branch disabled for Advanced Hunting current-state semantics.\r\n // this alteration is due to the threat types being updated directly within advanced hunting.\r\n | where DeliveryLocation != \"Quarantine\" // Advanced Hunting current-state branch.\r\n | project NetworkMessageId,ThreatTypes \r\n); \r\n// Get all mailflow detected as phish or malware at time of delivery \r\nlet EmailEventsThreats = materialize( \r\n EmailEvents \r\n | where Timestamp between (toscalar(minTime) .. toscalar(maxTime)) and EmailDirection == \"Inbound\" \r\n | where ThreatTypes contains \"Phish\" or ThreatTypes contains \"Malware\" \r\n | extend MDO_detection = parse_json(DetectionMethods) \r\n | extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n | extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n | project NetworkMessageId,FirstDetection,FirstSubcategory,MDO_detection,ThreatTypes \r\n); \r\n// Get all post delivery ZAP / Redelivery events, and arg_max them to ensure we have the latest verdict to work with for each \r\nlet EmailPostDeliveryFiltered = materialize( \r\n EmailPostDeliveryEvents \r\n | where Timestamp between (toscalar(minTime) .. datetime_add('day', 7, toscalar(maxTime))) \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") or Action has_any (\"Redelivery\",\"Reprocessed\") \r\n | extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n | summarize arg_max(Timestamp, *) by Key \r\n | project Action,ActionType,ActionResult,ThreatTypes,NetworkMessageId \r\n); \r\n// Optional - get all admin submissions for malware or phish, so we can also count these in the miss bucket. \r\nlet CloudAppEventsFiltered = materialize( \r\n CloudAppEvents \r\n | where Timestamp between (toscalar(minTime) .. datetime_add('day', 7, toscalar(maxTime)))\r\n | where ActionType == \"AdminSubmissionSubmitted\" \r\n | extend SubmissionType = tostring(parse_json(RawEventData).SubmissionType) \r\n | extend NetworkMessageId = tostring(parse_json(RawEventData).ObjectId) \r\n | where SubmissionType in (\"1\", \"2\") \r\n | project SubmissionType,NetworkMessageId \r\n); \r\n// get the number of threats caught in mailflow \r\nlet Mal_Phish_Mailflow = toscalar( \r\n EmailEventsThreats \r\n | summarize count() \r\n); \r\n// get the number of threats caught in mailflow which turned out to be false positives (FPs) so we can correct the calculation \r\nlet FP_ZAP = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ThreatTypes !contains \"Phish\" and ThreatTypes !contains \"Malware\" and Action has_any (\"Redelivery\",\"Reprocessed\") \r\n | join kind=leftsemi (EmailEventsThreats) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// get the number of threats successfully cleaned up post delivery, ignoring where administrative policy stopped action \r\nlet FN_ZAP_Successful = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") and ActionResult in (\"Success\",\"AdminPolicy\") \r\n | join kind=leftsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// get the number of threats unsuccessfully cleaned up post delivery. \r\nlet FN_ZAP_Unsuccessful = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") and ActionResult !in (\"Success\",\"AdminPolicy\") \r\n | join kind=leftsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// join the administrative submissions to clean mailflow to find the additional miss \r\nlet FN_Admin_Submissions = toscalar( \r\n CloudAppEventsFiltered \r\n | join kind=rightsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n ); \r\n // print each result, and run the calculation to work out effectiveness at time of delivery and post delivery. \r\n\r\nprint StatisticName=\"Effectiveness Post Delivery\", Value=abs(round(((toreal(toscalar(FN_Admin_Submissions))+toreal(toscalar(FN_ZAP_Unsuccessful)))/(toreal(toscalar(Mal_Phish_Mailflow))+toreal(toscalar(FN_ZAP_Successful))+toreal(toscalar(FN_ZAP_Unsuccessful))+toreal(toscalar(FN_Admin_Submissions))-toreal(toscalar(FP_ZAP)))*100-100),2))", + "size": 1, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "tileSettings": { + "showBorder": false, + "titleContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Value", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "graphSettings": { + "type": 0, + "topContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Value", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "statSettings": { + "valueField": "Value", + "valueAggregation": "None", + "colorSettings": { + "type": "thresholds", + "mode": "foreground", + "heatmapPalette": "greenRed", + "thresholdsGrid": [ + { + "operator": ">", + "thresholdValue": "95", + "representation": "green" + }, + { + "operator": "<=", + "thresholdValue": "95", + "representation": "orange" + }, + { + "operator": "<=", + "thresholdValue": "90", + "representation": "red" + } + ] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "numberFormatSettings": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "tagText": "Phish / Malware Effectiveness - Post Delivery", + "valueFontStyle": "superLarge", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 5", + "id": "62de2a91-a809-48ec-a111-e697d556b2b3" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the percentage of emails released from quarantine out of the total ammount of quarantined emails\r\nlet Quarantine_Releases = toscalar(EmailPostDeliveryEvents\r\n| where Action == \"Quarantine release\"\r\n| join kind=leftouter (EmailEvents | where DeliveryLocation == \"Quarantine\") on NetworkMessageId\r\n| summarize count());\r\nlet Quarantined_Mailflow = toscalar(EmailEvents | where DeliveryLocation == \"Quarantine\"\r\n| summarize count());\r\nprint\r\nQuarantine_Releases = toreal(Quarantine_Releases),\r\nQuarantined_Mailflow = toreal(Quarantined_Mailflow),\r\nRelease_Percentage = abs(round(((toreal(Quarantine_Releases)/toreal(Quarantined_Mailflow))*100),2))", + "size": 1, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "tileSettings": { + "titleContent": { + "columnMatch": "Release_Percentage", + "formatter": 12, + "formatOptions": { + "palette": "none" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + "showBorder": true, + "sortCriteriaField": "Release_Percentage", + "size": "auto" + }, + "graphSettings": { + "type": 0, + "topContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Value", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "statSettings": { + "valueField": "Release_Percentage", + "valueAggregation": "None", + "colorSettings": { + "type": "thresholds", + "mode": "foreground", + "heatmapPalette": "greenRed", + "thresholdsGrid": [ + { + "operator": "<", + "thresholdValue": "5", + "representation": "green" + }, + { + "operator": ">", + "thresholdValue": "5", + "representation": "redDark" + } + ] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "numberFormatSettings": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "tagText": "Quarantine Release Percentage", + "valueFontStyle": "superLarge", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 1", + "id": "858ac1a4-8828-45e9-968c-d3cfc1216c64" + } + ] + }, + "name": "TopNr", + "id": "1369c97e-848b-475a-b447-3a435cb7a1f1" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "**Effectiveness visually represents the protection given by Defender for Office 365 against phishing and malware in email messages.**
\r\nWe consider messages that your users report, as well as decisions that are made after delivery." + }, + "name": "text - 9", + "styleSettings": { + "margin": "1px" + }, + "id": "25e2e19e-aefb-4e37-b28f-b4138d63e109" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows the number behind the effectiveness of phish and malware false positives including post delivery events but without edge data detections.\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\n\r\n// Get all mailflow detected as clean at time of delivery \r\nlet EmailEventsClean = materialize( \r\n EmailEvents \r\n | where Timestamp between (toscalar(minTime) .. toscalar(maxTime)) and EmailDirection == \"Inbound\" \r\n // | where ThreatTypes !contains \"Phish\" and ThreatTypes !contains \"Malware\" // Streaming-SIEM branch disabled for Advanced Hunting current-state semantics.\r\n // this alteration is due to the threat types being updated directly within advanced hunting.\r\n | where DeliveryLocation != \"Quarantine\" // Advanced Hunting current-state branch.\r\n | project NetworkMessageId,ThreatTypes \r\n); \r\n// Get all mailflow detected as phish or malware at time of delivery \r\nlet EmailEventsThreats = materialize( \r\n EmailEvents \r\n | where Timestamp between (toscalar(minTime) .. toscalar(maxTime)) and EmailDirection == \"Inbound\" \r\n | where ThreatTypes contains \"Phish\" or ThreatTypes contains \"Malware\" \r\n | extend MDO_detection = parse_json(DetectionMethods) \r\n | extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n | extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n | project NetworkMessageId,FirstDetection,FirstSubcategory,MDO_detection,ThreatTypes \r\n); \r\n// Get all post delivery ZAP / Redelivery events, and arg_max them to ensure we have the latest verdict to work with for each \r\nlet EmailPostDeliveryFiltered = materialize( \r\n EmailPostDeliveryEvents \r\n | where Timestamp between (toscalar(minTime) .. datetime_add('day', 7, toscalar(maxTime))) \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") or Action has_any (\"Redelivery\",\"Reprocessed\") \r\n | extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n | summarize arg_max(Timestamp, *) by Key \r\n | project Action,ActionType,ActionResult,ThreatTypes,NetworkMessageId \r\n); \r\n// Optional - get all admin submissions for malware or phish, so we can also count these in the miss bucket. \r\nlet CloudAppEventsFiltered = materialize( \r\n CloudAppEvents \r\n | where Timestamp between (toscalar(minTime) .. datetime_add('day', 7, toscalar(maxTime)))\r\n | where ActionType == \"AdminSubmissionSubmitted\" \r\n | extend SubmissionType = tostring(parse_json(RawEventData).SubmissionType) \r\n | extend NetworkMessageId = tostring(parse_json(RawEventData).ObjectId) \r\n | where SubmissionType in (\"1\", \"2\") \r\n | project SubmissionType,NetworkMessageId \r\n); \r\n// get the number of threats caught in mailflow \r\nlet Mal_Phish_Mailflow = toscalar( \r\n EmailEventsThreats \r\n | summarize count() \r\n); \r\n// get the number of threats caught in mailflow which turned out to be false positives (FPs) so we can correct the calculation \r\nlet FP_ZAP = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ThreatTypes !contains \"Phish\" and ThreatTypes !contains \"Malware\" and Action has_any (\"Redelivery\",\"Reprocessed\") \r\n | join kind=leftsemi (EmailEventsThreats) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// get the number of threats successfully cleaned up post delivery, ignoring where administrative policy stopped action \r\nlet FN_ZAP_Successful = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") and ActionResult in (\"Success\",\"AdminPolicy\") \r\n | join kind=leftsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// get the number of threats unsuccessfully cleaned up post delivery. \r\nlet FN_ZAP_Unsuccessful = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") and ActionResult !in (\"Success\",\"AdminPolicy\") \r\n | join kind=leftsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// join the administrative submissions to clean mailflow to find the additional miss \r\nlet FN_Admin_Submissions = toscalar( \r\n CloudAppEventsFiltered \r\n | join kind=rightsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n ); \r\n // print each result, and run the calculation to work out effectiveness at time of delivery and post delivery. \r\nunion withsource=Table \r\n (print StatisticName=\"Mal/Phish Mailflow totals - Minus FPs\", Value=toreal(Mal_Phish_Mailflow) - toreal(FP_ZAP)), \r\n (print StatisticName=\"Admin Mal/Phish FNs Submitted\", Value=toreal(FN_Admin_Submissions)), \r\n (print StatisticName=\"Mal/Phish FPs Reverse Zapped\", Value=toreal(FP_ZAP)), \r\n (print StatisticName=\"Mal / Phish Successfully Zapped\", Value=toreal(FN_ZAP_Successful)), \r\n (print StatisticName=\"Mal / Phish UN-Successfully Zapped\", Value=toreal(FN_ZAP_Unsuccessful)), \r\n (print StatisticName=\"Effectiveness Post Delivery (%)\", Value=abs(round(((toreal(FN_Admin_Submissions)+toreal(FN_ZAP_Unsuccessful))/(toreal(Mal_Phish_Mailflow)+toreal(FN_ZAP_Successful)+toreal(FN_ZAP_Unsuccessful)+toreal(FN_Admin_Submissions)-toreal(FP_ZAP))*100-100),2))), \r\n (print StatisticName=\"Effectiveness Pre-Delivery (%)\", Value=abs(round(((toreal(FN_Admin_Submissions)+toreal(FN_ZAP_Unsuccessful)+toreal(FN_ZAP_Successful))/(toreal(Mal_Phish_Mailflow)+toreal(FN_ZAP_Successful)+toreal(FN_ZAP_Unsuccessful)+toreal(FN_Admin_Submissions)-toreal(FP_ZAP))*100-100),2))) \r\n| project StatisticName, Value", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Value", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "tileSettings": { + "showBorder": false, + "titleContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Value", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "graphSettings": { + "type": 2, + "topContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Value", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + }, + "nodeIdField": "StatisticName", + "sourceIdField": "Value", + "targetIdField": "Value", + "graphOrientation": 3, + "showOrientationToggles": false, + "nodeSize": null, + "staticNodeSize": 100, + "colorSettings": null, + "hivesMargin": 5, + "edgeColorSettings": null + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 7", + "id": "9e09ff94-8092-49c7-860f-341049e1398c" + } + ] + }, + "customWidth": "50", + "name": "Effectiveness Nr", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "31081a73-9a54-4668-9e26-ad7347f1e06e" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "**Quarantine release rate by detection technology.** \r\n
\r\nFor each detector, the share of its quarantined mail that was later released (Release % = released / quarantined). A high rate can indicate false positives worth reviewing." + }, + "name": "text - 1", + "styleSettings": { + "margin": "1px" + }, + "id": "e9848043-03dd-4ada-9e73-238067463f74" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Per detection technology: the share of its quarantined emails later released from quarantine (a high rate can indicate false positives). Top 7 by release rate; detectors with <10 quarantined excluded so the rate is meaningful.\r\nEmailEvents\r\n| where DeliveryLocation == \"Quarantine\"\r\n| extend MDO_detection = parse_json(DetectionMethods)\r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0]))\r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\")\r\n| where FirstSubcategory contains \"Malware\" or FirstSubcategory contains \"Phish\"\r\n| join kind=leftouter (\r\n EmailPostDeliveryEvents\r\n | where Action == \"Quarantine release\"\r\n | distinct NetworkMessageId\r\n | extend ReleasedFlag = \"yes\"\r\n ) on NetworkMessageId\r\n| summarize Quarantined = dcount(NetworkMessageId), Released = dcountif(NetworkMessageId, ReleasedFlag == \"yes\") by FirstSubcategory\r\n| where Quarantined >= 10 and Released > 0\r\n| extend ReleaseRate = round(Released * 100.0 / Quarantined, 2)\r\n| project ['Detection Technology']=FirstSubcategory, ['Quarantined Emails']=Quarantined, ['Released']=Released, ['Release %']=ReleaseRate\r\n| order by ['Release %'] desc\r\n| take 7", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Quarantined Emails", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Released", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Release %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 2", + "id": "1bbae9d1-d6f8-446a-817c-8fdc2df83d4c" + } + ] + }, + "customWidth": "50", + "name": "Quarantine Overview Relese", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "36fd8f20-ece7-4889-9fb1-f5b85b97b45a" + } + ] + }, + "customWidth": "100", + "name": "group - Exec Protection Insights", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "1d8e22e0-22f7-453e-aed2-9e56ace1363a" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Protection details\r\n
\r\n\r\nThis Overview provides an executive summary of your Microsoft Defender for Office 365 email security posture: the volume of mail processed, threats detected and filtered (phishing, malware, spam), overall protection effectiveness, and the mix of threats targeting your organization. Use it as a starting point, then drill into the dedicated tabs for detailed investigation." + }, + "name": "text - 13", + "id": "24cf577c-e12a-4747-95a7-1c19bee17397" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "5c0f0101-0a11-4b22-9c33-000000000101", + "version": "KqlParameterItem/1.0", + "name": "ProtectionView", + "label": "Protection view", + "type": 2, + "isRequired": true, + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "jsonData": "[[{ \"value\": \"Table\", \"label\": \"Summary table\", \"selected\": true }, { \"value\": \"Tiles\", \"label\": \"Detailed tiles\" }]", + "value": "Tiles" + } + ], + "style": "pills" + }, + "name": "Protection view selector", + "id": "5c0f0102-0a11-4b22-9c33-000000000102" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let base = materialize(EmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| summarize arg_max(Timestamp, ThreatTypes, DeliveryAction, OrgLevelPolicy, OrgLevelAction, UserLevelAction) by Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress));\r\nlet agg = materialize(base | summarize\r\n Total = count(),\r\n Filtered = countif(isnotempty(ThreatTypes) and DeliveryAction != \"Delivered\" and OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")),\r\n FMal = countif(ThreatTypes has \"Malware\" and OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")),\r\n FPhish = countif(ThreatTypes has \"Phish\" and not(ThreatTypes has \"Malware\") and DeliveryAction != \"Delivered\" and OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")),\r\n FSpam = countif(ThreatTypes == \"Spam\" and DeliveryAction != \"Delivered\" and OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")),\r\n Deliv = countif(isnotempty(ThreatTypes) and DeliveryAction == \"Delivered\" and (isnotempty(OrgLevelAction) or isnotempty(UserLevelAction))),\r\n Blocked = countif(isempty(ThreatTypes) and DeliveryAction != \"Delivered\" and (isnotempty(OrgLevelAction) or isnotempty(UserLevelAction))),\r\n Clean = countif(isempty(ThreatTypes) and DeliveryAction == \"Delivered\"));\r\nlet pd = materialize(EmailPostDeliveryEvents | where ActionResult == \"Success\" | summarize MalZap = countif(ActionType == \"Malware ZAP\"), PhishZap = countif(ActionType == \"Phish ZAP\"), SpamZap = countif(ActionType == \"Spam ZAP\"));\r\nlet sub = materialize(CloudAppEvents | extend R = tostring(parse_json(RawEventData).RecordType), SCT = tostring(parse_json(RawEventData).SubmissionContentType) | where R == \"29\" | summarize Adm = countif(ActionType == \"AdminSubmissionSubmitted\" and SCT == \"Mail\"), Usr = countif(ActionType == \"UserSubmission\"));\r\nlet Total = toscalar(agg | project Total);\r\nlet Filtered = toscalar(agg | project Filtered);\r\nlet FMal = toscalar(agg | project FMal);\r\nlet FPhish = toscalar(agg | project FPhish);\r\nlet FSpam = toscalar(agg | project FSpam);\r\nlet Deliv = toscalar(agg | project Deliv);\r\nlet Blocked = toscalar(agg | project Blocked);\r\nlet Clean = toscalar(agg | project Clean);\r\nlet MalZap = toscalar(pd | project MalZap);\r\nlet PhishZap = toscalar(pd | project PhishZap);\r\nlet SpamZap = toscalar(pd | project SpamZap);\r\nlet Adm = toscalar(sub | project Adm);\r\nlet Usr = toscalar(sub | project Usr);\r\nunion\r\n (print o = 1, Name = \"Total Inbound Emails\", Count = Total),\r\n (print o = 2, Name = \"    Filtering Totals\", Count = Filtered),\r\n (print o = 3, Name = \"        Filtered as Malware\", Count = FMal),\r\n (print o = 4, Name = \"        Filtered as Phish\", Count = FPhish),\r\n (print o = 5, Name = \"        Filtered as Spam\", Count = FSpam),\r\n (print o = 6, Name = \"    Delivered with Detection\", Count = Deliv),\r\n (print o = 7, Name = \"    User/Admin Blocked\", Count = Blocked),\r\n (print o = 8, Name = \"    Clean Emails\", Count = Clean),\r\n (print o = 9, Name = \"Post-Delivery ZAP Removals\", Count = MalZap + PhishZap + SpamZap),\r\n (print o = 10, Name = \"    Removed by Malware ZAP\", Count = MalZap),\r\n (print o = 11, Name = \"    Removed by Phish ZAP\", Count = PhishZap),\r\n (print o = 12, Name = \"    Removed by Spam ZAP\", Count = SpamZap),\r\n (print o = 13, Name = \"User/Admin Reported\", Count = Adm + Usr),\r\n (print o = 14, Name = \"    Reported by Admins\", Count = Adm),\r\n (print o = 15, Name = \"    Reported by Users\", Count = Usr)\r\n| sort by o asc\r\n| extend [\"% of Inbound\"] = round(Count * 100.0 / Total, 1)\r\n| project Name, Count, [\"% of Inbound\"]", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Name", + "formatter": 1, + "formatOptions": { + "customColumnWidthSetting": "3fr" + } + }, + { + "columnMatch": "Count", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "3fr" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "% of Inbound", + "formatter": 3, + "formatOptions": { + "palette": "green", + "min": 0, + "max": 100, + "customColumnWidthSetting": "2fr" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "ProtectionView", + "comparison": "isEqualTo", + "value": "Table" + }, + "name": "query - option 1 grid", + "id": "5c0f0005-0a11-4b22-9c33-000000000005" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "title": "Total Emails", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| summarize Count = count()\r\n| extend Details = \"Total Inbound Emails\";", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Count", + "formatter": 4, + "formatOptions": { + "palette": "greenRed" + } + } + ] + }, + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1, + "formatOptions": { + "compositeBarSettings": { + "labelText": "" + } + } + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "blue", + "compositeBarSettings": { + "labelText": "" + } + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "chartSettings": { + "xAxis": "Count", + "createOtherGroup": 0 + }, + "mapSettings": { + "locInfo": "LatLong", + "sizeSettings": "Count", + "sizeAggregation": "Sum", + "legendMetric": "Count", + "legendAggregation": "Sum", + "itemColorSettings": { + "type": "heatmap", + "colorAggregation": "Sum", + "nodeColorField": "Count", + "heatmapPalette": "greenRed" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 1", + "id": "84e8d60b-7937-46f5-b2f4-a1a4adf06c9f" + } + ] + }, + "name": "Total Inbound", + "id": "1aeed046-9ea5-4583-b966-722847997fc7" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "title": "Filtering Totals", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where isnotempty(ThreatTypes) and EmailDirection == \"Inbound\" and DeliveryAction != 'Delivered'\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| summarize Count = count()\r\n| extend Details = \"Filtering Totals\";", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1, + "formatOptions": { + "compositeBarSettings": { + "labelText": "" + } + } + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "redDark", + "compositeBarSettings": { + "labelText": "" + } + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 1", + "id": "bae9a200-589f-4ca6-a3cf-f1110f644c49" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Total emails detected as Malware\r\nEmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| where ThreatTypes has ('Malware') and EmailDirection == \"Inbound\"\r\n| summarize Count= count()\r\n| extend Details = \"Emails Filtered as Malware\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "red" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 4", + "id": "0984d05b-fd2c-48e1-835f-41afc5a2385a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Total emails detected as Phish\r\nEmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| where ThreatTypes has \"Phish\" and not(ThreatTypes has \"Malware\") and EmailDirection == \"Inbound\" and DeliveryAction != 'Delivered'\r\n| summarize Count= count()\r\n| extend Details = \"Emails Filtered as Phish\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "orange" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 4", + "id": "ced2d054-76d1-40df-a412-0bc86a6c3336" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Total emails by detected as Spam\r\nEmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| where ThreatTypes == 'Spam' and EmailDirection == \"Inbound\" and DeliveryAction != 'Delivered'\r\n| summarize Count= count()\r\n| extend Details = \"Emails Filtered as Spam\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "yellow" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 4", + "id": "14456a0d-f5ac-46a0-a007-c72c7c40c58f" + } + ] + }, + "customWidth": "50", + "name": "group - 9", + "id": "d4e69885-f1b2-4c2b-85c2-188a6708dc4b" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "title": " ", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and DeliveryAction == 'Delivered'\r\n| where isnotempty(OrgLevelAction) or isnotempty(UserLevelAction)\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| summarize Count= count()\r\n| extend Details = \"Delivered with Detection\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "red" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "394d1ed4-7089-4291-bc80-f9948e3be6a9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\" and isempty(ThreatTypes) \r\n| where isnotempty(OrgLevelAction) or isnotempty(UserLevelAction)\r\n| where DeliveryAction != 'Delivered'\r\n| summarize Count= count()\r\n| extend Details = \"User/Admin Blocked\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "gray" + }, + "tooltipFormat": { + "tooltip": "Emails blocked from being delivered because of User or Admin overriddes" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "c29a2268-67d1-4958-a9a3-696384075987" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where isempty(ThreatTypes) and EmailDirection == \"Inbound\" and DeliveryAction == 'Delivered'\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| summarize Count= count()\r\n| extend Details = \"Clean Emails\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "gray" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "89a02ac7-971c-4672-bf5d-64709c479536" + } + ] + }, + "customWidth": "50", + "name": "group - 8", + "id": "761e74d4-279e-465f-ba47-5eeec4cf05d2" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "title": "Post-Delivery ZAP Removals", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailPostDeliveryEvents\r\n| where ActionResult == \"Success\"\r\n| where ActionType == \"Malware ZAP\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Removed by Malware ZAP\"\r\n", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "red" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "b06666bc-6ec0-49e7-a332-77e278d2320f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailPostDeliveryEvents\r\n| where ActionResult == \"Success\"\r\n| where ActionType == \"Phish ZAP\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Removed by Phish ZAP\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "orange" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "6fbac01b-0c42-46dc-8ca8-68e285593a45" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailPostDeliveryEvents\r\n| where ActionResult == \"Success\"\r\n| where ActionType == \"Spam ZAP\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Removed by Spam ZAP\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "yellow" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "7bd27a3b-be13-4ca0-9964-0f872f826b45" + } + ] + }, + "name": "Post Delivery", + "id": "4d20339e-5215-4edf-99d6-728cac183d16" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails reported by user and total emails reported by Admins as false positive or false negative detection\r\nCloudAppEvents\r\n| extend Record= (parse_json(RawEventData)).RecordType\r\n| extend SubmissionState = (parse_json(RawEventData)).SubmissionState,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Reported by Admins\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "palette": "none" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 3", + "id": "7490fa3a-e287-4fc3-b025-8772b9edb601" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails reported by user and total emails reported by Admins as false positive or false negative detection\r\nCloudAppEvents\r\n| extend Record= (parse_json(RawEventData)).RecordType\r\n| extend SubmissionState = (parse_json(RawEventData)).SubmissionState\r\n| where Record == 29 and ActionType == \"UserSubmission\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Reported by Users\"\r\n", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "palette": "none" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 2", + "id": "7af222dc-fd74-40ec-8ab7-741e179c07bf" + } + ] + }, + "name": "Reported", + "id": "8151e242-1c30-4550-ae9c-83f159e1a456" + } + ] + }, + "conditionalVisibility": { + "parameterName": "ProtectionView", + "comparison": "isEqualTo", + "value": "Tiles" + }, + "name": "Protection - Tiles view", + "id": "5c0f0103-0a11-4b22-9c33-000000000103" + }, + { + "type": 1, + "content": { + "json": "## Most Attacked Users
\r\n\r\n**The users most targeted by inbound email threats across all threat types (malware, phishing, and spam) in the selected period. Concentrated targeting of a few individuals is a strong signal of deliberate campaigns.**

**Recommended action:** Prioritise these users for security awareness training, tighter protection policies (for example the Strict preset), and closer monitoring - they are your highest-risk people." + }, + "name": "exec vap banner", + "id": "1fe431fb-cc96-4e81-b164-3a1a3823ebeb" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query surfaces the users most targeted by inbound email threats across all threat types (malware, phishing, spam) for the selected period, so SecOps can prioritise the highest-risk individuals. Similar to a \"Most Attacked People\" view.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| where isnotempty(ThreatTypes)\r\n| summarize\r\n ['Total Threats'] = count(),\r\n Malware = countif(ThreatTypes has \"Malware\"),\r\n Phish = countif(ThreatTypes has \"Phish\"),\r\n Spam = countif(ThreatTypes has \"Spam\"),\r\n ['Last Seen'] = max(Timestamp)\r\n by ['User']=RecipientEmailAddress\r\n| top 10 by ['Total Threats']\r\n| project ['User'], ['Total Threats'], Malware, Phish, Spam, ['Last Seen']", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Malware", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "145px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Phish", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "145px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Spam", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "145px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Total Threats", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "145px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "exec vap table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "2dfd91b1-b8d3-4a72-aaf4-a30a1886bed7" + }, + { + "type": 1, + "content": { + "json": "## Detection trend over time - grouped by {Granularity}\r\n**Represents total emails, total detections, total user submissions and admin email submissions over time summarizing the data per {Granularity} interval**" + }, + "name": "text - 14", + "id": "ddbbdaef-b374-42a8-821c-7fcd7ee53ba9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails, total detections, total user, and admin email submissions over time summarizing the data daily\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet scaffold = range Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran;\r\nlet baseQuery = materialize(EmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where isnotempty(Timestamp));\r\nlet sub = materialize(CloudAppEvents\r\n| extend Record = (parse_json(RawEventData)).RecordType, SubmissionContentType = tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29);\r\nlet zapbase = EmailPostDeliveryEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ActionResult == \"Success\"\r\n| where ActionType == \"Phish ZAP\" or ActionType == \"Malware ZAP\" or ActionType == \"Spam ZAP\";\r\nunion\r\n(scaffold | join kind=leftouter (baseQuery | where EmailDirection == \"Inbound\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Inbound Emails\"),\r\n(scaffold | join kind=leftouter (baseQuery | where ThreatTypes has ('Phish') | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Emails Detected as Phish\"),\r\n(scaffold | join kind=leftouter (baseQuery | where ThreatTypes has ('Malware') | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Emails Detected as Malware\"),\r\n(scaffold | join kind=leftouter (baseQuery | where ThreatTypes has ('Spam') | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Emails Detected as Spam\"),\r\n(scaffold | join kind=leftouter (baseQuery | where EmailDirection == \"Intra-org\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Intra-org Emails\"),\r\n(scaffold | join kind=leftouter (baseQuery | where EmailDirection == \"Outbound\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Outbound Emails\"),\r\n(scaffold | join kind=leftouter (baseQuery | where isnotempty(ThreatTypes) | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Emails with Threat\"),\r\n(scaffold | join kind=leftouter (sub | where ActionType == \"UserSubmission\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Emails Reported by Users\"),\r\n(scaffold | join kind=leftouter (zapbase | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Emails Removed by ZAP\"),\r\n(scaffold | join kind=leftouter (sub | where ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType == \"Mail\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Emails Reported by Admins\")", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp", + "seriesLabelSettings": [ + { + "seriesName": "Total Inbound Emails", + "label": "Inbound Emails", + "color": "green" + }, + { + "seriesName": "Total Emails with Threat", + "label": "Emails with Threat", + "color": "redDark" + }, + { + "seriesName": "Emails Detected as Phish", + "label": "Emails with Phish", + "color": "redBright" + }, + { + "seriesName": "Emails Detected as Malware", + "label": "Emails with Malware", + "color": "red" + }, + { + "seriesName": "Total Intra-org Emails", + "label": "Intra-org Emails", + "color": "greenDark" + }, + { + "seriesName": "Emails Detected as Spam", + "label": "Emails with Spam", + "color": "gray" + }, + { + "seriesName": "Total Outbound Emails", + "label": "Outbound Emails", + "color": "greenDarkDark" + }, + { + "seriesName": "Total Emails Removed by ZAP", + "label": "Emails ZAP-d", + "color": "orangeDark" + }, + { + "seriesName": "Total Emails Reported by Users", + "label": "User Reported Emails", + "color": "lightBlue" + }, + { + "seriesName": "Total Emails Reported by Admins", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 1", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "bcbefa48-f553-4290-acff-2691caf898ea" + }, + { + "type": 1, + "content": { + "json": "## Bad traffic (%) - Inbound Emails - grouped by {Granularity}\r\n**This represents bad traffic (% of emails with threats) compared to total inbound emails, summarized per {Granularity} interval over time.**" + }, + "name": "text - 15", + "id": "30761bcc-b1a5-45e2-8c0a-22388fbbf16c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises bad traffic (% of emails with threats) compared to total inbound emails over time summarising the data daily.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalEmailCount = count(),\r\n BadEmailCount = countif(isnotempty(ThreatTypes)) by bin(Timestamp, {Granularity})\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(BadEmailCount / todouble(TotalEmailCount) * 100, 2))\r\n| project Timestamp, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 0, + "aggregation": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 4", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "508036a8-d969-44c2-b2d2-c62d99999197" + } + ] + }, + "customWidth": "100", + "name": "group - Exec Protection Details", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "e6edeeeb-dcde-41d0-88c7-97ef773403b1" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Collaboration Protection Posture\r\n
\r\n\r\nMicrosoft Defender for Office 365 protects Microsoft Teams and collaboration, not only email. This snapshot shows Teams threat activity for the period.

**Recommended action:** Review the dedicated **Teams & Collaboration** tab for impersonation, malicious URLs, risky senders and file threats in Teams." + }, + "name": "exec collab banner", + "id": "3d78a6aa-51d4-4cab-93d1-26dff86fd667" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Headline Microsoft Teams / collaboration protection metrics for the executive summary, with per-interval sparklines so the collaboration threat trend is visible at a glance. Messages and URLs are counted per distinct Teams message.\r\nlet gran = {Granularity};\r\nlet me = materialize(MessageEvents);\r\nlet cae = materialize(CloudAppEvents | where ActionType == \"TeamsImpersonationDetected\");\r\nlet mui = materialize(MessageUrlInfo);\r\nlet uce = materialize(UrlClickEvents | where Workload == \"Teams\" and ActionType in (\"ClickBlocked\",\"ClickBlockedByTenantPolicy\"));\r\nlet fmc = materialize(FileMaliciousContentInfo | where Workload == \"MicrosoftTeams\");\r\nunion\r\n(me | summarize Count = dcount(TeamsMessageId) | extend Details = \"Teams Messages Scanned\", Ord = 1, Trend = toscalar(me | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(me | where isnotempty(ThreatTypes) | summarize Count = count() | extend Details = \"Teams Threat Messages\", Ord = 2, Trend = toscalar(me | where isnotempty(ThreatTypes) | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(cae | summarize Count = count() | extend Details = \"Teams Impersonation Detections\", Ord = 3, Trend = toscalar(cae | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(mui | summarize Count = dcount(TeamsMessageId) | extend Details = \"URLs Shared in Teams\", Ord = 4, Trend = toscalar(mui | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(uce | summarize Count = count() | extend Details = \"Malicious Clicks Blocked\", Ord = 5, Trend = toscalar(uce | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(fmc | summarize Count = count() | extend Details = \"Teams Files Scanned\", Ord = 6, Trend = toscalar(fmc | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(fmc | where isnotempty(ThreatTypes) | summarize Count = count() | extend Details = \"Malicious Teams Files\", Ord = 7, Trend = toscalar(fmc | where isnotempty(ThreatTypes) | make-series S = count() default = 0 on Timestamp step gran | project S))\r\n| sort by Ord asc\r\n| project Details, Count, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21 + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "exec collab tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3175aee5-56d2-4cb1-b1c3-75be683e6ffb" + } + ] + }, + "customWidth": "100", + "name": "group - Exec Collaboration Posture", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "39b0921f-fcef-49f4-8d52-0dcd1f33045b" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Emerging Threats\r\n
\r\n\r\n

With more sophisticated adversaries and new threats emerging frequently and prevalently, it's critical to be able to quickly identify and react to these threats.

\r\n\r\n[

🛡️Activity Profile: Email threat landscape

](https://security.microsoft.com/threatanalytics3/f186e4b0-28df-499a-901e-c64768b6d0dc/overview?filters=tags%253DPhishing)\r\n[

🛡️Activity Profile: Automated business email impersonation campaign uses parallel aging report and payroll diversion lures

](https://security.microsoft.com/threatanalytics3/3eb53378-892d-4695-a497-25d0a54181ee)\r\n[

🛡️Tool Profile: StealC

](https://security.microsoft.com/threatanalytics3/4d837c12-1db4-49c8-8466-219198d40b9b)\r\n[

🛡️OSINT Profile: UNC1151/Ghostwriter phishing campaign targeting Gmail accounts

](https://security.microsoft.com/threatanalytics3/b1a7e5e7-4b43-4758-8805-f714a131161a)\r\n[

🛡️Activity Profile: Encrypted message campaign targets real estate/financial sectors

](https://security.microsoft.com/threatanalytics3/651d669a-4721-42ab-bb96-509e94b5bfd9)\r\n\r\n
\r\n\r\nView all\r\n \r\n\r\n" + }, + "name": "text - 10", + "styleSettings": { + "margin": "0", + "padding": "0" + }, + "id": "0c781e85-af9a-41a6-9cf7-b3bb9a09d5d0" + } + ] + }, + "customWidth": "100", + "name": "group - Exec Emerging Threats", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "4f8886d3-882a-4c14-ab7f-a37bd302e32f" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Microsoft 365 Secure Email Gateway Performance\r\n
\r\n\r\n

Using multiple vendor email security products can offer diverse detections. However, our comprehensive end-to-end approach—spanning prevention, detection, posture, investigation, response, and user training—delivers a unified and effective defense that matches or exceeds the efficacy of siloed Secure Email Gateway solutions.

\r\n\r\n[

Learn more

](https://www.microsoft.com/en-us/security/blog/2026/06/15/microsoft-defender-email-security-benchmarking-key-insights-from-one-year-of-data/) \r\n\r\n
\r\n

High-severity email threats missed per 1,000 users protected - February–April 2026 (Microsoft Defender email security benchmarking)

" + }, + "name": "text - 12", + "id": "94c804f9-2860-4768-be59-fb31a4ff22d7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "datatable(Index:int, Name:string, Value:int)\r\n[\r\n 1, \"Defender for Office 365\", 194,\r\n 2, \"Mimecast\", 478,\r\n 3, \"ProofPoint\", 483,\r\n 4, \"HornetSecurity\", 813,\r\n 5, \"TrendMicro\", 1151,\r\n 6, \"IronPort\", 1274,\r\n 7, \"Barracuda\", 1585,\r\n 8, \"FireEye\", 2107\r\n]\r\n| project [\"Email security solution\"] = Name, [\"High-severity threats missed / 1K users\"] = Value\r\n| order by [\"High-severity threats missed / 1K users\"] asc\r\n", + "size": 0, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Email security solution", + "formatter": 1, + "formatOptions": { + "customColumnWidthSetting": "40%" + } + }, + { + "columnMatch": "High-severity threats missed / 1K users", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "min": 0, + "max": 2107, + "customColumnWidthSetting": "60%" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "useGrouping": true + } + } + } + ], + "rowLimit": 10, + "sortBy": [ + { + "itemKey": "High-severity threats missed / 1K users", + "sortOrder": 1 + } + ] + } + }, + "name": "query - 11", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e54fd5bd-17e2-40dc-897d-8a3bb21116ff" + } + ] + }, + "customWidth": "100", + "name": "group - Exec SEG Performance", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "1f3a7e2b-0a1f-48ba-9da3-e7531d500938" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "id": "ab3756d3-3f60-4024-9376-0f1a7d47ac13", + "type": 1, + "name": "text - 18", + "content": { + "json": "\r\n\r\n\r\n\r\n
Stay Current\r\n
\r\n\r\n
\r\n\r\n- **Threat Analytics (Defender XDR)** — live, tenant-specific threat intelligence and recommended actions: aka.ms/threatanalytics\r\n- **Microsoft Security Blog** — campaign write-ups and threat research: microsoft.com/security/blog\r\n- **Microsoft Defender for Office 365 Tech Community blog** — product updates and reporting guidance: Tech Community\r\n- **Latest features in Microsoft Defender for Office 365** — What's new in Microsoft Defender for Office 365 \r\n- **Share reporting feedback**: aka.ms/mdoreportingfeedback\r\n" + } + } + ] + }, + "customWidth": "100", + "name": "group - Exec Stay Current", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "5e22c565-cd2e-41f3-8d5a-0735af67c93f" + } + ], + "exportParameters": true + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "1" + }, + "name": "Detection Overview", + "styleSettings": { + "margin": "0", + "padding": "0" + }, + "id": "3f2cc277-9eb3-486d-a1f8-9fa5374a3d80" + }, + { + "type": 1, + "content": { + "json": "# Malware detection insights\r\n\r\n---\r\n\r\nThis tab provides insights into email message **detections** by Microsoft Defender for Office 365 where the message contained a **malware threat** (such as viruses, spyware, or ransomware) within its **URLs** or **attachments**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "text - 13", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "81f28ffc-b69e-4960-a61c-cac17a012ed6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//KPI summary of inbound email malware detections for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet mal = EmailEvents | where EmailDirection == \"Inbound\" | where ThreatTypes has \"Malware\";\r\nlet inbox = mal | where DeliveryLocation has \"Inbox\";\r\nlet malTrend = toscalar(mal | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet inboxTrend = toscalar(inbox | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(mal | summarize count()), Details = \"Malware Emails\", Ord = 1, Trend = malTrend),\r\n(print Count = toscalar(mal | summarize dcount(RecipientEmailAddress)), Details = \"Users Targeted\", Ord = 2, Trend = malTrend),\r\n(print Count = toscalar(mal | summarize dcount(SenderFromDomain)), Details = \"Sender Domains\", Ord = 3, Trend = malTrend),\r\n(print Count = toscalar(inbox | summarize count()), Details = \"Delivered to Inbox\", Ord = 4, Trend = inboxTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "malware kpi strip", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "20c06dd3-5025-4b2b-960e-ff012f5d2343" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Malware Detection Trends, Threat Classes, and Malware Names\r\n
\r\n\r\nThis section consolidates key visuals that track and explain malware detections in inbound email as identified by Microsoft Defender for Office 365 focusing on per-{Granularity} trend, threat classes and Malware types. \r\n

**Recommended action:** If malware volume spikes, confirm Safe Attachments (Block mode) is enabled for all users and investigate the top malware families below." + }, + "name": "text - 14", + "id": "1f09c6ec-b2de-4aa9-bd8e-81d11c92ebd4" + }, + { + "type": 1, + "content": { + "json": "### Malware Detection Trend\r\n**This visual displays a per-{Granularity} trend of email malware detections identified by Microsoft Defender for Office 365. The area chart summarises the number of messages flagged for malware threats.**" + }, + "name": "text - Malware Trend header", + "id": "e90b714f-de84-4571-9a60-b3b2f3bd09dd" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents \r\n| where ThreatTypes has \"Malware\" \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize MalwareDetections = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, MalwareDetections = coalesce(MalwareDetections, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "MalwareDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 0", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "350d0aa3-c093-4105-a150-c20111ac2912" + }, + { + "type": 1, + "content": { + "json": "### Malware Detection Trend - Advanced Threats\r\n**Not all threats are going to be easily recognisable, that's why Microsoft Defender for Office 365 has advanced threat detection methods, that use virtual sandbox environments to detonate URLs and Files. These virtual sandbox technologies look for known patterns, such as a recognisable login page in a URL, or a file accessing command and control infrastructure. This visual displays a per-{Granularity} trend of Malware detections of these advanced threats**" + }, + "name": "text - Malware Advanced Threats header", + "id": "12e07248-ada4-41d9-99cc-824eb65cff79" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections over time summarizing the data daily by Malware detection technologies/controls used for detecting unknown-unique malware.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Malware'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand MalwareMethod = ParsedMethods.Malware\r\n| where MalwareMethod in ('File detonation','URL detonation')\r\n| summarize Count = count() by MalwareMethod = tostring(MalwareMethod), Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct MalwareMethod | extend d = 1) on d | project Timestamp, MalwareMethod\r\n| join kind=leftouter (agg) on Timestamp, MalwareMethod\r\n| project Timestamp, MalwareMethod, Count = coalesce(Count, 0)\r\n| sort by MalwareMethod asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "File detonation", + "color": "redDark" + }, + { + "seriesName": "URL detonation", + "color": "orangeDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 9", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "ebcb6f29-02be-4dd0-b792-cd99285c29d4" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by Threat Classification\r\n**Summary of email messages detected by Microsoft Defender for Office 365 as malware, grouped by type of malware (Adware, Downloader, HackTool, Ransomware, Remote access trojan, Spyware).**" + }, + "customWidth": "33", + "name": "text - 15", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5638fc51-0830-4675-87d4-82f03df17bbf" + }, + { + "type": 1, + "content": { + "json": "### Top Attacked Users by Malware Threat Classification\r\n**Displays the recipient most frequently targeted for each malware type (Adware, Downloader, HackTool, Ransomware, Remote access trojan, Spyware) in inbound email detections.**" + }, + "customWidth": "33", + "name": "text - 15 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d2e3903b-4984-40da-a437-3d6a2b121e23" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by Threat Name\r\n**Summarises email messages flagged by Microsoft Defender for Office 365, grouped by specific malware names detected in URLs or attachments.**" + }, + "customWidth": "33", + "name": "text - 15 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6c0bebcf-9838-4385-ab3a-30db6c994284" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by threat classification of the malware threat in the message.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where ThreatTypes has 'Malware' and ThreatClassification has_any(\"Adware\",\"Downloader\",\"HackTool\",\"Ransomware\",\"Remote access trojan\",\"Spyware\")\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Count = count(Key) by ThreatClassification\r\n| sort by Count desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "query - 11", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "acb98530-8e3a-4383-b42f-8fd74b1c3fbe" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Malware detections in emails summarizing by various Threat classes showing the top attacked user for each threat classification type.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where ThreatTypes has \"Malware\" and EmailDirection == \"Inbound\" and ThreatClassification has_any(\"Adware\",\"Downloader\",\"HackTool\",\"Ransomware\",\"Remote access trojan\",\"Spyware\")\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize EmailCount=count() by ThreatClassification, RecipientEmailAddress\r\n| summarize Count = arg_max(EmailCount, RecipientEmailAddress) by ThreatClassification\r\n| sort by Count desc\r\n| project ['Threat Classification'] = ThreatClassification, ['Top Recipient'] = RecipientEmailAddress, ['Emails'] = Count", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "TopEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "statSettings": { + "valueField": "RecipientEmailAddress", + "valueAggregation": "None", + "colorSettings": { + "type": "static", + "mode": "background", + "heatmapPalette": "greenRed", + "thresholdsGrid": [] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "tagText": "", + "valueFontStyle": "auto" + }, + "chartSettings": { + "xAxis": "RecipientEmailAddress" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 5 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d9b46c97-91ce-4d64-aca6-3126ac49c0ff" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by ThreatNames of the malware detected.\r\nEmailEvents \r\n| where isnotempty(ThreatNames) and ThreatTypes has \"Malware\" \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| mv-expand ThreatName = split(ThreatNames, \",\") to typeof(string)\r\n| where isnotempty(ThreatName)\r\n| distinct Key, ThreatName\r\n| summarize Count = count() by ThreatName\r\n| top 15 by Count\r\n| project ['Threat Name'] = ThreatName, Count", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Count", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "xAxis": "ThreatNames", + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 3", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b9a4b34f-f54f-4d6e-bb20-81925d0f5540" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "group - 3", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "82853a93-e11f-4e4a-80f4-733850a1d3ff" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Malware Detections by Delivery Location, Detection Technology and Sender Infrastructure Insights\r\n
\r\n\r\nThis section consolidates key visuals that track and explain malware detections delivery locations, detection technologies used for detections, sender infrastructure insights in inbound email identified by Microsoft Defender for Office 365 as Malware. \r\n

**Recommended action:** For sender IPs or countries you do not do business with, consider connection filtering or geo-based rules; verify the detection technologies catching these are enabled." + }, + "name": "banner - Malware Delivery Detection Sender", + "id": "cba6403d-e2b1-4fe8-af52-57e5c2aa8e54" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by delivery location\r\n**Visualizes counts (per {Granularity}) of malware detections of inbound emails by delivery location: Quarantine or Failed (rejected with or without NDR)**" + }, + "name": "text - Malware Delivery Location header", + "id": "95be7f48-40eb-4154-91d8-20f7033f2ff5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections over time summarizing the data daily by Delivery Location\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Malware' and EmailDirection == 'Inbound'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalMalwareDetections=count(), Quarantine=countif(DeliveryLocation == 'Quarantine'), Failed=countif(DeliveryLocation == 'Failed') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, TotalMalwareDetections=coalesce(TotalMalwareDetections,0), Quarantine=coalesce(Quarantine,0), Failed=coalesce(Failed,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "TotalMalwareDetections", + "color": "blue" + }, + { + "seriesName": "Quarantine", + "color": "orangeDark" + }, + { + "seriesName": "Failed", + "color": "redDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 10", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b2c19e58-2123-490b-9631-c0b238c582e6" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by Detection Technology\r\n**Visualizes counts (per {Granularity}) of Malware detections of inbound emails by various Microsoft Defender for Office 365 detection technologies.**" + }, + "name": "text - Malware Detection Technology header", + "id": "f3c2691e-4f32-4109-9524-8a11719e4425" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections over time summarizing the data daily by various Malware detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Malware'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand MalwareMethod = ParsedMethods.Malware\r\n| summarize Count = count() by MalwareMethod = tostring(MalwareMethod), Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct MalwareMethod | extend d = 1) on d | project Timestamp, MalwareMethod\r\n| join kind=leftouter (agg) on Timestamp, MalwareMethod\r\n| project Timestamp, MalwareMethod, Count = coalesce(Count, 0)\r\n| sort by MalwareMethod asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 8", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f00c1ce0-e55e-44c0-8bf0-4af662ccef89" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by various Malware detection technologies/controls in Microsoft Defender for Office 365.\r\nEmailEvents \r\n| where DetectionMethods has 'Malware'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand MalwareMethod = ParsedMethods.Malware\r\n| summarize Count = count() by MalwareMethod = tostring(MalwareMethod)\r\n| sort by Count desc\r\n| project ['Detection Technology'] = MalwareMethod, ['Detections'] = Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "34", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 2", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "590880a9-1cf7-44ae-b4de-2f65bc700b5d" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by SenderIPv4 Geo Location\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Malware, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" + }, + "name": "text - Malware Geo Location header", + "id": "19d78b48-af58-4bee-abfe-57efb1eba125" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by email sender IP address (SenderIPv4).\r\nEmailEvents \r\n| where ThreatTypes has 'Malware' and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_", + "size": 0, + "showAnalytics": true, + "title": "Malware Detections-Sender Heatmap (IPv4)", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "map", + "gridSettings": { + "sortBy": [ + { + "itemKey": "count_", + "sortOrder": 2 + } + ] + }, + "sortBy": [ + { + "itemKey": "count_", + "sortOrder": 2 + } + ], + "mapSettings": { + "locInfo": "LatLong", + "locInfoColumn": "GeoInfo", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "none" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 1", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8cb46ec0-ac2a-41d1-bf8a-0b8585d1fefc" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where ThreatTypes has 'Malware' and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Malware Emails'] = count_\r\n| sort by ['Malware Emails'] desc\r\n\r\n\r\n", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Malware Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "mapSettings": { + "locInfo": "LatLong", + "locInfoColumn": "GeoInfo", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "heatmap", + "heatmapPalette": "red" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 1 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b6a0355a-2b8f-48a5-8edc-58f4f7f8180a" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "Malware-Detectiontech-Deliverylocation-SendingInfra", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "2692cb5e-825c-45c1-bd3a-096b55e8d760" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Malware Detections Top attacked users and top senders\r\n
\r\n\r\nThis section consolidates key visuals that track and explain malware detections in inbound email as identified by Microsoft Defender for Office 365 focusing on top attacked users and top senders. \r\n

**Recommended action:** Apply the Strict preset security policy to the most-attacked users and consider adding persistent malicious sender domains to the Tenant Allow/Block List." + }, + "name": "banner - Malware Top Users Senders", + "id": "bc5b37a4-71e4-4a2f-b0ba-b3dd87333391" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections top attacked users\r\n**Displays the top 10 recipient email addresses that received inbound emails flagged as Malware. These users may be at higher risk and should be prioritised for targeted cybersecurity awareness training. Training should cover the specific threat types and techniques they are exposed to, and reinforce best practices for promptly reporting any suspicious messages that might bypass security controls and reach their inbox.**" + }, + "customWidth": "100", + "name": "text - Malware Top Users header", + "id": "cb87a026-ad03-45cc-887e-ab460490d9a5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails with Malware detections summarizing the data by the top 15 recipient email address (RecipientEmailAddress).\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),MalwareEmailCount = countif(ThreatTypes has \"Malware\") by RecipientEmailAddress\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(MalwareEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| where MalwareEmailCount !=0\r\n| top 15 by MalwareEmailCount\r\n| project ['Recipient'] = RecipientEmailAddress, ['Malware Emails'] = MalwareEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Malware Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - Malware Top Recipients", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e7ffef62-f85e-4188-8ab9-d90a5c666c30" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains with Malware Detections (Inbound)\r\n**Displays the top 10 sender domains sending inbound emails detected as Malware. Helps identify external sources most frequently associated with malicious content for prioritised threat monitoring and mitigation.**" + }, + "customWidth": "100", + "name": "text - Malware Top Senders header", + "id": "93390807-25b2-4bea-9648-98e821da8ec6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by the top 15 email sender P2 domain (SenderFromDomain). Adding additional insights for total inbound emails and bad traffic percentage for each sender domain.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount = count(), MalwareEmailCount = countif(ThreatTypes has \"Malware\") by SenderFromDomain\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(MalwareEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| where MalwareEmailCount !=0\r\n| top 15 by MalwareEmailCount\r\n| project ['Sender Domain'] = SenderFromDomain, ['Malware Emails'] = MalwareEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Malware Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal", + "useGrouping": false + } + } + }, + { + "columnMatch": "BadEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - Malware Top Sender Domains", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "eaa45734-2df2-4a5e-b35b-1295e00cb46f" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "MalwareTopAttackedUser-TopSenders", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "4e0900ab-e7e4-4cf1-93a4-7e86bca20782" + }, + { + "type": 1, + "content": { + "json": "# Phishing Detection Insights\r\n\r\n---\r\nThis tab provides insights into email message **detections** by Microsoft Defender for Office 365 where the message contained a **Phishing threat** within its **email content**, **URLs**, or **attachments**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "text - 24", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "fe82d665-fa9e-4fc2-9ba9-7e2eabb9a04b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//KPI summary of inbound email phishing detections for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet ph = EmailEvents | where EmailDirection == \"Inbound\" | where ThreatTypes has \"Phish\";\r\nlet inbox = ph | where DeliveryLocation has \"Inbox\";\r\nlet phTrend = toscalar(ph | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet inboxTrend = toscalar(inbox | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(ph | summarize count()), Details = \"Phish Emails\", Ord = 1, Trend = phTrend),\r\n(print Count = toscalar(ph | summarize dcount(RecipientEmailAddress)), Details = \"Users Targeted\", Ord = 2, Trend = phTrend),\r\n(print Count = toscalar(ph | summarize dcount(SenderFromDomain)), Details = \"Sender Domains\", Ord = 3, Trend = phTrend),\r\n(print Count = toscalar(inbox | summarize count()), Details = \"Delivered to Inbox\", Ord = 4, Trend = inboxTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "phish kpi strip", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5debf0b8-4384-485b-8a7f-71ead592718a" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Phishing Detection Trend, LLM Content Analysis, Advanced Threats, and Threat Classes\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Phish detections in inbound email as identified by Microsoft Defender for Office 365 focusing on per-{Granularity} trends, advanced threat detections, LLM-based content analysis, and threat classes.

**Recommended action:** Review the LLM-classified phishing themes; enable Safe Links and impersonation protection, and prioritise awareness training on the dominant lure types." + }, + "name": "text - Phish Section1 Banner", + "id": "ce5e489f-c83b-4bc8-9e63-b08dfb5ef31f" + }, + { + "type": 1, + "content": { + "json": "### Phish Detection Trend
\r\n\r\n**This visual displays a per-{Granularity} trend of email Phish detections identified by Microsoft Defender for Office 365. The area chart summarises the number of messages flagged for Phish threats.**" + }, + "name": "text - Phish Trend Header", + "id": "429ef4d2-61a9-40d0-940f-2212ddce22ce" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections over time summarizing the data daily.\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has \"Phish\"\r\n| summarize PhishDetections = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, PhishDetections = coalesce(PhishDetections, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "PhishDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b0d170ec-331c-4ad0-8ce6-258704cc5345" + }, + { + "type": 1, + "content": { + "json": "### Phish Detection Trend - Advanced Threats
\r\n\r\n**Not all threats are easily recognizable, which is why Microsoft Defender for Office 365 uses advanced detection methods, including virtual sandbox environments to detonate URLs and files. These virtual sandbox technologies look for known patterns, such as a recognisable login page in a URL, or a file accessing command and control infrastructure. This visual displays a per-{Granularity} trend of Phish detections of these advanced threats.**" + }, + "name": "text - Phish AdvThreats Header", + "id": "425476e0-066a-42ee-afb9-5dabc612a3c8" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections over time summarizing the data daily by Phish detection technologies/controls used for detecting unknown-unique phish.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| project Timestamp, RecipientEmailAddress, NetworkMessageId, DT=parse_json(DetectionMethods)\r\n| evaluate bag_unpack(DT)\r\n| summarize [\"File detonation\"]=countif(Phish has 'File detonation' and Phish !has 'File detonation reputation'), [\"URL detonation\"]=countif(Phish has 'URL detonation' and Phish !has 'URL detonation reputation') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, [\"File detonation\"]=coalesce([\"File detonation\"],0), [\"URL detonation\"]=coalesce([\"URL detonation\"],0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "URL detonation", + "color": "orangeDark" + }, + { + "seriesName": "File detonation", + "color": "redDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish AdvThreats Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6b62347a-b162-49e6-891c-07697af22dd9" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - LLM content analysis
\r\n\r\n**Microsoft Defender for Office 365 uses Language AI for Phish and Business Email Compromise (BEC) detection. These models are progressively learning from thousands of real-world phishing attempts and analyzing all messages classified as phish. Furthermore, it incorporates advanced Machine Learning and Natural Language Processing (NLP) techniques to read, process, and understand email content the way a human analyst might, yet in a fraction of the time and at a large scale. [Learn more](https://techcommunity.microsoft.com/blog/microsoftdefenderforoffice365blog/microsoft-defender-for-office-365s-language-ai-for-phish-enhancing-email-securit/4410446)**" + }, + "customWidth": "50", + "name": "text - Phish LLM Content Header", + "id": "c23460b1-e025-4f6c-b2d5-3f78c0c9afc6" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - LLM Threat Classifications
\r\n\r\n**Microsoft Defender for Office 365 uses purpose-built Large Language Models (LLM) at scale to provide AI-powered email and collaboration security. Our solution now parses language to understand and identify attacker intent and classifies threats at machine speed – keeping malicious emails out of your inbox and giving security operations (SOC) teams a new level of insight into adversary techniques. [Learn more](https://techcommunity.microsoft.com/blog/microsoftdefenderforoffice365blog/microsoft-ignite-redefining-email-security-with-llms-to-tackle-a-new-era-of-soci/4302421)**" + }, + "customWidth": "50", + "name": "text - Phish LLM ThreatClass Header", + "id": "1d723c26-501f-4385-9331-957ab7ae5019" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails detected as Phish by LLM content analysis detection technology in Microsoft Defender for Office 365. \r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has 'Phish' and DetectionMethods contains \"LLM content analysis\"\r\n| summarize count()\r\n| sort by count_ desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "statSettings": { + "valueAggregation": "None", + "colorSettings": { + "type": "thresholds", + "mode": "foreground", + "thresholdsGrid": [ + { + "operator": ">", + "thresholdValue": "0", + "representation": "red" + }, + { + "operator": "<=", + "thresholdValue": "0", + "representation": "red" + } + ] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "tagText": "", + "valueFontStyle": "auto", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish LLM Content Count", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "86a301c5-2bc0-436a-982c-861beee7c9ab" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by intent of the message.\r\n// Microsoft Defender for Office 365 LLM analysis is analyzing email messages to understand the intent of the messages. These threat classifications are then used in filtering decisions.\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has 'Phish' and ThreatClassification has_any(\"Business intelligence\",\"Contact establishment\",\"Gift card\",\"Invoice\",\"Payroll\",\"PII gathering\",\"Task\")\r\n| summarize count() by ThreatClassification\r\n| sort by count_ desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish LLM ThreatClass Pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d547b730-f174-4f78-8998-02f24453304e" + }, + { + "type": 1, + "content": { + "json": "### Top Attacked Users by LLM Threat classes (Phish)
\r\n\r\n**Displays recipients most frequently targeted by inbound phishing emails, grouped by threat classification (e.g., Gift Card, Invoice, Payroll). Helps identify users at higher risk for phishing attacks. These users may be at higher risk and should be prioritised for targeted cybersecurity awareness training. Training should cover the specific threat types and techniques they are exposed to, and reinforce best practices for promptly reporting any suspicious messages that might bypass security controls and reach their inbox.**" + }, + "customWidth": "100", + "name": "text - Phish LLM TopUsers Header", + "id": "4ba9d9eb-d88d-4e5d-ba58-a740559677f7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Phish detections in emails summarizing by various Threat classes showing the top attacked user for each threat classification type.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has \"Phish\" and EmailDirection == \"Inbound\" and ThreatClassification has_any(\"Business intelligence\",\"Contact establishment\",\"Gift card\",\"Invoice\",\"Payroll\",\"PII gathering\",\"Task\")\r\n| summarize EmailCount=count() by ThreatClassification, RecipientEmailAddress\r\n| summarize Emails = arg_max(EmailCount, RecipientEmailAddress) by ThreatClassification\r\n| sort by Emails desc\r\n| project ['Threat Classification'] = ThreatClassification, ['Top Recipient'] = RecipientEmailAddress, ['Emails'] = Emails", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "80px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish LLM TopUsers", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "51599ab2-db69-4195-b4e9-2828729ec35b" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "group - 5", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "25c47f6a-3525-435e-90cf-357f02fb2fed" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Phish Detections by Delivery location, Detection technology and Sender infrastructure insights\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Phish detections delivery locations, detection technologies used for detections, sender infrastructure insights in inbound email identified by Microsoft Defender for Office 365 as Phish.

**Recommended action:** Verify anti-phishing and Safe Links policies cover these delivery paths; consider blocking sender infrastructure from regions you do not operate in, where appropriate." + }, + "name": "text - Phish Section2 Banner", + "id": "6876063e-6a4f-48ea-829d-4486922783dd" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections by delivery location
\r\n\r\n**Visualizes counts (per {Granularity}) of Phish detections of inbound emails by various delivery locations: Quarantine, Junk folder or Failed (rejected with or without NDR)**" + }, + "name": "text - Phish DeliveryLoc Header", + "id": "b5045aab-1b4b-4d35-af41-a6315d36e864" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections over time summarizing the data daily by Delivery Location.\r\n//The comment in the query excludes deliveries to the SecOps Mailboxes and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\" and EmailDirection == \"Inbound\"\r\n| summarize TotalPhishDetections=count(), Quarantine=countif(DeliveryLocation == \"Quarantine\"), Junkfolder=countif(DeliveryLocation == \"Junk folder\"), Inbox=countif(DeliveryLocation == \"Inbox/folder\"), Failed=countif(DeliveryLocation == \"Failed\"), Dropped=countif(DeliveryLocation == \"Dropped\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, TotalPhishDetections=coalesce(TotalPhishDetections,0), Quarantine=coalesce(Quarantine,0), Junkfolder=coalesce(Junkfolder,0), Inbox=coalesce(Inbox,0), Failed=coalesce(Failed,0), Dropped=coalesce(Dropped,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Quarantine", + "color": "greenDark" + }, + { + "seriesName": "Failed", + "color": "green" + }, + { + "seriesName": "Dropped", + "color": "green" + }, + { + "seriesName": "Junk folder", + "color": "orangeDark" + }, + { + "seriesName": "Inbox", + "color": "redBright" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish DeliveryLoc Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e839848c-d176-4251-bbb4-1c2e1103ed2d" + }, + { + "type": 1, + "content": { + "json": "### Phish detections by Detection Technology
\r\n\r\n**Visualizes counts (per {Granularity}) of Phish detections of inbound emails by various Microsoft Defender for Office 365 detection technologies.**" + }, + "name": "text - Phish DetTech Header", + "id": "149bf1b3-80cc-4e82-ae5d-ddee0f6b0cd9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections over time summarizing the data daily by various Phish Detection technologies/controls in Microsoft Defender for Office 365.\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "createOtherGroup": 15 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish DetTech Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b0b16329-e1a6-4138-871e-76d57a60b978" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarized by individual Phish detection technology/control in Microsoft Defender for Office 365.\r\n//Each detection technology is counted individually via mv-expand over DetectionMethods.Phish (matching the sibling trend line chart), so a message flagged by multiple techniques counts once per technique.\r\n//The where clause excludes deliveries to the SecOps Mailbox and by the Phish Simulation system.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details\r\n| sort by Count desc\r\n| project ['Detection Technology'] = Details, ['Detections'] = Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish DetTech Pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5270ba04-599f-4940-805b-687f7475bc70" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections by SenderIPv4 Geo Location
\r\n\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Phish, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" + }, + "name": "text - Phish Geo Header", + "id": "ddd0c12f-1bb1-4d7d-afb4-f28bcfcd7c4b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by email sender IP address (SenderIPv4).\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has \"Phish\" and isnotempty(SenderIPv4)\r\n| summarize count() by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "map", + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "none" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish Geo Map", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "85ea7223-7d77-43f5-b0d9-e0de7c898758" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where ThreatTypes has 'Phish' and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Phish Emails'] = count_\r\n| sort by ['Phish Emails'] desc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Phish Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "heatmap", + "heatmapPalette": "red" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish Country Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f561209b-15a6-442e-af10-63e375088209" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "group - 25- Phish delivery locations-detecion tech-sender infra", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "10f3e3eb-b330-4955-952e-01eff69405e9" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Phish Detections Top attacked users and top senders\r\n
\r\n\r\nThis section consolidates key visuals that track and explain phish detections in inbound email as identified by Microsoft Defender for Office 365 focusing on top attacked users and top senders.

**Recommended action:** Enroll the most-targeted users in security awareness training and consider blocking persistent phishing sender domains." + }, + "name": "text - Phish Section3 Banner", + "id": "f46ed4a8-e2b5-4ccd-ae38-efc571bfc791" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections top attacked users\r\n**Displays the top 10 recipient email addresses that received inbound emails flagged as Phish. These users may be at higher risk and should be prioritised for targeted cybersecurity awareness training. Training should cover the specific threat types and techniques they are exposed to, and reinforce best practices for promptly reporting any suspicious messages that might bypass security controls and reach their inbox.**" + }, + "customWidth": "100", + "name": "text - Phish TopUsers Header", + "id": "96d9b543-070a-42d4-bbed-3f5cf79ca7ce" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails with Phish detections summarizing the data by the top 15 recipient email address (RecipientEmailAddress).\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),PhishEmailCount = countif(ThreatTypes has \"Phish\") by RecipientEmailAddress\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(PhishEmailCount / todouble(TotalEmailCount) * 100, 2))\r\n| where PhishEmailCount !=0\r\n| top 15 by PhishEmailCount\r\n| project ['Recipient'] = RecipientEmailAddress, ['Phish Emails'] = PhishEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Phish Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish TopRecipients Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "25100115-78d3-4144-b44e-613b44f02484" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains with Phish Detections (Inbound)\r\n**Displays the top 10 sender domains sending inbound emails detected as Phish. Helps identify external sources most frequently associated with malicious content for prioritised threat monitoring and mitigation.**" + }, + "customWidth": "100", + "name": "text - Phish TopSenders Header", + "id": "e7fcb7fe-4bca-4153-a9b0-8ded135b1c64" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by the top 15 email sender P2 domain (SenderFromDomain), now including the Phish confidence split (High/Normal) and the aggregated phish detection methods seen per domain. Adding additional insights for total inbound emails and bad traffic percentage for each sender domain.\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where EmailDirection == \"Inbound\"\r\n| extend PhishConf = tostring(parse_json(ConfidenceLevel).Phish)\r\n| extend PhishMethods = parse_json(DetectionMethods).Phish\r\n| summarize TotalEmailCount = count(),\r\n PhishEmailCount = countif(ThreatTypes has \"Phish\"),\r\n Phish_High = countif(ThreatTypes has \"Phish\" and PhishConf == \"High\"),\r\n Phish_Normal = countif(ThreatTypes has \"Phish\" and PhishConf == \"Normal\"),\r\n PhishMethodSet = make_set_if(PhishMethods, ThreatTypes has \"Phish\") by SenderFromDomain\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(PhishEmailCount / todouble(TotalEmailCount) * 100, 2))\r\n| where PhishEmailCount != 0\r\n| top 15 by PhishEmailCount\r\n| mv-apply S = PhishMethodSet on ( mv-expand m = S to typeof(string) | summarize Methods = make_set(m) )\r\n| project ['Sender Domain'] = SenderFromDomain, ['Phish Emails'] = PhishEmailCount, ['Phish (High)'] = Phish_High, ['Phish (Normal)'] = Phish_Normal, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound, ['Detection Methods'] = strcat_array(Methods, \", \")", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Phish Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish (High)", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish (Normal)", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "BadEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish TopSenders Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "717bfce8-b5d4-4900-99db-4ba0c503591d" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "group - 26-PhishDetectionsTopattackedusers-topsenders", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "553afca2-caa1-45b1-bec0-dca426b5be46" + }, + { + "type": 1, + "content": { + "json": "# Spam Detection Insights\r\n\r\n---\r\nThis tab provides insights into email message **detections** by Microsoft Defender for Office 365 where the message contained a **Spam threat** within its **email content**, **URLs**, or **attachments**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "4" + }, + "name": "text - Spam Tab Intro", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a693a05a-a772-4ac4-9863-07ad0d1b7092" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//KPI summary of inbound email spam detections for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet sp = EmailEvents | where EmailDirection == \"Inbound\" | where ThreatTypes has \"Spam\";\r\nlet junk = sp | where DeliveryLocation has \"Junk\";\r\nlet spTrend = toscalar(sp | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet junkTrend = toscalar(junk | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(sp | summarize count()), Details = \"Spam Emails\", Ord = 1, Trend = spTrend),\r\n(print Count = toscalar(sp | summarize dcount(RecipientEmailAddress)), Details = \"Users Targeted\", Ord = 2, Trend = spTrend),\r\n(print Count = toscalar(sp | summarize dcount(SenderFromDomain)), Details = \"Sender Domains\", Ord = 3, Trend = spTrend),\r\n(print Count = toscalar(junk | summarize count()), Details = \"Sent to Junk\", Ord = 4, Trend = junkTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "4" + }, + "name": "spam kpi strip", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "cadd5331-1db8-4ac8-bc99-42cd5227ee51" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Spam Detection Effectiveness and Trends\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Spam detections in inbound email as identified by Microsoft Defender for Office 365 focusing on Effectiveness and per-{Granularity} trend. For effectiveness, we consider messages reported by your admins and decisions made post-delivery.

**Recommended action:** If legitimate mail is marked as spam, review the Spam and Bulk thresholds; if spam is leaking through, tighten them." + }, + "name": "text - Spam Section1 Banner", + "id": "1093f3b6-cea7-4f54-9029-f9aadd79ca9f" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query calculates the effectiveness of spam detections without edge data.\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\n// baseQuery _FN_Admin_Submissions_SPM\r\nlet _FN_Admin_Submissions_SPM = toscalar(\r\nCloudAppEvents\r\n| where Timestamp between (minTime .. maxTime)\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType)\r\n| extend NetworkMessageId = tostring((parse_json(RawEventData)).ObjectId)\r\n| where SubmissionType in (\"0\")\r\n| summarize count()\r\n);\r\n// baseQuery _FN_ZAP_Successful_Spam\r\nlet _FN_ZAP_Successful_Spam = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and ActionType == \"Spam ZAP\" and ActionResult == \"Success\" and Timestamp between (minTime .. maxTime)\r\n| summarize count()\r\n //Take all our Spam ZAP, and count how many messages we missed and successfully cleaned up.\r\n);\r\n// baseQuery _FN_ZAP_Unsuccessful_Spam\r\nlet _FN_ZAP_Unsuccessful_Spam = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and ActionType == \"Spam ZAP\" and ActionResult != \"Success\" and Timestamp between (minTime .. maxTime)\r\n| summarize count()\r\n//Take all our Spam ZAP, and count how many messages we failed to clean up due to error or users/admins/API vendors getting to the message first.\r\n);\r\n// baseQuery _SPAM_ZAP_FP\r\nlet _SPAM_ZAP_FP = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and Action has_any (\"Redelivery\",\"Reprocessed\") and Timestamp between (minTime .. maxTime)\r\n| join kind=leftsemi (\r\n EmailEvents\r\n | where Timestamp between (minTime ..maxTime )\r\n | where ThreatTypes contains \"Spam\"\r\n | project NetworkMessageId, ThreatTypes)\r\n on NetworkMessageId\r\n| summarize count()\r\n// count all the FPs which were originally Spam, and when we TT'd them were not so we can subtract that from our mailfow catch, and therefore the total true bad.\r\n);\r\n// baseQuery _Spam_Mailflow\r\nlet _Spam_Mailflow = toscalar(\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and ThreatTypes == \"Spam\" and Timestamp between (minTime .. maxTime)\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count()\r\n// Get all the mailflow detected as SPM, then count all the NMIDs (not distinct)\r\n);\r\nprint\r\nEffectiveness_PostDelivery = abs(round(((toreal(toscalar(_FN_Admin_Submissions_SPM))+toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)))/(toreal(toscalar(_Spam_Mailflow))+toreal(toscalar(_FN_ZAP_Successful_Spam))+toreal(toscalar(_FN_ZAP_Unsuccessful_Spam))+toreal(toscalar(_FN_Admin_Submissions_SPM))-toreal(toscalar(_SPAM_ZAP_FP)))*100-100),2))", + "size": 1, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "statSettings": { + "valueAggregation": "None", + "colorSettings": { + "type": "thresholds", + "mode": "foreground", + "heatmapPalette": "greenRed", + "thresholdsGrid": [ + { + "operator": ">", + "thresholdValue": "95", + "representation": "green" + }, + { + "operator": "<=", + "thresholdValue": "95", + "representation": "orange" + }, + { + "operator": "<=", + "thresholdValue": "90", + "representation": "red" + } + ] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "numberFormatSettings": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "tagText": "Spam Effectiveness (without Edge data)", + "valueFontStyle": "superLarge", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Effectiveness Stat", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "036851c1-489e-4fda-8059-850c161578b3" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\n// baseQuery _FN_Admin_Submissions_SPM\r\nlet _FN_Admin_Submissions_SPM = toscalar(\r\nCloudAppEvents\r\n| where Timestamp between (minTime .. maxTime)\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType)\r\n| extend NetworkMessageId = tostring((parse_json(RawEventData)).ObjectId)\r\n| where SubmissionType in (\"0\")\r\n| summarize count()\r\n);\r\n// baseQuery _FN_ZAP_Successful_Spam\r\nlet _FN_ZAP_Successful_Spam = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and ActionType == \"Spam ZAP\" and ActionResult == \"Success\" and Timestamp between (minTime .. maxTime)\r\n| summarize count()\r\n //Take all our Spam ZAP, and count how many messages we missed and successfully cleaned up.\r\n);\r\n// baseQuery _FN_ZAP_Unsuccessful_Spam\r\nlet _FN_ZAP_Unsuccessful_Spam = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and ActionType == \"Spam ZAP\" and ActionResult != \"Success\" and Timestamp between (minTime .. maxTime)\r\n| summarize count()\r\n//Take all our Spam ZAP, and count how many messages we failed to clean up due to error or users/admins/API vendors getting to the message first.\r\n);\r\n// baseQuery _SPAM_ZAP_FP\r\nlet _SPAM_ZAP_FP = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and Action has_any (\"Redelivery\",\"Reprocessed\") and Timestamp between (minTime .. maxTime)\r\n| join kind=leftsemi (\r\n EmailEvents\r\n | where Timestamp between (minTime ..maxTime )\r\n | where ThreatTypes contains \"Spam\"\r\n | project NetworkMessageId, ThreatTypes)\r\n on NetworkMessageId\r\n| summarize count()\r\n// count all the FPs which were originally Spam, and when we TT'd them were not so we can subtract that from our mailfow catch, and therefore the total true bad.\r\n);\r\n// baseQuery _Spam_Mailflow\r\nlet _Spam_Mailflow = toscalar(\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and ThreatTypes == \"Spam\" and Timestamp between (minTime .. maxTime)\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count()\r\n// Get all the mailflow detected as SPM, then count all the NMIDs (not distinct)\r\n);\r\nprint StatisticName=\"Spam Mailflow Minus FPs\", Value=toreal((toscalar(_Spam_Mailflow)) - toreal(toscalar(_SPAM_ZAP_FP)))\r\n| union (print StatisticName=\"Spam Admin FNs Submitted\", Value=toreal(toscalar(_FN_Admin_Submissions_SPM)))\r\n| union (print StatisticName=\"Spam FPs Reverse Zapped\", Value=toreal(toscalar(_SPAM_ZAP_FP)))\r\n| union (print StatisticName=\"Spam Zapped Successfully\", Value=toreal(toscalar(_FN_ZAP_Successful_Spam)))\r\n| union (print StatisticName=\"Spam NotZapped\", Value=toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)))\r\n| union (print StatisticName=\"Spam Effectiveness Post Delivery %\", Value=abs(round(((toreal(toscalar(_FN_Admin_Submissions_SPM)) + toreal(toscalar(_FN_ZAP_Unsuccessful_Spam))) / (toreal(toscalar(_Spam_Mailflow)) + toreal(toscalar(_FN_ZAP_Successful_Spam)) + toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)) + toreal(toscalar(_FN_Admin_Submissions_SPM)) - toreal(toscalar(_SPAM_ZAP_FP)))) * 100 - 100, 2)))\r\n| union (print StatisticName=\"Spam Effectiveness Pre-Delivery %\", Value=abs(round(((toreal(toscalar(_FN_Admin_Submissions_SPM)) + toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)) + (toscalar(_FN_ZAP_Successful_Spam))) / (toreal(toscalar(_Spam_Mailflow)) + toreal(toscalar(_FN_ZAP_Successful_Spam)) + toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)) + toreal(toscalar(_FN_Admin_Submissions_SPM)) - toreal(toscalar(_SPAM_ZAP_FP)))) * 100 - 100, 2 )))\r\n| project ['Statistic'] = StatisticName, Value", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "tileSettings": { + "showBorder": false, + "titleContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Value", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Value", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 2 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Effectiveness Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8d456ea2-f04a-4d71-95c6-fbaad8c2d2f2" + } + ] + }, + "customWidth": "100", + "name": "Spam Effectiveness", + "id": "82812b88-e7f7-4be0-9d13-8e7a7d8c0c4e" + }, + { + "type": 1, + "content": { + "json": "### Spam Detection Trend
\r\n\r\n**This visual displays a per-{Granularity} trend of email Spam detections identified by Microsoft Defender for Office 365. The area chart summarises the number of messages flagged for Spam threats.**" + }, + "name": "text - Spam Trend Header", + "id": "b5574a88-430b-4cca-a76e-9a0b07e9da2e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where ThreatTypes has \"Spam\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, SpamDetections = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "SpamDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "09b7d330-1683-45c4-ac0e-8141580d13b5" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "4" + }, + "name": "group - 6-Spam-detections-trend", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "25273f47-8201-4565-8815-1d059ee8abb6" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Spam Detections by Delivery location, Detection technology, Sender infrastructure and Bulk insights\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Spam detections delivery locations, detection technologies used for detections, sender infrastructure and Bulk insights in inbound email identified by Microsoft Defender for Office 365 as Spam.

**Recommended action:** Raise the Bulk Complaint Level (BCL) threshold for noisy sender domains and consider blocking high-volume, low-value bulk senders where appropriate." + }, + "name": "text - Spam Section2 Banner", + "id": "b82f442b-a3a0-44f7-82df-2fd4a9594992" + }, + { + "type": 1, + "content": { + "json": "### Spam Detections by delivery location
\r\n\r\n**Visualizes counts (per {Granularity}) of Spam detections of inbound emails by various delivery locations Quarantine, Junk folder or Failed (rejected with or without NDR)**" + }, + "name": "text - Spam DeliveryLoc Header", + "id": "a6326d97-56cc-45fb-8019-e0c3346968f2" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections over time summarizing the data daily by Delivery Location.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Spam\" and EmailDirection == \"Inbound\"\r\n| summarize TotalSpamDetections=count(), Quarantine=countif(DeliveryLocation == \"Quarantine\"), Junkfolder=countif(DeliveryLocation == \"Junk folder\"), Inbox=countif(DeliveryLocation == \"Inbox/folder\"), Failed=countif(DeliveryLocation == \"Failed\"), Dropped=countif(DeliveryLocation == \"Dropped\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, TotalSpamDetections=coalesce(TotalSpamDetections,0), Quarantine=coalesce(Quarantine,0), Junkfolder=coalesce(Junkfolder,0), Inbox=coalesce(Inbox,0), Failed=coalesce(Failed,0), Dropped=coalesce(Dropped,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "TotalSpamDetections", + "color": "blue" + }, + { + "seriesName": "Quarantine", + "color": "greenDark" + }, + { + "seriesName": "Junkfolder", + "color": "orangeDark" + }, + { + "seriesName": "Inbox", + "color": "redBright" + }, + { + "seriesName": "Failed", + "color": "red" + }, + { + "seriesName": "Dropped", + "color": "redDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam DeliveryLoc Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "97f89032-34e3-40ff-bb88-42d195aea095" + }, + { + "type": 1, + "content": { + "json": "### Spam Detections Detection Technology
\r\n\r\n**Visualizes counts (per {Granularity}) of Spam detections of inbound emails by various Microsoft Defender for Office 365 detection technologies.**" + }, + "name": "text - Spam DetTech Header", + "id": "935ea90d-8430-49d5-b942-3a7b319a603e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections over time summarizing the data daily by various Spam Detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where DetectionMethods has \"Spam\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| mv-expand Details = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam DetTech Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f31ec0d1-04e1-4b2b-9b98-27289ca34b84" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections summarized by individual Spam detection technology/control in Microsoft Defender for Office 365.\r\n//Each technique is counted individually via mv-expand over DetectionMethods.Spam (matching the sibling trend line chart), so a message flagged by multiple techniques counts once per technique.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Spam\"\r\n| mv-expand Details = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details\r\n| sort by Count desc\r\n| project ['Detection Technology'] = Details, ['Detections'] = Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam DetTech Pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "95e40479-f0bc-41ff-8191-634b606d3632" + }, + { + "type": 1, + "content": { + "json": "### Spam Detections by SenderIPv4 Geo Location
\r\n\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Spam, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" + }, + "name": "text - Spam Geo Header", + "id": "614d1c3f-df6a-4659-b170-7b466c66d66f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections summarizing the data by email sender IP address (SenderIPv4).\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where ThreatTypes has \"Spam\" and isnotempty(SenderIPv4)\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_ ", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "map", + "mapSettings": { + "locInfo": "LatLong", + "locInfoColumn": "SenderIPv4", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "none" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Geo Map", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5519d715-dc79-45f8-8ed5-a63a253c45e3" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where ThreatTypes has 'Spam' and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Spam Emails'] = count_\r\n| sort by ['Spam Emails'] desc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spam Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "mapSettings": { + "locInfo": "LatLong", + "locInfoColumn": "SenderIPv4", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "heatmap", + "heatmapPalette": "red" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Country Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5078dc24-e8be-4943-98fc-6527968e1e3d" + }, + { + "type": 1, + "content": { + "json": "### Spam Detections Bulk Insights
\r\n\r\n**Displays the distribution of inbound emails across different Bulk Complaint Levels together with Top 10 domains sending Bulk email (grey mail). Helps identify patterns in bulk email complaints and assess potential spam or unwanted message trends.**" + }, + "name": "text - Spam Bulk Header", + "id": "cd7b3cbe-a6c1-422c-ab37-4afc26002d5d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails which has any Bulk complaint level. It is summarizing the data by the various Bulk Complaint levels to understand how many messages are detected with each Bulk Complaint level.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\" and isnotnull(BulkComplaintLevel)\r\n| summarize count() by BulkComplaintLevel\r\n| sort by BulkComplaintLevel desc\r\n| project ['Bulk Complaint Level'] = BulkComplaintLevel, Emails=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "blueDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Bulk By Level", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "021c022b-aa67-427d-9e1a-688af7aed5d4" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails which has any Bulk complaint level. It is summarizing the data by the various Bulk Complaint levels and SenderFromDomain of the email sender. It provides insights how many messages are detected with each Bulk Complaint level for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\" and isnotnull(BulkComplaintLevel)\r\n| summarize count() by BulkComplaintLevel, SenderFromDomain\r\n| top 10 by count_ desc\r\n| project ['Sender Domain'] = SenderFromDomain, ['Bulk Complaint Level'] = BulkComplaintLevel, Emails=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Bulk By Domain", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b1835e0f-f9ad-44c3-bba4-cf9a9546d09a" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "4" + }, + "name": "group - 28-Spam-Delivery location-Detection technology-Sender infrastructure insights", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "307d3d03-93ae-4c8f-b68b-f833ee7d38e8" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n\r\n
Spam Detections Top attacked users and top senders\r\n
\r\n\r\nThis section consolidates key visuals that track and explain spam detections in inbound email as identified by Microsoft Defender for Office 365 focusing on top attacked users and top senders.

**Recommended action:** Review the most-affected users and the top spam sender domains as possible block-list candidates." + }, + "name": "text - Spam Section3 Banner", + "id": "4c34ed7b-86da-4ee1-8a69-f96c213a4340" + }, + { + "type": 1, + "content": { + "json": "### Spam Detections top attacked users
\r\n\r\n**Displays the top 10 recipient email addresses that received inbound emails flagged as Spam. These users may be at higher risk and should be prioritised for targeted cybersecurity awareness training. Training should cover the specific threat types and techniques they are exposed to, and reinforce best practices for promptly reporting any suspicious messages that might bypass security controls and reach their inbox.**" + }, + "customWidth": "100", + "name": "text - Spam TopUsers Header", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "be708ad5-51fd-4a54-b1bc-f912e12b4a01" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails with Spam detections summarizing the data by the top 15 recipient email address (RecipientEmailAddress).\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where EmailDirection ==\"Inbound\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),SpamEmailCount = countif(ThreatTypes has \"Spam\") by RecipientEmailAddress\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(SpamEmailCount / todouble(TotalEmailCount)* 100, 2))\r\n| where SpamEmailCount !=0\r\n| top 15 by SpamEmailCount\r\n| project ['Recipient'] = RecipientEmailAddress, ['Spam Emails'] = SpamEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spam Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "40ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal", + "useGrouping": false + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam TopRecipients Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6e7b357d-6792-41c5-83fc-efae31afe2ee" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains with Spam Detections (Inbound)
\r\n\r\n**Displays the top 10 sender domains sending inbound emails detected as Spam. Helps identify external sources most frequently associated with spam content for prioritised monitoring and mitigation.**" + }, + "customWidth": "100", + "name": "text - Spam TopSenders Header", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1d1bdb8d-9619-488b-935a-3791ad73f096" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails with Spam detections summarizing the data by the top 15 email sender P2 domain (SenderFromDomain). Adding additional insights for total inbound emails and bad traffic percentage for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where EmailDirection == \"Inbound\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount = count(),\r\n SpamEmailCount = countif(ThreatTypes has \"Spam\") by SenderFromDomain\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(SpamEmailCount / todouble(TotalEmailCount) * 100, 2))\r\n| where SpamEmailCount !=0\r\n| top 15 by SpamEmailCount\r\n| project ['Sender Domain'] = SenderFromDomain, ['Spam Emails'] = SpamEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spam Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "40ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam TopSenders Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "253efada-ca89-49c5-b1e3-e42ac005b938" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "4" + }, + "name": "group - 29-Spam Detections Top attacked users and top senders", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "d4cc057f-c9b7-40b9-85d3-52f90767d1f5" + }, + { + "type": 1, + "content": { + "json": "# Email Impersonation & BEC Insights\r\n\r\n---\r\nThis tab focuses on the highest-value email threat class: **impersonation and Business Email Compromise (BEC)**. It brings together impersonation and spoof detections, sender authentication (DMARC, DKIM, SPF, CompAuth), supply-chain and partner-compromise correlation, and first-contact / new-vendor senders - the signals that precede targeted financial and credential attacks. It is the email-side companion to the impersonation insights on the **Teams & Collaboration** tab." + }, + "name": "text - impersonation bec description", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "id": "fda8ccd5-fafc-457a-a6a2-05b504be1023" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//KPI summary of inbound email impersonation and spoof (BEC) detections for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet bec = EmailEvents | where EmailDirection == \"Inbound\" | where DetectionMethods has \"Impersonation\" or DetectionMethods has \"Spoof\";\r\nlet inbox = bec | where DeliveryLocation has \"Inbox\";\r\nlet becTrend = toscalar(bec | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet inboxTrend = toscalar(inbox | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(bec | summarize count()), Details = \"Impersonation / Spoof Emails\", Ord = 1, Trend = becTrend),\r\n(print Count = toscalar(bec | summarize dcount(RecipientEmailAddress)), Details = \"Users Targeted\", Ord = 2, Trend = becTrend),\r\n(print Count = toscalar(bec | summarize dcount(SenderFromDomain)), Details = \"Spoofed Sender Domains\", Ord = 3, Trend = becTrend),\r\n(print Count = toscalar(inbox | summarize count()), Details = \"Delivered to Inbox\", Ord = 4, Trend = inboxTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "name": "bec kpi strip", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "91fdd28f-31c4-4f94-b60a-12cd97d44ddf" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Phish Detections Business Email Compromise (BEC) detections\r\n
\r\n\r\nThis section consolidates key visuals that track and explain phish detections in inbound email as identified by Microsoft Defender for Office 365 focusing on Business Email Compromise (BEC) detections Impersonation and Spoof.

**Recommended action:** Enable mailbox intelligence and impersonation protection for frequently-impersonated users and domains; consider adding confirmed look-alike domains to the Tenant Block List." + }, + "name": "text - Phish BEC Banner", + "id": "e3b2232c-8056-4913-a652-64f70e228750" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Impersonation detections Trend\r\n**Displays counts (per {Granularity}) of inbound emails flagged for Business Email Compromise (BEC) using Impersonation detection methods by Microsoft Defender for Office 365. Helps track impersonation attack patterns over time.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Imp Trend Header", + "id": "e95667df-3bcd-4023-9e8f-99ed05bc4bf0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Impersonation detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has 'Impersonation'\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ImpersonationDetections = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "ImpersonationDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Imp Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "61fa166d-f300-42a6-a324-de18b3fdf4c1" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Impersonation detections by Detection Technology\r\n**Visualizes counts (per {Granularity}) of Phish detections of inbound emails by various Microsoft Defender for Office 365 detection technologies used for detecting Impersonations.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Imp Tech Header", + "id": "09e1a866-f344-4a92-a3bd-8c3c3c5d598d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Impersonation detections over time summarizing the data daily by various Impersonation Detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where Details has \"Impersonation\"\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Imp Tech Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6cd5662f-13b4-4a9b-afe7-0a6343e3ab5c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish - Business Email Compromise (BEC) - Impersonation detections summarized by individual detection technology/control in Microsoft Defender for Office 365.\r\n//Each technique is counted individually via mv-expand over DetectionMethods.Phish (matching the sibling trend line chart), so a message flagged by multiple techniques counts once per technique.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where Details has \"Impersonation\"\r\n| summarize Count = count() by Details\r\n| sort by Count desc\r\n| project ['Detection Technology'] = Details, ['Detections'] = Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "graphSettings": { + "type": 0 + }, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Imp Tech Pie", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "73499618-e842-440e-a555-cd8849093884" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Impersonation detections by SenderIPv4 Geo Location\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Phish - Impersonation, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Imp Geo Header", + "id": "189a1ac1-f275-4697-880b-7ffae1e5d263" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Impersonation detections summarizing the data by email sender IP address (SenderIPv4).\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Impersonation\" and isnotempty(SenderIPv4)\r\n//| project Timestamp, EmailDirection, SenderFromAddress, AdditionalFields, SenderIPv4 \r\n| summarize count()by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_ ", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "map", + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "none" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish BEC Imp Geo Map", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "574b61ad-ec2d-4517-93c5-d0e9bd14f2e9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where DetectionMethods has \"Impersonation\" and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Impersonation Emails'] = count_\r\n| sort by ['Impersonation Emails'] desc", + "size": 0, + "showAnalytics": true, + "title": "Impersonation Detections-Sender Heatmap (IPv4)", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Impersonation Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "heatmap", + "heatmapPalette": "red" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish BEC Imp Country", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e53b7dbc-4683-4309-b879-c7be68599159" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Spoof detections Trend\r\n**Displays counts (per {Granularity}) of inbound emails flagged for Business Email Compromise (BEC) using Spoof detection methods by Microsoft Defender for Office 365. Helps track Spoofing based attack patterns over time.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Spoof Trend Header", + "id": "8db0f1b0-49bf-43a2-9f9f-164eb9530629" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Spoof detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has 'Spoof'\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, SpoofDetections = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "SpoofDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Spoof Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "9a308cd9-bf05-4287-b0d5-54636d081a82" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Spoof detections Trend by Detection Technology\r\n**Visualizes counts (per {Granularity}) of Phish detections of inbound emails by various Microsoft Defender for Office 365 detection technologies used for detecting Spoofing.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Spoof Tech Header", + "id": "28c9c15d-d22f-4412-9efc-868b95082668" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Spoof detections over time summarizing the data daily by various Spoof Detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where Details has \"Spoof\"\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "yAxis": [ + "Count" + ], + "seriesLabelSettings": [ + { + "seriesName": "[[\"Spoof external domain\"]", + "color": "redDark" + }, + { + "seriesName": "[[\"Spoof intra-org\"]", + "color": "orangeDark" + }, + { + "seriesName": "[[\"Spoof DMARC\"]", + "color": "yellowDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Spoof Tech Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1a1328fc-5404-4dff-99ed-3a30082a4cbe" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish - Business Email Compromise (BEC) - Spoof detections summarized by individual detection technology/control in Microsoft Defender for Office 365.\r\n//Each technique is counted individually via mv-expand over DetectionMethods.Phish (matching the sibling trend line chart), so a message flagged by multiple techniques counts once per technique.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where Details has \"Spoof\"\r\n| summarize Count = count() by Details\r\n| sort by Count desc\r\n| project ['Detection Technology'] = Details, ['Detections'] = Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Spoof Tech Pie", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "f7df9892-85b4-49c3-8739-873b745183a3" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Spoof detections by SenderIPv4 Geo Location\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Phish - Spoofing, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Spoof Geo Header", + "id": "3c83e7f0-5391-4b1a-bb5b-de0d17488efd" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Spoof detections summarizing the data by email sender IP address (SenderIPv4).\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Spoof\" and isnotempty(SenderIPv4)\r\n//| project Timestamp, EmailDirection, SenderFromAddress, AdditionalFields, SenderIPv4 \r\n| summarize count()by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_ ", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "map", + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "none" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish BEC Spoof Geo Map", + "styleSettings": { + "margin": "15px", + "padding": "15px" + }, + "id": "122d860c-ab0d-475e-b29e-2955020680c7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where DetectionMethods has \"Spoof\" and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Spoof Emails'] = count_\r\n| sort by ['Spoof Emails'] desc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spoof Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "heatmap", + "heatmapPalette": "red" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish BEC Spoof Country", + "styleSettings": { + "margin": "15px", + "padding": "15px" + }, + "id": "9d0111bc-8d01-4a99-9009-645dc02c3bed" + }, + { + "type": 1, + "content": { + "json": "### Supply-Chain & Partner Risk (Possible Partner Compromise)\r\n**Correlates the external domains your organization emails most with inbound emails from those same domains that carried threats. A trusted partner or supplier domain suddenly sending threats is a strong signal that the partner may be compromised - a common supply-chain and business email compromise (BEC) vector.**

**Recommended action:** Verify any flagged partner through a trusted channel before acting on their recent messages, alert them to a possible compromise, and consider tightening inbound policy for that domain until confirmed clean." + }, + "customWidth": "100", + "name": "text - Phish Partner Compromise Header", + "id": "2c62c576-3b05-4663-ae2e-4f961d7409c6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises top outbound recipient domains by outbound email volume and shows total number of inbound emails with Threats from the same domains (as inbound senders) \r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Outbound\"\r\n| project RecipientDomain = tostring(split(RecipientEmailAddress, \"@\")[1])\r\n| summarize count() by RecipientDomain\r\n| project OutboundCount=count_, RecipientDomain, SenderFromDomain=RecipientDomain\r\n| join (EmailEvents | where EmailDirection == \"Inbound\" and isempty(ThreatTypes)==false) on SenderFromDomain\r\n| summarize max(OutboundCount),count() by SenderFromDomain\r\n| project SenderFromDomain, OutboundEmails=max_OutboundCount, IncomingEmailsWithThreats=count_\r\n| extend Bad_Traffic_Percentage = todouble(round(IncomingEmailsWithThreats / todouble(OutboundEmails) * 100, 2))\r\n| top 15 by OutboundEmails\r\n| project ['Sender Domain'] = SenderFromDomain, ['Outbound Emails'] = OutboundEmails, ['Inbound w/ Threats'] = IncomingEmailsWithThreats, ['Bad Traffic %'] = Bad_Traffic_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Outbound Emails", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Inbound w/ Threats", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "60ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish Partner Compromise", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1aaa047c-1108-4288-833e-61ca35b5495a" + }, + { + "type": 1, + "content": { + "json": "### Top Recipients Targeted by Impersonation / BEC\r\n**Lists the recipients most frequently targeted by impersonation and Business Email Compromise (BEC) attempts, showing the number of impersonation emails, how many distinct senders were involved, the top spoofed sender domains, and how many of those messages were delivered to the inbox. Helps identify high-risk users (often executives or finance staff) who may need extra protection or awareness.**" + }, + "customWidth": "100", + "name": "text - impersonation targets", + "id": "b1e7c2a4-9f3d-4a6b-8c12-7d5e9f0a1b23" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top recipients targeted by impersonation / BEC, with distinct senders, spoofed domains and how many landed in the inbox.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| where OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")\r\n| where DetectionMethods has \"Impersonation\"\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize ImpersonationEmails = count(),\r\n DistinctSenders = dcount(SenderFromAddress),\r\n TopSpoofedDomains = make_set(SenderFromDomain, 5),\r\n DeliveredToInbox = countif(DeliveryLocation has \"Inbox\")\r\n by RecipientEmailAddress\r\n| top 20 by ImpersonationEmails\r\n| project ['Recipient'] = RecipientEmailAddress, ['Impersonation Emails'] = ImpersonationEmails, ['Distinct Senders'] = DistinctSenders, ['Top Spoofed Domains'] = strcat_array(TopSpoofedDomains, \", \"), ['Delivered to Inbox'] = DeliveredToInbox", + "size": 0, + "title": "Top Recipients Targeted by Impersonation / BEC", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "showAnalytics": true, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Impersonation Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "name": "newviz - impersonation targets", + "id": "afe28369-af82-47ae-846d-179bd86b660e" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "name": "group - 7 - Phish-BEC-Insights", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "b7971cd9-d086-47c7-8f66-50956b9c56c3" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Phish Detections Sender Authentication details (DMARC, DKIM, SPF, CompAuth)\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Sender Authentication checks details in inbound email by Microsoft Defender for Office 365 focusing on the various Sender Authentication standards: DMARC, DKIM, SPF, CompAuth.

**Recommended action:** For domains failing DMARC/DKIM/SPF, verify your own outbound authentication is published and enforced (p=reject), and treat persistent external spoofers as possible block candidates." + }, + "name": "text - Phish Section5 Banner", + "id": "90d7a338-d943-4398-b788-bfd4f93007d4" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections Sender Authentication Trend (DMARC, DKIM, SPF, CompAuth)\r\n**Shows counts (per {Granularity}) of sender authentication check outcomes (DMARC, DKIM, SPF, CompAuth) performed by Microsoft Defender for Office 365 on inbound emails. Useful for monitoring authentication success and failure patterns over time to identify anomalies or potential phishing risks.**" + }, + "customWidth": "100", + "name": "text - Phish SenderAuth Trend Header", + "id": "4a0ab90e-55dd-4fa6-82c3-0edc57ce0966" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spoof- DMARC fails summarizing the data daily.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend DMARCFail = (tostring(parse_json(AuthenticationDetails).DMARC) == \"fail\") \r\n| summarize DMARCFail = sum(DMARCFail) by bin (Timestamp,{Granularity})", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "DMARCFail", + "color": "orangeDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish Auth DMARC Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "79920d30-01d4-4412-b994-853e50c9d7d8" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spoof- DKIM fails summarizing the data daily.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend DKIMFail = (tostring(parse_json(AuthenticationDetails).DKIM) == \"fail\") \r\n| summarize DKIMFail = sum(DKIMFail) by bin (Timestamp,{Granularity})", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "DKIMFail", + "color": "yellowDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish Auth DKIM Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "bf09ffd4-eee0-42f7-a507-1cf54d9c365a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spoof- SPF fails summarizing the data daily.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend SPFFail = (tostring(parse_json(AuthenticationDetails).SPF) == \"fail\") \r\n| summarize SPFFail = sum(SPFFail) by bin (Timestamp,{Granularity})", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "SPFFail", + "color": "purpleDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish Auth SPF Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "4d66fe13-9904-45cf-8783-f3ee984f3a66" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spoof- Composite Authentication fails summarizing the data daily.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend CompAuthFail = (tostring(parse_json(AuthenticationDetails).CompAuth) == \"fail\") \r\n| summarize CompAuthFail = sum(CompAuthFail) by bin (Timestamp,{Granularity})", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "CompAuthFail", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish Auth CompAuth Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "0968b828-23fe-4fa2-a5ea-8ab39362457f" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections Top Sender Domains with DMARC Failures (Inbound)\r\n**Displays the top 10 sender domains (P1 and P2) for inbound emails where Spoof-DMARC detection triggered. Includes total inbound email volume and calculates DMARC fail traffic percentage per domain to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "text - Phish Auth DMARC Domains Header", + "id": "24d4689a-eb6d-49f5-85a8-fcadca409f7a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spoof-DMARC fails detections summarizing the data by the top 10 email sender P2 domain (SenderFromDomain) and sender P1 domain (SenderMailFromDomain). Adding additional insights for total inbound emails and DMARC fail traffic percentage for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalEmailCount = count(),\r\n DMARCFailCount = countif(set_has_element(parse_json(DetectionMethods).Phish, \"Spoof DMARC\")) by P1Sender=SenderMailFromDomain, P2Sender=SenderFromDomain\r\n| extend DMARCFail_Traffic_Percentage = todouble(round(DMARCFailCount / todouble(TotalEmailCount) * 100, 2))\r\n| where DMARCFailCount !=0\r\n| top 10 by DMARCFailCount\r\n| project ['P1 Sender'] = P1Sender, ['P2 Sender'] = P2Sender, ['DMARC Failures'] = DMARCFailCount, ['Total Inbound'] = TotalEmailCount, ['DMARC Fail %'] = DMARCFail_Traffic_Percentage", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "DMARCFail", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "DMARC Fail %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "40ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish Auth DMARC Domains", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "642814ad-9d24-4be9-ae10-3578e89da05b" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections Top Sender Domains with Spoof External Domain Detections (Inbound)\r\n**Displays the top 10 sender domains (P1 and P2) for inbound emails flagged for Spoof External Domain detection. Includes total inbound email volume and calculates spoof traffic percentage per domain to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "text - Phish Auth SpoofExt Domains Header", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "993fdc34-354b-412e-be39-facbde4f4f0e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish-Spoof-external domain detections summarizing the data by the top 10 email sender P2 domain (SenderFromDomain) and sender P1 domain (SenderMailFromDomain). Adding additional insights for total inbound emails and Spoof external domain detection traffic percentage for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalEmailCount = count(),\r\n SpoofExternalCount = countif(set_has_element(parse_json(DetectionMethods).Phish, \"Spoof external domain\")) by P1Sender=SenderMailFromDomain, P2Sender=SenderFromDomain\r\n| extend SpoofExternal_Traffic_Percentage = todouble(round(SpoofExternalCount / todouble(TotalEmailCount) * 100, 2))\r\n| where SpoofExternalCount !=0\r\n| top 10 by SpoofExternalCount\r\n| project ['P1 Sender'] = P1Sender, ['P2 Sender'] = P2Sender, ['Spoof External'] = SpoofExternalCount, ['Total Inbound'] = TotalEmailCount, ['Spoof External %'] = SpoofExternal_Traffic_Percentage", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spoof External", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spoof External %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "40ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "SpoofExternalFail", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true, + "sortBy": [ + { + "itemKey": "Spoof External %", + "sortOrder": 2 + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish Auth SpoofExt Domains", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "69ca3799-d2d5-4896-b3a5-1eeba46f0b46" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections Top Sender Domains with Spoof Internal Domain Detections (Inbound)\r\n**Displays the top 10 sender domains (P1 and P2) for inbound emails flagged for Spoof Internal Domain detection. Includes total inbound email volume and calculates spoof traffic percentage per domain to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "text - Phish Auth SpoofInt Domains Header", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3fa33c5d-0eba-471f-b47f-0c12c1f770d6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish-Spoof-internal domain detections summarizing the data by the top 10 email sender P2 domain (SenderFromDomain) and sender P1 domain (SenderMailFromDomain). Adding additional insights for total inbound emails and Spoof internal domain detection traffic percentage for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalEmailCount = count(),\r\n SpoofInternalCount = countif(set_has_element(parse_json(DetectionMethods).Phish, \"Spoof intra-org\")) by P1Sender=SenderMailFromDomain, P2Sender=SenderFromDomain\r\n| extend SpoofInternal_Traffic_Percentage = todouble(round(SpoofInternalCount / todouble(TotalEmailCount) * 100, 2))\r\n| where SpoofInternalCount !=0\r\n| top 10 by SpoofInternalCount\r\n| project ['P1 Sender'] = P1Sender, ['P2 Sender'] = P2Sender, ['Spoof Internal'] = SpoofInternalCount, ['Total Inbound'] = TotalEmailCount, ['Spoof Internal %'] = SpoofInternal_Traffic_Percentage", + "size": 3, + "showAnalytics": true, + "title": "Top 10 Spoof intra-org detections by Sender domain (P1/P2)", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spoof Internal", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spoof Internal %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "40ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "SpoofIntraorgFail", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish Auth SpoofInt Domains", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "ae0c65c7-68ea-4d50-b177-1effeaf1c045" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "name": "group - 8-Phish-SenderAuth", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "8077779a-4da8-46be-8032-626bd8c36dbd" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
First-Contact & New-Vendor Senders\r\n
\r\n\r\nExternal email senders and domains seen for the first time in the selected period. New/first-contact relationships - especially ones already carrying threats - are a common precursor to phishing, business email compromise (BEC), and supply-chain attacks.

**Recommended action:** Treat brand-new domains sending threats as high-priority review; verify any that claim to be a known brand or partner before trusting their messages." + }, + "name": "phish fc banner", + "id": "05b83435-c7ed-48a3-919e-388b2e599726" + }, + { + "type": 1, + "content": { + "json": "### First-contact external senders
\r\n\r\n**External email senders ordered by when they were first seen in the period (most recent first). In tenants with longer history this highlights genuinely new senders.**" + }, + "customWidth": "100", + "name": "phish fc senders header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "c57dffb4-dfdb-4a1e-93be-16fa9e856a0d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists external email senders seen for the first time in the selected period (most recent first), surfacing new/first-contact senders. In tenants with longer history this highlights genuinely new relationships - a common precursor to BEC and supply-chain attacks.\r\n// TIP: to hide your own accepted domains, uncomment the ExcludeDomains line and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"fabrikam.com\"]);\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| extend SenderDomain = tostring(split(SenderFromAddress, \"@\")[1])\r\n| where isnotempty(SenderFromAddress)\r\n//| where SenderDomain !in~ (ExcludeDomains)\r\n| summarize FirstSeen=min(Timestamp), Messages=count(), ThreatMessages=countif(isnotempty(ThreatTypes)) by SenderFromAddress, SenderDomain\r\n| top 20 by FirstSeen desc\r\n| project ['Sender']=SenderFromAddress, ['Sender Domain']=SenderDomain, ['First Seen']=FirstSeen, Messages, ['Threat Messages']=ThreatMessages", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "phish fc senders table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d1ceb0ac-2dad-49af-b416-a3376a7b8513" + }, + { + "type": 1, + "content": { + "json": "### New sender domains carrying threats
\r\n\r\n**External sender domains seen for the first time in the period that already carried threats, most-recent first. A brand-new domain sending threats to your users is a strong early-warning signal.**" + }, + "customWidth": "100", + "name": "phish fc domains header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "bd29bbe4-cde2-499c-a1d0-e2cc51f7733d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists external sender domains seen for the first time in the selected period that already carried threats, ranked by most-recently first seen. A brand-new domain sending threats to your users is a strong early-warning signal for phishing and BEC.\r\n// TIP: to hide your own accepted domains, uncomment the ExcludeDomains line and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"fabrikam.com\"]);\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| extend SenderDomain = tostring(split(SenderFromAddress, \"@\")[1])\r\n| where isnotempty(SenderDomain)\r\n//| where SenderDomain !in~ (ExcludeDomains)\r\n| summarize FirstSeen=min(Timestamp), LastSeen=max(Timestamp), Messages=count(), Senders=dcount(SenderFromAddress), Recipients=dcount(RecipientEmailAddress), ThreatMessages=countif(isnotempty(ThreatTypes)) by SenderDomain\r\n| where ThreatMessages > 0\r\n| top 20 by FirstSeen desc\r\n| project ['Sender Domain']=SenderDomain, ['First Seen']=FirstSeen, Messages, Senders, Recipients, ['Threat Messages']=ThreatMessages, ['Last Seen']=LastSeen", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Senders", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Recipients", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "phish fc domains table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "7da952d5-5ae2-4b2e-a5cf-c78b11bda4f8" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "customWidth": "100", + "name": "group - Phish First Contact", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "90e5248a-2c35-48f3-869c-c45c631c6fbf" + }, + { + "type": 1, + "content": { + "json": "# URL Detections and URL Click Insights\r\n\r\n---\r\nThis tab provides insights into **URL-based detections** in email messages and details about URL clicks performed by end users on URLs identified as **malicious**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "5" + }, + "name": "text - 24 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "2156430d-fec6-48bb-a9a8-3166182f6993" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//KPI summary of URL threat protection (Safe Links clicks and URLs seen in email) for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet clicks = UrlClickEvents;\r\nlet blocked = clicks | where ActionType in (\"ClickBlocked\",\"ClickBlockedByTenantPolicy\");\r\nlet allowed = clicks | where ActionType == \"ClickAllowed\";\r\nlet blockedTrend = toscalar(blocked | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet allowedTrend = toscalar(allowed | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet usersTrend = toscalar(clicks | make-series Trend = dcount(AccountUpn) default = 0 on Timestamp step gran | project Trend);\r\nlet urlsTrend = toscalar(EmailUrlInfo | make-series Trend = dcount(Url) default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(blocked | summarize count()), Details = \"Malicious Clicks Blocked\", Ord = 1, Trend = blockedTrend),\r\n(print Count = toscalar(allowed | summarize count()), Details = \"Clicks Allowed Through\", Ord = 2, Trend = allowedTrend),\r\n(print Count = toscalar(clicks | summarize dcount(AccountUpn)), Details = \"Users Clicking Links\", Ord = 3, Trend = usersTrend),\r\n(print Count = toscalar(EmailUrlInfo | summarize dcount(Url)), Details = \"Distinct URLs in Email\", Ord = 4, Trend = urlsTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "5" + }, + "name": "url kpi strip", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d5e2326a-a5dd-4217-bb75-0e337d75d306" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Insights on URL-Based Threat Detections\r\n
\r\n\r\nThis section consolidates key visuals that track and explain URL based threat detections in inbound email as identified by Microsoft Defender for Office 365 focusing on per-{Granularity} trends of URL-based threat detections, QR code detections, and URL scans activity by locations.

**Recommended action:** Confirm Safe Links is enabled for email and Teams; investigate QR-code and URL detection spikes for emerging campaigns." + }, + "name": "text - 13 - Copy", + "id": "ed3468e7-1936-45fd-9168-93010a662302" + }, + { + "type": 1, + "content": { + "json": "### Trend of URL-Based Malware Threat Detections
\r\n\r\n**This visual displays a per-{Granularity} trend of emails with URL based Malware threat detections identified by Microsoft Defender for Office 365. The line chart summarises the number of messages flagged for malware threats.**" + }, + "name": "text - 13 - Copy - Copy", + "id": "77e7bbac-d752-478b-bce9-06bb1bd12bfe" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections over time summarizing the data daily by various Malware URL threat based detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Malware'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand MalwareMethod = ParsedMethods.Malware\r\n| where MalwareMethod contains \"URL\"\r\n| summarize Count = count() by MalwareMethod = tostring(MalwareMethod), Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct MalwareMethod | extend d = 1) on d | project Timestamp, MalwareMethod\r\n| join kind=leftouter (agg) on Timestamp, MalwareMethod\r\n| project Timestamp, MalwareMethod, Count = coalesce(Count, 0)\r\n| sort by MalwareMethod asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 8 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "79ef5e7b-57a6-4519-9899-18fd8cae5e68" + }, + { + "type": 1, + "content": { + "json": "### Trend of URL-Based Phish Threat Detections
\r\n\r\n**This visual displays a per-{Granularity} trend of emails with URL based Phish threat detections identified by Microsoft Defender for Office 365. The line chart summarises the number of messages flagged for Phish threats.**" + }, + "name": "text - 13 - Copy - Copy - Copy", + "id": "48923812-5440-4f47-8881-273f14cbfb8e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phishing detections over time summarizing the data daily by various Phishing URL threat based detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Phish'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand PhishMethod = ParsedMethods.Phish\r\n| where PhishMethod contains \"URL\"\r\n| summarize Count = count() by PhishMethod = tostring(PhishMethod), Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct PhishMethod | extend d = 1) on d | project Timestamp, PhishMethod\r\n| join kind=leftouter (agg) on Timestamp, PhishMethod\r\n| project Timestamp, PhishMethod, Count = coalesce(Count, 0)\r\n| sort by PhishMethod asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 8 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b983b361-6c2e-47d5-b2c5-edd9caa6a55d" + }, + { + "type": 1, + "content": { + "json": "### Trend (per {Granularity}) of QR Code-Based Threat Detections
\r\n\r\n**Displays counts (per {Granularity}) of inbound emails containing QR codes flagged for Phish, Malware, or Spam via URL-based detection methods. Helps track QR code abuse patterns over time.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3d8b75e1-6e1d-44eb-b1fc-78d3db7feb71" + }, + { + "type": 1, + "content": { + "json": "### URL Scan activity by Location (per {Granularity})
\r\n\r\n**Displays counts (per {Granularity}) of URLs scanned from various locations within emails (e.g., body, attachments, QR codes). Helps identify where malicious URLs are most commonly embedded.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b275b28c-e441-4c19-9055-256d5d45c69c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where EmailDirection == \"Inbound\" \r\n| where DetectionMethods has \"Url\"\r\n| join EmailUrlInfo on NetworkMessageId\r\n| where UrlLocation == \"QRCode\"\r\n| summarize [\"Phish QR Detection\"]=countif(parse_json(DetectionMethods).Phish has \"URL\"), [\"Malware QR Detection\"]=countif(parse_json(DetectionMethods).Malware has \"URL\"), [\"Spam QR Detection\"]=countif(parse_json(DetectionMethods).Spam has \"URL\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, [\"Phish QR Detection\"]=coalesce([\"Phish QR Detection\"],0), [\"Malware QR Detection\"]=coalesce([\"Malware QR Detection\"],0), [\"Spam QR Detection\"]=coalesce([\"Spam QR Detection\"],0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "graphSettings": { + "type": 0 + }, + "chartSettings": { + "xAxis": "Timestamp", + "xSettings": { + "dateFormatSettings": { + "formatName": "shortDatePattern", + "showUtcTime": false + } + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 6", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6c2a7724-d3c2-42b2-b8da-7acbcd0666c6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises where URL's have been scanned identified from various locations in emails\r\nEmailUrlInfo\r\n| summarize count() by UrlLocation", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 5", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5640dbd5-4085-4f2a-8fb9-e4112233e99e" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "5" + }, + "name": "group - 9-URL detections", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "b572d79b-17a0-48ac-9a43-4f20324cf998" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Insights on URL Click-Based Threat Detections\r\n
\r\n\r\nThis section consolidates key visuals that track and explain URL click based threat detections in emails as identified by Microsoft Defender for Office 365 focusing on per-{Granularity} trend of blocked URL clicks, time-of-click URL scans by workload, malicious clicks allowed, top clicks on malicious URLs, and more.

**Recommended action:** For blocked-click spikes, verify Safe Links is set to not allow click-through; investigate workloads with high click-through activity." + }, + "name": "text - 13 - Copy - Copy", + "id": "6d37617e-911e-4ce6-a10d-4749486738ea" + }, + { + "type": 1, + "content": { + "json": "### Trend (per {Granularity}) of Blocked URL Click Events
\r\n\r\n**Shows the count (per {Granularity}) of blocked URL click attempts and click attempts on URLs with detections, grouped by threat types (e.g., Phish, Malware, Spam). Helps track user interaction with malicious links over time across various threat types.**" + }, + "name": "text - 13 - Copy - Copy - Copy", + "id": "9e477950-bedc-4cc0-9863-df07d124806c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// Generates a time-series analysis for blocked URL click events from the 'UrlClickEvents' table\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(UrlClickEvents\r\n| where isnotempty(ActionType)\r\n| where ActionType has_any(\"ClickBlocked\")\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, BlockedClicks = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "BlockedClicks", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "query - 4", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "366e80d9-f6ed-43af-91e5-3d04cdcf692d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of click attempts on URL's with detections split by the different threat types identified\r\nUrlClickEvents\r\n| where isnotempty(ThreatTypes)\r\n| summarize count() by ThreatTypes", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "query - 4", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a356eac3-62c2-4fc9-a4d9-3b05b13848df" + }, + { + "type": 1, + "content": { + "json": "### Trend (per {Granularity}) of URL Click Actions by Type
\r\n\r\n**Displays counts (per {Granularity}) of URL click events categorised by action type: Blocked, Allowed, Pending Verdict, Error Page, and Clicked Through. Helps identify risky user behaviour and policy gaps.**" + }, + "customWidth": "66", + "name": "text - 13 - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a91fe7a6-f507-48f7-bbcc-61dc4f998ba6" + }, + { + "type": 1, + "content": { + "json": "### URL Clicks by Workload
\r\n\r\n**Displays counts (per {Granularity}) of URL click events grouped by Workload (e.g., Outlook, Teams, Copilot, Office Apps: Word, Excel, PowerPoint) Helps identify which applications are most frequently used for URL interactions and potential risk exposure.**" + }, + "customWidth": "33", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "ce05fa08-6e68-4c02-a0bf-2be6cdfae935" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises different URL click event types by action (e.g., blocked, allowed, pending verdict, error pages, and clicked through), summarizing the data daily\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(UrlClickEvents\r\n| where isnotempty(ActionType)\r\n| summarize ClickBlocked=countif(ActionType has_any(\"ClickBlocked\")), ClickAllowed=countif(ActionType has_any(\"ClickAllowed\")), PendingVerdict=countif(ActionType has_any(\"UrlScanInProgress\")), ErrorPage=countif(ActionType has_any(\"UrlErrorPage\")), ClickedThrough=countif(IsClickedThrough == true) by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ClickBlocked=coalesce(ClickBlocked,0), ClickAllowed=coalesce(ClickAllowed,0), PendingVerdict=coalesce(PendingVerdict,0), ErrorPage=coalesce(ErrorPage,0), ClickedThrough=coalesce(ClickedThrough,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "query - 1", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a12b4c78-7d18-4adc-86e0-54395d6a996a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises where URL clicks scanned by the Workload the click happened from\r\nUrlClickEvents\r\n| summarize count() by Workload", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "query - 5 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3237cd55-1d5c-41a9-a8f2-1d46c61a709e" + }, + { + "type": 1, + "content": { + "json": "### Blocked URL Clicks by Workload (per {Granularity})
\r\n\r\n**Displays counts (per {Granularity}) of blocked URL click attempts grouped by Workload (Email, Teams, Office, Microsoft 365 Copilot). Helps identify which platforms are most exposed to malicious link interactions and where user awareness or policy enforcement should be strengthened.**" + }, + "customWidth": "66", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1f209a83-3d50-4bb8-9a79-a365a50a4142" + }, + { + "type": 1, + "content": { + "json": "### Click-Through Activity on Detected URLs by Workload
\r\n\r\n**Displays counts of click‑through actions on URLs already identified with detections, grouped by Workload where the click happened. Helps identify clients/platforms where users are most likely to proceed to risky URLs and prioritise awareness training or policy tuning for those workloads**" + }, + "customWidth": "33", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "33592db8-0ff5-4d8e-bd8f-0201b81a4584" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises blocked URL click event types by Workload (e.g., Email, Teams, Office, Microsoft 365 Copilot), summarizing the data daily\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(UrlClickEvents\r\n| where ActionType ==\"ClickBlocked\"\r\n| summarize Teams=countif(Workload==\"Teams\"), Office=countif(Workload==\"Office\"), Email=countif(Workload==\"Email\"), Copilot=countif(Workload==\"Copilot\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, Teams=coalesce(Teams,0), Office=coalesce(Office,0), Email=coalesce(Email,0), Copilot=coalesce(Copilot,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "query - 3", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "80241767-0f69-4e2e-9889-3bf1f48e4f02" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of click-through activities on URL's with detections split by the source client\r\nUrlClickEvents \r\n| where IsClickedThrough !=\"0\"\r\n| where isnotempty(ThreatTypes) \r\n| summarize count() by Workload", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "query - 2", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "fde29b46-2896-4bfc-bb61-09436696d738" + }, + { + "type": 1, + "content": { + "json": "### Top clicks on Malicious URLs
\r\n\r\n**Displays the top 20 URLs associated with detections that registered the highest number of clicks. Includes ThreatTypes, ActionType, and Workload to provide context on the nature of the threat and where user interaction occurred.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "22bda63a-626c-47de-9a76-ad665ef87862" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows the top 20 URL's that have a detection associated with the most ammount of clicks registered \r\nUrlClickEvents\r\n| where ThreatTypes !=\"\"\r\n| summarize count() by Url, ThreatTypes, ActionType, Workload\r\n| top 20 by count_\r\n| project ['URL']=Url, ['Threat Types']=ThreatTypes, ['Action Type']=ActionType, Workload, ['Click Count']=count_", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Click Count", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 10 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a044fd4e-7be6-4a11-974c-b54e417c2a81" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "5" + }, + "name": "group - 31-URL clicks", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "75e543f6-08c0-42ed-9869-ecd61b721d34" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Top Risky Users Clicking on URLs with Threats\r\n
\r\n\r\nThis section consolidates key visuals that track and identify users who have clicked on malicious URLs detected by Microsoft Defender for Office 365.

**Recommended action:** Enroll these users in security awareness training and verify Safe Links policy coverage for their mailboxes." + }, + "name": "text - 13 - Copy - Copy - Copy", + "id": "19487811-a94b-4537-877e-61ac7e287c21" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Users Clicking on URLs with Malware Threat
\r\n\r\n**Displays the top 10 user accounts with the highest number of click attempts on URLs flagged as Malware. Helps identify individuals at greater risk and prioritise targeted security awareness training.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "78e10621-0e98-44c4-8399-810c19f138c2" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top 10 users with click attempts on URL's with malware detections\r\nUrlClickEvents\r\n| summarize TotalClickCount=count(),MalwareClickCount = countif(ThreatTypes has \"Malware\") by AccountUpn\r\n| extend Bad_Click_Percentage = todouble(round(MalwareClickCount / todouble(TotalClickCount) *100, 2))\r\n| where MalwareClickCount !=0\r\n| sort by MalwareClickCount desc\r\n| top 15 by MalwareClickCount\r\n| project ['User']=AccountUpn, ['Malware Clicks']=MalwareClickCount, ['Total Clicks']=TotalClickCount, ['Bad Click %']=Bad_Click_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Malware Clicks", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "25ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Clicks", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Click %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "25ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "MalwareEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "TotalEmailCount", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad_Traffic_Percentage_Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 18 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a7ae8a75-ca7f-49be-8cad-d1451a3bd396" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Users Clicking on URLs with Phish Threat
\r\n\r\n**Displays the top 10 user accounts with the highest number of click attempts on URLs flagged as Phish. Helps identify individuals at greater risk and prioritise targeted security awareness training.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "90d9a0c3-970a-4998-be62-3b3b84bb0f37" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top 10 users with click attempts on URL's with Phish detections\r\nUrlClickEvents\r\n| summarize TotalClickCount=count(),PhishClickCount = countif(ThreatTypes has \"Phish\") by AccountUpn\r\n| extend Bad_Click_Percentage = todouble(round(PhishClickCount / todouble(TotalClickCount) *100, 2))\r\n| where PhishClickCount !=0\r\n| sort by PhishClickCount desc\r\n| top 15 by PhishClickCount\r\n| project ['User']=AccountUpn, ['Phish Clicks']=PhishClickCount, ['Total Clicks']=TotalClickCount, ['Bad Click %']=Bad_Click_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Phish Clicks", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "25ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Clicks", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Click %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "25ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "MalwareClickCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "MalwareEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "TotalEmailCount", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad_Traffic_Percentage_Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 18 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d46877d9-03af-463a-b406-bb4c601dffeb" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Users Clicking on URLs with Spam Threat
\r\n\r\n**Displays the top 10 user accounts with the highest number of click attempts on URLs flagged as Spam. Helps identify individuals at greater risk and prioritise targeted security awareness training.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "dc66e020-0932-4346-8e20-6a2dc78de7a9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top 10 users with click attempts on URL's with Spam detections\r\nUrlClickEvents\r\n| summarize TotalClickCount=count(),SpamClickCount = countif(ThreatTypes has \"Spam\") by AccountUpn\r\n| extend Bad_Click_Percentage = todouble(round(SpamClickCount / todouble(TotalClickCount) *100, 2))\r\n| where SpamClickCount !=0\r\n| sort by SpamClickCount desc\r\n| top 15 by SpamClickCount\r\n| project ['User']=AccountUpn, ['Spam Clicks']=SpamClickCount, ['Total Clicks']=TotalClickCount, ['Bad Click %']=Bad_Click_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spam Clicks", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "25ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Clicks", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Click %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "25ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "PhishClickCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "MalwareClickCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "MalwareEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "TotalEmailCount", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad_Traffic_Percentage_Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 18 - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "734ee45e-4dff-4ca1-b17d-02389086b17b" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "5" + }, + "name": "group - 32-Top clickers", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "ee6c3413-28be-49a1-a89d-bf5fce7acfa4" + }, + { + "type": 1, + "content": { + "json": "# Microsoft Teams Collaboration Protection\r\n\r\n---\r\nAs email defenses mature, attackers are shifting into **Microsoft Teams**, where messages bypass secure email gateways and carry the implicit trust of a colleague chat. Microsoft Threat Intelligence reports Teams-based phishing and voice phishing (vishing) rising steadily through 2026, most often as **IT help desk or technical-support impersonation** from external or newly-created tenants, used to steer users toward remote-access tools and credential theft.\r\n\r\nThis tab shows **Microsoft Defender for Office 365** protection for Microsoft Teams: threat detections and impersonation, suspicious external senders, malicious URLs and clicks, malicious files, post-delivery ZAP removals, and user and admin submissions across chats and channels.\r\n\r\n**Recommended action:** Treat unsolicited external help desk or IT support contact as suspicious. Restrict inbound chat from unmanaged and consumer tenants, allowlist trusted external domains, remove or restrict remote-support tools such as Quick Assist where they are not required, and enforce phishing-resistant MFA for all users (Conditional Access with authentication strength), prioritizing privileged and administrator accounts first.\r\n\r\n[

Disrupting threats targeting Microsoft Teams

](https://www.microsoft.com/en-us/security/blog/2025/10/07/disrupting-threats-targeting-microsoft-teams/)[

Cross-tenant helpdesk impersonation to data exfiltration: a human-operated intrusion playbook

](https://www.microsoft.com/en-us/security/blog/2026/04/18/crosstenant-helpdesk-impersonation-data-exfiltration-human-operated-intrusion-playbook/)[

Help on the line: how a Microsoft Teams support call led to compromise

](https://www.microsoft.com/en-us/security/blog/2026/03/16/help-on-the-line-how-a-microsoft-teams-support-call-led-to-compromise/)[

Email threat landscape: Q2 2026 trends and insights

](https://www.microsoft.com/en-us/security/blog/2026/07/23/email-threat-landscape-q2-2026-trends-and-insights/)" + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "text - teams description", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5c0f0100-0a11-4b22-9c33-000000000100" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Headline Microsoft Teams protection metrics for the selected period, with per-interval sparklines. Messages are de-duplicated to the latest record per Teams message.\r\nlet gran = {Granularity};\r\nlet msgs = materialize(MessageEvents | summarize arg_max(Timestamp, *) by TeamsMessageId);\r\nlet zap = materialize(MessagePostDeliveryEvents);\r\nunion\r\n(msgs | summarize Count = count() | extend Details = \"Teams Messages Scanned\", Ord = 1, Trend = toscalar(msgs | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where isnotempty(ThreatTypes) | summarize Count = count() | extend Details = \"Messages with Threats\", Ord = 2, Trend = toscalar(msgs | where isnotempty(ThreatTypes) | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where ThreatTypes has \"Phish\" | summarize Count = count() | extend Details = \"Phish Detections\", Ord = 3, Trend = toscalar(msgs | where ThreatTypes has \"Phish\" | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where ThreatTypes has \"Malware\" | summarize Count = count() | extend Details = \"Malware Detections\", Ord = 4, Trend = toscalar(msgs | where ThreatTypes has \"Malware\" | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where ThreatTypes has \"Spam\" | summarize Count = count() | extend Details = \"Spam Detections\", Ord = 5, Trend = toscalar(msgs | where ThreatTypes has \"Spam\" | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where SafetyTip == \"URLMessageWarning\" | summarize Count = count() | extend Details = \"Messages with URL Warning\", Ord = 6, Trend = toscalar(msgs | where SafetyTip == \"URLMessageWarning\" | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(zap | summarize Count = count() | extend Details = \"Post-Delivery ZAP Actions\", Ord = 7, Trend = toscalar(zap | make-series S = count() default = 0 on Timestamp step gran | project S))\r\n| sort by Ord asc\r\n| project Details, Count, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21 + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams kpi tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b2c476ca-4141-43b4-9d4e-98470aa432fc", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + } + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Microsoft Teams - Collaboration Protection Overview\r\n
\r\n\r\nMicrosoft Defender for Office 365 extends its protection to **Microsoft Teams**, detecting malicious messages, URLs, and files shared through chats and channels. This tab summarizes Teams message detections, link-safety warnings, post-delivery ZAP, file scanning, and user/admin submissions.

*Scope note: the Teams message tables surface metadata for external-conversation messages plus internal messages that contain URLs, so counts reflect that scope rather than the full volume of Teams messages.*" + }, + "name": "teams overview banner", + "id": "2f71360f-1673-480f-8361-5afc83aee67d" + }, + { + "type": 1, + "content": { + "json": "### Teams threat detections over time
\r\n\r\n**Volume (per selected interval) of Microsoft Teams messages detected with a threat by Microsoft Defender for Office 365. Spikes may indicate a targeted Teams-based campaign.**" + }, + "customWidth": "100", + "name": "teams trend header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "0ac71d4e-8ecb-4d17-9fd3-10754007ec07" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the number of Microsoft Teams messages detected with a threat over time, de-duplicated to the latest record per message and summarized per selected interval.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(MessageEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(MessageEvents | summarize max(Timestamp));\r\nlet agg = materialize(MessageEvents | where isnotempty(ThreatTypes) | summarize arg_max(Timestamp, *) by TeamsMessageId | summarize ThreatDetections = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ThreatDetections = coalesce(ThreatDetections, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "xAxis": "Timestamp", + "seriesLabelSettings": [ + { + "seriesName": "ThreatDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams detection trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "937f3bc6-21f5-4f4c-ab72-78f08f32c5bd" + }, + { + "type": 1, + "content": { + "json": "### Threat type breakdown
\r\n\r\n**Split of Microsoft Teams threat detections across Phish, Malware, and Spam.**" + }, + "customWidth": "50", + "name": "teams threat pie header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "645a39ae-843a-47db-8016-6082ef37744d" + }, + { + "type": 1, + "content": { + "json": "### Thread exposure
\r\n\r\n**De-duplicated Microsoft Teams messages split by whether the conversation includes external participants.**" + }, + "customWidth": "50", + "name": "teams thread header", + "id": "a1a48f9a-8593-4ab5-8824-5998c643e844" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query breaks down Microsoft Teams threat detections by threat type for the selected period, de-duplicated to the latest record per message. A message flagged for more than one threat type is counted under each, so the split can exceed the distinct message count.\r\nlet msgs = MessageEvents | where isnotempty(ThreatTypes) | summarize arg_max(Timestamp, *) by TeamsMessageId;\r\nunion\r\n(msgs | where ThreatTypes has \"Phish\" | summarize Count = count() | extend ThreatType = \"Phish\"),\r\n(msgs | where ThreatTypes has \"Malware\" | summarize Count = count() | extend ThreatType = \"Malware\"),\r\n(msgs | where ThreatTypes has \"Spam\" | summarize Count = count() | extend ThreatType = \"Spam\")\r\n| project ThreatType, Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams threat type pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "029b4ecc-cd95-4385-a251-8ab194add8f4" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows de-duplicated Microsoft Teams messages split by whether the thread includes external participants.\r\nMessageEvents\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| extend Thread = iif(IsExternalThread == true, \"External Thread\", \"Internal Thread\")\r\n| summarize Count = count() by Thread", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams thread pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1581f447-9b3e-4857-84b8-e78b5df65ac5" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Overview", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "283f36b2-5c54-4afe-9a87-33d4796bd5b7" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Teams Calls and Vishing (Voice Phishing)\r\n
\r\n\r\n**Voice phishing (vishing) over Microsoft Teams is the fastest-growing collaboration threat of 2026. Attackers impersonate IT help desk or support and call users directly, often after a chat lure, to talk them into granting remote access or entering credentials. Because a target must be online to answer, malicious calls cluster in working hours. This section surfaces Teams call activity, when calls happen, and callers using support or brand-impersonation identities.**

*Interim data source: Teams call activity is currently read from Microsoft Defender for Cloud Apps call telemetry (CloudAppEvents). The existing V4 logic retains this source while the dedicated CallActivityEvents implementation is evaluated separately.*

**Recommended action:** Treat unsolicited help desk or support calls as suspicious. Confirm any request through a known internal channel, and never grant remote access such as Quick Assist on the strength of an inbound Teams call. Restrict inbound calls and chat from unmanaged and consumer tenants." + }, + "customWidth": "100", + "name": "teams calls banner", + "id": "9815bdc9-9e10-4e84-9164-783092b4ccb0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Teams call and vishing headline metrics for the selected period, with per-interval sparklines. Interim source: Defender for Cloud Apps call telemetry (CloudAppEvents / CallParticipantDetail).\r\nlet gran = {Granularity};\r\nlet calls = materialize(CloudAppEvents | where ActionType == \"CallParticipantDetail\" | extend R = parse_json(RawEventData) | extend CallId = tostring(R.CallId), UId = tolower(tostring(R.UserId)));\r\nlet susp = calls | extend Local = tostring(split(UId, \"@\")[0]), Dom = tostring(split(UId, \"@\")[1]) | where Local matches regex @\"(?i)help ?desk|helpdesk|it ?support|service ?desk|sys ?admin|administrator|security|microsoft|google|apple|amazon|paypal|support|update|verif|account|password|mfa|maintenance\" or Dom endswith \".onmicrosoft.com\";\r\nlet reported = CloudAppEvents | where ActionType == \"CallReported\";\r\nunion\r\n(calls | summarize Count = dcount(CallId) | extend Details = \"Teams Calls\", Ord = 1, Trend = toscalar(calls | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(susp | summarize Count = dcount(UId) | extend Details = \"Impersonation-style Callers\", Ord = 2, Trend = toscalar(susp | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(reported | summarize Count = count() | extend Details = \"Reported Suspicious Calls\", Ord = 3, Trend = toscalar(reported | make-series S = count() default = 0 on Timestamp step gran | project S))\r\n| sort by Ord asc\r\n| project Details, Count, Trend", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21 + }, + "showBorder": true, + "size": "auto" + }, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams calls kpi", + "id": "be8946d9-1eae-405c-b8df-cee2242cb44d" + }, + { + "type": 1, + "content": { + "json": "### Teams call activity over time
\r\n**Distinct Microsoft Teams calls per selected interval. A sudden rise, or calls outside normal working hours, can indicate a vishing campaign in progress.**" + }, + "customWidth": "100", + "name": "teams calls trend header", + "id": "1b49c98f-e5d9-457c-b058-a195e89eac0e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Distinct Teams calls per interval (interim source: CloudAppEvents / CallParticipantDetail).\r\nCloudAppEvents\r\n| where ActionType == \"CallParticipantDetail\"\r\n| extend R = parse_json(RawEventData)\r\n| extend CallId = tostring(R.CallId)\r\n| summarize ['Teams Calls'] = dcount(CallId) by Timestamp = bin(Timestamp, {Granularity})\r\n| sort by Timestamp asc", + "size": 0, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "xAxis": "Timestamp", + "seriesLabelSettings": [ + { + "seriesName": "Teams Calls", + "color": "blueDark" + } + ] + }, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams calls trend", + "id": "7538b3ca-b96d-421a-9cdc-69b8aef4b185" + }, + { + "type": 1, + "content": { + "json": "### When calls happen (hour of day, UTC)
\r\n**Microsoft Teams calls by the hour of day they started (UTC), listed 00:00 through 23:00. The bar length is the number of calls that started in that hour across the selected period. Vishing calls cluster in working hours because the target must be online to answer, with the heaviest malicious-call activity between 14:00 and 20:00 UTC, Monday to Friday, according to Microsoft Threat Intelligence. Use this to baseline normal call timing and spot unusual off-hours spikes.**" + }, + "customWidth": "100", + "name": "teams calls hour header", + "id": "6bc095e9-fe0d-4f6f-81bd-f3374d758229" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Teams calls by start hour of day (UTC), all 24 hours 00:00..23:00 in order (interim source: CloudAppEvents / CallParticipantDetail).\r\nlet data = CloudAppEvents\r\n| where ActionType == \"CallParticipantDetail\"\r\n| extend R = parse_json(RawEventData)\r\n| extend JoinTime = todatetime(R.JoinTime), CallId = tostring(R.CallId)\r\n| where isnotempty(JoinTime) and isnotempty(CallId)\r\n| summarize CallStart = min(JoinTime) by CallId\r\n| extend HourUTC = hourofday(CallStart)\r\n| summarize Calls = count() by HourUTC;\r\nrange HourUTC from 0 to 23 step 1\r\n| join kind=leftouter (data) on HourUTC\r\n| extend Calls = coalesce(Calls, 0)\r\n| extend HourLabel = strcat(iif(HourUTC < 10, strcat(\"0\", tostring(HourUTC)), tostring(HourUTC)), \":00\")\r\n| order by HourUTC asc\r\n| project ['Hour of Day (UTC)'] = HourLabel, ['Teams Calls'] = Calls", + "size": 0, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Teams Calls", + "formatter": 3, + "formatOptions": { + "palette": "blueDark", + "customColumnWidthSetting": "360px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams calls hour", + "id": "c36a9909-5570-4fe7-8efc-1b9b4745713a" + }, + { + "type": 1, + "content": { + "json": "### Suspicious callers (support and helpdesk impersonation)
\r\n**Teams call participants whose display name or address looks like IT support, help desk, or a well-known brand (for example \"Microsoft IT support\", \"Help Desk\", \"Office 365 Support\"), or who dial in from a throwaway `.onmicrosoft.com` tenant. Origin shows whether the caller is external, an external throwaway tenant, or inside your own tenant. External and throwaway-tenant callers are the primary vishing risk; own-tenant matches are frequently a legitimate internal help desk and should be confirmed rather than assumed malicious.**

**Recommended action:** Prioritise External and `.onmicrosoft` callers, confirm none are legitimate, and warn the users they called. Genuine IT support does not cold-call staff over Teams to request remote access." + }, + "customWidth": "100", + "name": "teams calls susp header", + "id": "aa420b5f-efd2-4da5-ab41-192031f62ed1" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Suspicious Teams callers by impersonation-style DISPLAY NAME or address (Attendees[].DisplayName / UPN), with Origin from the org's own accepted (EmailEvents inbound) domains - no tenant-id anchor. Interim source: CloudAppEvents / CallParticipantDetail.\r\nlet suspRegex = @\"(?i)help ?desk|helpdesk|it ?support|service ?desk|sys ?admin|administrator|security|microsoft|google|apple|amazon|paypal|support|update|verif|account|password|mfa|maintenance\";\r\nlet ownDomains = toscalar(EmailEvents | where EmailDirection == \"Inbound\" | extend RD = tolower(tostring(split(RecipientEmailAddress, \"@\")[1])) | where isnotempty(RD) | summarize make_set(RD, 200));\r\nlet calls = CloudAppEvents\r\n| where ActionType == \"CallParticipantDetail\"\r\n| extend R = parse_json(RawEventData)\r\n| extend CallId = tostring(R.CallId), JoinTime = todatetime(R.JoinTime), Attendees = R.Attendees\r\n| where isnotempty(CallId);\r\nlet callAtt = calls | summarize Attendees = take_any(Attendees), JoinTime = min(JoinTime) by CallId;\r\ncallAtt\r\n| mv-expand Att = Attendees\r\n| extend Caller = tolower(tostring(Att.UPN)), CallerName = tostring(Att.DisplayName)\r\n| extend CallerDom = tostring(split(Caller, \"@\")[1])\r\n| where isnotempty(Caller)\r\n| extend SuspName = CallerName matches regex suspRegex or Caller matches regex suspRegex\r\n| where SuspName or CallerDom endswith \".onmicrosoft.com\"\r\n| extend Origin = case(CallerDom endswith \".onmicrosoft.com\", \"External (.onmicrosoft throwaway)\", set_has_element(ownDomains, CallerDom), \"Own tenant\", \"External\")\r\n| summarize CallsPlaced = dcount(CallId), FirstSeen = min(JoinTime), LastSeen = max(JoinTime) by CallerName, Caller, Origin\r\n| extend OriginRank = case(Origin == \"External (.onmicrosoft throwaway)\", 0, Origin == \"External\", 1, 2)\r\n| sort by OriginRank asc, CallsPlaced desc\r\n| take 10\r\n| project ['Caller Display Name'] = CallerName, ['Caller Address'] = Caller, ['Origin'] = Origin, ['Calls Placed'] = CallsPlaced, ['First Seen'] = FirstSeen, ['Last Seen'] = LastSeen", + "size": 0, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Calls Placed", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams calls susp table", + "id": "d1c4df7b-db07-4c4c-bc71-dfd8623cd704" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Calls and Vishing", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "1d133411-9b5c-4ede-8502-68b3b02262e4" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Teams Impersonation & Identity Deception\r\n
\r\n\r\nMicrosoft Defender for Office 365 flags Teams messages where a sender impersonates a brand, a specific person, or a trusted domain. Impersonation is the entry point for most Teams social-engineering: attackers pose as IT, executives, or Microsoft to build trust before delivering a malicious link or request. These visuals expose who is being impersonated, who is being targeted, and the infrastructure (display names, look-alike domains, and URLs) behind the campaigns so you can hunt IOCs and coach at-risk users.

**Recommended action:** Treat the impersonated display names and look-alike domains below as IOCs to hunt, and prioritize the Microsoft Defender alert *Microsoft Teams chat initiated by a suspicious external user*. Teach users that a Teams display name is not proof of identity: verify the real sender domain, and confirm any help desk, executive, or Microsoft support request through a known internal channel before acting." + }, + "name": "teams imp banner", + "id": "7ff04ff3-9f2d-4a49-8383-2b542d78fe9b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nunion\r\n(imp | summarize Count=count() | extend Details=\"Impersonation Detections\", Ord=1),\r\n(imp | summarize Count=dcount(FakeSenderAddress) | extend Details=\"Distinct Fake Senders\", Ord=2),\r\n(imp | summarize Count=dcount(TargetUser) | extend Details=\"Targeted Users\", Ord=3),\r\n(imp | summarize Count=dcount(ImpersonationType) | extend Details=\"Impersonation Types\", Ord=4)\r\n| sort by Ord asc | project Count, Details", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e37f94d5-9bcc-432e-aa66-25831603c228" + }, + { + "type": 1, + "content": { + "json": "### Impersonation over time, by type
\r\n\r\n**Trend of Brand, User, and Domain impersonation detections. A spike in a single type often marks the start of a targeted campaign.**" + }, + "customWidth": "100", + "name": "teams imp trend header", + "id": "09907f5b-5c20-4a7e-86d3-c89153c4df98" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp | summarize Count=count() by ImpersonationType, Timestamp=bin(Timestamp, {Granularity}) | sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp trend", + "id": "757204b1-e900-4217-a2ff-2224a033fdcc" + }, + { + "type": 1, + "content": { + "json": "### Suspicious external senders (impersonation and throwaway tenants)
\r\n**External Microsoft Teams senders flagged as likely impersonation: throwaway `.onmicrosoft.com` tenants and/or help desk, IT support, security, admin, or account/update-themed display names. Attackers rotate through many such identities (for example numbered `ithelpdesk@...` addresses) from newly-created or consumer tenants to pose as internal support, frequently before the Defender impersonation detector assigns a verdict. This heuristic complements that detector.**

**Recommended action:** Review high threat-rate senders, block the sending domains, and remind users that genuine IT support does not cold-contact them from an external tenant; verify any such request through a known internal channel." + }, + "customWidth": "100", + "name": "teams susp senders header", + "id": "5df4af86-49e9-4fc7-b6ad-76d3ef3f7da6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//External Teams senders flagged as likely impersonation: throwaway .onmicrosoft.com tenants and/or help desk / IT / admin / update-themed display names, ranked by messages carrying a threat.\r\nMessageEvents\r\n| where IsExternalThread == true\r\n| extend SenderDomain = tolower(tostring(split(SenderEmailAddress, \"@\")[1]))\r\n| extend IsOnMicrosoft = SenderDomain endswith \".onmicrosoft.com\"\r\n| extend SuspName = SenderDisplayName matches regex @\"(?i)help ?desk|helpdesk|it ?support|service ?desk|it team|administrator|sys ?admin|security|microsoft|maintenance|support|update|verif|account|password|mfa\"\r\n| where IsOnMicrosoft or SuspName\r\n| summarize TeamsMessages = count(), ThreatMessages = countif(isnotempty(ThreatTypes)), FirstSeen = min(Timestamp), LastSeen = max(Timestamp) by SenderDisplayName, SenderEmailAddress, SenderDomain, IsOnMicrosoft, SuspName\r\n| extend WhyFlagged = case(IsOnMicrosoft and SuspName, \"Throwaway .onmicrosoft tenant + helpdesk-style name\", IsOnMicrosoft, \"Throwaway .onmicrosoft tenant\", \"Helpdesk / IT-style display name\")\r\n| extend ThreatPct = round(todouble(ThreatMessages) * 100 / TeamsMessages, 1)\r\n| project ['Sender Display Name']=SenderDisplayName, ['Sender Address']=SenderEmailAddress, ['Why Flagged']=WhyFlagged, ['Teams Messages']=TeamsMessages, ['Threat Messages']=ThreatMessages, ['Threat %']=ThreatPct, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen\r\n| sort by ['Threat Messages'] desc, ['Teams Messages'] desc\r\n| take 10", + "size": 0, + "title": "", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Teams Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Threat %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 100 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams susp senders table", + "id": "dd1d79d8-f591-4aae-bd44-6ad23a3e0ae4" + }, + { + "type": 1, + "content": { + "json": "### Who is being targeted
\r\n\r\n**Internal users receiving the most impersonation attempts. Concentrated targeting of a few users is a strong signal of a deliberate campaign - prioritize these users for security awareness training.**" + }, + "customWidth": "100", + "name": "teams imp targets header", + "id": "43112ad1-ebc9-42fb-9ebd-0dbaa862ed45" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp | summarize Detections=count(), ['Distinct Fake Senders']=dcount(FakeSenderAddress), Types=make_set(ImpersonationType,3), ['Last Seen']=max(Timestamp) by ['Targeted User']=TargetUser | top 10 by Detections", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp targets", + "id": "cc4b3f98-bfcb-4741-9abb-9ff099eb946f" + }, + { + "type": 1, + "content": { + "json": "### Impersonating senders
\r\n\r\n**The identities behind the impersonation, grouped by fake display name, sender domain, and type. Attackers rotate through many sending addresses under a single display name - Distinct Sender Addresses exposes that rotation, and a high count is itself a strong bulk-campaign signal. Use First/Last Seen to scope the campaign window.**" + }, + "customWidth": "100", + "name": "teams imp senders header", + "id": "99859796-7b69-42e7-a27a-541e0ba86cb2" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the identities behind Teams impersonation, grouped by the fake display name, sender domain, and impersonation type. Attackers rotate through many sending addresses under one display name, so Distinct Sender Addresses reveals bulk campaigns that per-address ranking would hide.\r\nlet imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp\r\n| summarize Detections=count(), SenderAddresses=dcount(FakeSenderAddress), Targets=dcount(TargetUser), FirstSeen=min(Timestamp), LastSeen=max(Timestamp) by FakeDisplayName, FakeSenderDomain, ImpersonationType\r\n| top 10 by Detections\r\n| project ['Fake Display Name']=FakeDisplayName, ['Sender Domain']=FakeSenderDomain, ['Impersonation Type']=ImpersonationType, ['Distinct Sender Addresses']=SenderAddresses, Detections, ['Targeted Users']=Targets, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Distinct Sender Addresses", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp senders", + "id": "209439a0-5be3-4e41-abe9-695552730dc8" + }, + { + "type": 1, + "content": { + "json": "### Display names abused
\r\n\r\n**The identities attackers pretend to be (for example \"IT HelpDesk\", \"Microsoft Support\"). These are the trust anchors of the social-engineering lure.**" + }, + "customWidth": "100", + "name": "teams imp names header", + "id": "e645578b-7a52-4d38-9d83-f5c500bbfe1a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp | summarize Detections=count(), ['Targeted Users']=dcount(TargetUser), ['Distinct Senders']=dcount(FakeSenderAddress) by ['Fake Display Name']=FakeDisplayName | top 10 by Detections", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Distinct Senders", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp names", + "id": "d723d72b-4e7c-431b-ae7b-980879c8bd75" + }, + { + "type": 1, + "content": { + "json": "### Look-alike sender domains
\r\n\r\n**Sending domains used for impersonation - watch for typosquats (for example rnicrosoft.com for m→rn). Add confirmed domains to your Tenant Allow/Block List.**" + }, + "customWidth": "100", + "name": "teams imp domains header", + "id": "98040a5a-bbd5-4c95-b976-5630ce48b282" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp | summarize Detections=count(), ['Targeted Users']=dcount(TargetUser), ['Display Names Used']=dcount(FakeDisplayName) by ['Sender Domain']=FakeSenderDomain | top 10 by Detections", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Display Names Used", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp domains", + "id": "94b9fa45-c889-46a7-8b80-92e5d280ad3b" + }, + { + "type": 1, + "content": { + "json": "### URL IOCs from impersonation messages
\r\n\r\n**URL domains that appeared in messages sent by impersonating senders. Threat actors deliberately mix legitimate domains (for example microsoft.com or google.com) with their malicious ones to make the lure look trustworthy, so treat this as a review list - not a blocklist. Investigate the unfamiliar or look-alike domains and block only those you confirm malicious; never block a well-known legitimate domain from this list.**" + }, + "customWidth": "100", + "name": "teams imp ioc header", + "id": "d5f4886c-7c7e-4c6f-94ca-569cabda5ede" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists URL domains that appeared in messages sent by impersonating senders, with a breakdown of how many carried Malware, Phish, or Spam verdicts. Threat actors mix legitimate and malicious domains in a single lure, so review the unfamiliar or look-alike domains and block only confirmed-malicious ones.\r\nlet imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ChatThreadId = tostring(RD.ChatThreadId);\r\nlet impThreads = imp | distinct ChatThreadId;\r\nlet impMsgs = MessageEvents\r\n | where ThreadId in (impThreads)\r\n | summarize arg_max(Timestamp, *) by TeamsMessageId\r\n | project TeamsMessageId, ThreatTypes;\r\nMessageUrlInfo\r\n| where isnotempty(UrlDomain)\r\n| join kind=inner (impMsgs) on TeamsMessageId\r\n| summarize ['URL Count']=count(), Messages=dcount(TeamsMessageId), Malware=countif(ThreatTypes has \"Malware\"), Phish=countif(ThreatTypes has \"Phish\"), Spam=countif(ThreatTypes has \"Spam\") by ['URL Domain']=UrlDomain\r\n| top 10 by ['URL Count']", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "URL Count", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Malware", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Phish", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Spam", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp ioc", + "id": "958ac65c-d56d-4a80-ba83-2ab33e8b1e2e" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Impersonation", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "c49582db-6318-423f-b806-91cbeb625ea2" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Malicious URLs and Link Warnings in Teams\r\n
\r\n\r\nTracks URLs shared through Microsoft Teams, messages that triggered a Microsoft Defender for Office 365 URL safety-tip warning, and the outcome of Teams URL clicks (allowed versus blocked) captured in UrlClickEvents.

**Recommended action:** Enable Safe Links for Microsoft Teams so links are checked at click time, and prioritize *User clicked a malicious link in Teams chat* alerts for investigation. Treat a blocked click as an attempted compromise: check whether the user went on to share credentials or run a file, and reset credentials where warranted." + }, + "name": "teams url banner", + "id": "e3ec4d65-8d1f-4303-bd8f-eb1ae521da41" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query surfaces Microsoft Teams URL-sharing and link-warning metrics for the selected period. URL-warning messages carry the Microsoft Defender for Office 365 URL safety tip.\r\nlet msgs = materialize(MessageEvents | summarize arg_max(Timestamp, *) by TeamsMessageId);\r\nunion\r\n(msgs | where SafetyTip == \"URLMessageWarning\" | summarize Count = count() | extend Details = \"Messages with URL Warning\", Ord = 1),\r\n(MessageUrlInfo | summarize Count = count() | extend Details = \"URLs Shared in Messages\", Ord = 2),\r\n(MessageUrlInfo | summarize Count = dcount(TeamsMessageId) | extend Details = \"Messages Containing URLs\", Ord = 3),\r\n(MessageUrlInfo | summarize Count = dcount(UrlDomain) | extend Details = \"Distinct URL Domains\", Ord = 4)\r\n| sort by Ord asc\r\n| project Count, Details", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams url tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b71382c7-c0f7-4f9d-9d21-e0a8bf9504ff" + }, + { + "type": 1, + "content": { + "json": "### Teams URL click outcomes over time
\r\n\r\n**Allowed versus blocked Microsoft Teams URL clicks (per selected interval) from UrlClickEvents where the click happened in the Teams workload.**" + }, + "customWidth": "66", + "name": "teams click trend header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "30818e0d-6c4b-4868-896a-ac48cb3cef86" + }, + { + "type": 1, + "content": { + "json": "### Click outcomes
\r\n\r\n**Distribution of Microsoft Teams URL click actions by type.**" + }, + "customWidth": "33", + "name": "teams click pie header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "5a882138-2241-4527-80b8-9983c5807050" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Microsoft Teams URL click outcomes over time (allowed vs blocked) using the UrlClickEvents workload filter, summarizing the data per selected interval.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(UrlClickEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(UrlClickEvents | summarize max(Timestamp));\r\nlet agg = materialize(UrlClickEvents\r\n| where Workload == \"Teams\"\r\n| summarize ClickAllowed = countif(ActionType has \"ClickAllowed\"), ClickBlocked = countif(ActionType has \"ClickBlocked\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ClickAllowed = coalesce(ClickAllowed, 0), ClickBlocked = coalesce(ClickBlocked, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "teams click trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "7a2f5559-1e3e-412a-addf-c3bf6be98502" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows Microsoft Teams URL click outcomes by action type for the selected period.\r\nUrlClickEvents\r\n| where Workload == \"Teams\"\r\n| where isnotempty(ActionType)\r\n| summarize Count = count() by ActionType", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "teams click pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "889c6bb3-438b-4575-84f2-084c1b5fd1f4" + }, + { + "type": 1, + "content": { + "json": "### Top domains shared in Teams messages
\r\n\r\n**The 10 most-shared URL domains in Microsoft Teams messages, with the number of messages each appeared in.**" + }, + "customWidth": "100", + "name": "teams top domains header", + "id": "dcb8c87c-087e-4d69-b7b7-0329296293ff" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 URL domains shared in Microsoft Teams messages by volume for the selected period.\r\nMessageUrlInfo\r\n| where isnotempty(UrlDomain)\r\n| summarize UrlCount = count(), Messages = dcount(TeamsMessageId) by UrlDomain\r\n| top 10 by UrlCount\r\n| project ['URL Domain']=UrlDomain, ['URLs Shared']=UrlCount, ['Messages']=Messages", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "URLs Shared", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams top domains table", + "id": "7561adb0-1fbe-41ce-a924-a27bcd4c5c12" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Malicious URLs", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "6d47c309-be9e-4b21-940e-7c7b282e5dc2" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Targeted Users & Risky Senders\r\n
\r\n\r\nIdentifies who is most targeted in Microsoft Teams, and profiles the external senders and domains behind risky messages - URL safety-tip warnings, first-contact senders, threat-carrying domains, and low-reputation link infrastructure - so you can spot anomalous senders before they succeed.

**Recommended action:** Prioritize the most-targeted users for phishing-resistant MFA and awareness coaching, and treat first-contact external senders and low-reputation domains as IOCs. Restrict inbound chat from unmanaged and consumer tenants, and allowlist only trusted external domains so unsolicited outsiders cannot start a conversation." + }, + "name": "teams risky banner", + "id": "0aa13d73-2e13-487c-a7c4-d90464a554d4" + }, + { + "type": 1, + "content": { + "json": "### Top targeted users (messages with threats)
\r\n\r\n**The 10 users receiving the most Microsoft Teams messages that contained a threat, expanded from each message recipient list.**" + }, + "customWidth": "100", + "name": "teams targeted header", + "id": "827dc0f6-2bb2-49b9-acf8-d7b400238594" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 users receiving Microsoft Teams messages that contained a threat, expanded from the message recipient list, with each user's total Teams messages received and the share that carried a threat. Messages are de-duplicated to the latest record per message.\r\nlet expanded = MessageEvents\r\n | summarize arg_max(Timestamp, *) by TeamsMessageId\r\n | mv-expand rd = parse_json(RecipientDetails)\r\n | extend Recipient = tostring(rd.RecipientSmtpAddress)\r\n | where isnotempty(Recipient);\r\nlet totals = expanded | summarize TotalMessages = count() by Recipient;\r\nexpanded\r\n| where isnotempty(ThreatTypes)\r\n| summarize ThreatMessages = count() by Recipient\r\n| join kind=leftouter (totals) on Recipient\r\n| extend ThreatPct = round(100.0 * ThreatMessages / TotalMessages, 1)\r\n| top 10 by ThreatMessages\r\n| project ['Recipient']=Recipient, ['Threat Messages']=ThreatMessages, ['Total Messages']=TotalMessages, ['Threat %']=ThreatPct", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams targeted users table", + "id": "79481d1b-617e-46df-b555-9f7240932dd0" + }, + { + "type": 1, + "content": { + "json": "### Top senders of URL-warning messages
\r\n\r\n**Senders whose Microsoft Teams messages most often triggered a URL safety-tip warning.**" + }, + "customWidth": "50", + "name": "teams warn senders header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "ef71d7dd-4442-4992-977d-d550aad4533c" + }, + { + "type": 1, + "content": { + "json": "### Top domains in URL-warning messages
\r\n\r\n**URL domains most frequently present in Microsoft Teams messages that triggered a URL safety-tip warning.**" + }, + "customWidth": "50", + "name": "teams warn domains header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "6f41a4ba-f832-4947-ad27-cd6b8015bd63" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 senders whose Microsoft Teams messages triggered a URL safety-tip warning for the selected period, with each sender's total Teams messages and the share that carried a warning. Messages are de-duplicated to the latest record per message.\r\nlet dedup = MessageEvents | summarize arg_max(Timestamp, *) by TeamsMessageId;\r\nlet totals = dedup | summarize TotalMessages = count() by SenderEmailAddress;\r\ndedup\r\n| where SafetyTip == \"URLMessageWarning\"\r\n| summarize WarningMessages = count() by SenderEmailAddress\r\n| join kind=leftouter (totals) on SenderEmailAddress\r\n| extend WarningPct = round(100.0 * WarningMessages / TotalMessages, 1)\r\n| top 10 by WarningMessages\r\n| project ['Sender']=SenderEmailAddress, ['Warning Messages']=WarningMessages, ['Total Messages']=TotalMessages, ['Warning %']=WarningPct", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Warning Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams warn senders table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3fa023af-79e3-407f-ac20-b0aa6e3ba511" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 URL domains appearing in Microsoft Teams messages that triggered a URL safety-tip warning, with the domain's total message appearances and the share that carried a warning.\r\nlet warned = MessageEvents | where SafetyTip == \"URLMessageWarning\" | distinct TeamsMessageId;\r\nlet totals = MessageUrlInfo | where isnotempty(UrlDomain) | summarize TotalMessages = dcount(TeamsMessageId) by UrlDomain;\r\nMessageUrlInfo\r\n| where TeamsMessageId in (warned)\r\n| summarize WarningMessages = dcount(TeamsMessageId) by UrlDomain\r\n| join kind=leftouter (totals) on UrlDomain\r\n| extend WarningPct = round(100.0 * WarningMessages / TotalMessages, 1)\r\n| top 10 by WarningMessages\r\n| project ['URL Domain']=UrlDomain, ['Warning Messages']=WarningMessages, ['Total Messages']=TotalMessages, ['Warning %']=WarningPct", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Warning Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams warn domains table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "68811015-1383-48ad-86da-4f8f9d39e4c4" + }, + { + "type": 1, + "content": { + "json": "### First-contact external senders
\r\n\r\n**External Microsoft Teams senders ordered by when they were first seen in the period (most recent first). Note: some flows tag internal-domain senders as external - to hide your own tenant domains, edit the query and uncomment the ExcludeDomains filter.**" + }, + "customWidth": "100", + "name": "teams fc senders header", + "id": "0f131ff3-d6b2-4187-b86c-ca3493594b54" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists external Microsoft Teams senders by the date they were first seen in the selected period, surfacing recent first-contact senders. Messages are de-duplicated to the latest record per message. In tenants with longer history this highlights genuinely new senders.\r\n// TIP: IsExternalThread may still surface senders from your own accepted domains. To hide them,\r\n// uncomment the ExcludeDomains line below (add your tenant domains) and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"contoso.com\"]);\r\nMessageEvents\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| where IsExternalThread == true\r\n//| where tostring(split(SenderEmailAddress, \"@\")[1]) !in~ (ExcludeDomains)\r\n| summarize FirstSeen = min(Timestamp), Messages = count(), ThreatMessages = countif(isnotempty(ThreatTypes)) by SenderEmailAddress\r\n| top 10 by FirstSeen desc\r\n| project ['Sender']=SenderEmailAddress, ['First Seen']=FirstSeen, ['Messages']=Messages, ['Threat Messages']=ThreatMessages", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true, + "sortBy": [ + { + "itemKey": "Threat Messages", + "sortOrder": 2 + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams fc senders table", + "id": "4e10a78d-8858-4dbb-9db0-e7b7d7e7636c" + }, + { + "type": 1, + "content": { + "json": "### External sender-domain risk
\r\n\r\n**External sending domains ranked by threat volume, with the mix of conversation types (1:1 chat, group chat, channel), threat breakdown, threat rate, count of messages carrying low-reputation URLs (domains on commonly-abused TLDs such as .xyz, .top, .click, .shop, .zip), and first/last-seen. A domain that is new in the period, skews toward 1:1 chats, or shows a high threat rate is anomalous and warrants review. Note: to exclude your own tenant domains, edit the query and uncomment the ExcludeDomains filter.**" + }, + "customWidth": "100", + "name": "teams anomaly header", + "id": "a91295db-8192-4828-93c5-408436e4b0e1" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query ranks external sender domains in Microsoft Teams by threat volume for the selected period, split by conversation type (1:1 chat, group chat, channel), with threat-type breakdown, threat rate, and a count of messages carrying low-reputation URL TLDs. Messages are de-duplicated to the latest record per message. New, 1:1-skewed, or high-threat-rate domains are the anomalies to review.\r\n// TIP: IsExternalThread may still surface your own accepted domains. To hide them, uncomment the\r\n// ExcludeDomains line below (add your tenant domains) and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"contoso.com\"]);\r\nlet suspTlds = dynamic([\"top\",\"xyz\",\"click\",\"link\",\"shop\",\"online\",\"site\",\"live\",\"icu\",\"cyou\",\"sbs\",\"rest\",\"quest\",\"cfd\",\"bond\",\"buzz\",\"fun\",\"space\",\"monster\",\"work\",\"tk\",\"ml\",\"ga\",\"cf\",\"gq\",\"dev\",\"app\",\"zip\",\"mov\",\"info\",\"win\",\"loan\",\"men\",\"stream\",\"country\"]);\r\nlet suspUrlMsgs = MessageUrlInfo\r\n | where isnotempty(UrlDomain)\r\n | extend Tld = tostring(split(UrlDomain, \".\")[-1])\r\n | where Tld in (suspTlds)\r\n | distinct TeamsMessageId;\r\nMessageEvents\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| where IsExternalThread == true\r\n| extend SenderDomain = tostring(split(SenderEmailAddress, \"@\")[1])\r\n| where isnotempty(SenderDomain)\r\n//| where SenderDomain !in~ (ExcludeDomains)\r\n| extend ConvType = case(isnotempty(GroupId), \"Channel\", array_length(todynamic(RecipientDetails)) > 1, \"Group chat\", \"1:1 chat\")\r\n| extend HasSuspUrl = TeamsMessageId in (suspUrlMsgs)\r\n| summarize Messages=count(), Senders=dcount(SenderEmailAddress), OneToOne=countif(ConvType==\"1:1 chat\"), GroupChat=countif(ConvType==\"Group chat\"), ChannelMsgs=countif(ConvType==\"Channel\"), ThreatMessages=countif(isnotempty(ThreatTypes)), Malware=countif(ThreatTypes has \"Malware\"), Phish=countif(ThreatTypes has \"Phish\"), Spam=countif(ThreatTypes has \"Spam\"), SuspUrlMsgs=countif(HasSuspUrl), FirstSeen=min(Timestamp), LastSeen=max(Timestamp) by SenderDomain\r\n| where ThreatMessages > 0\r\n| extend ThreatRatePct = round(100.0 * ThreatMessages / Messages, 1)\r\n| top 10 by ThreatMessages desc\r\n| project ['Sender Domain']=SenderDomain, Messages, Senders, ['1:1']=OneToOne, ['Group']=GroupChat, ['Channel']=ChannelMsgs, ['Threat Msgs']=ThreatMessages, Malware, Phish, Spam, ['Threat Rate %']=ThreatRatePct, ['Low-Rep URL Msgs']=SuspUrlMsgs, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams anomaly table", + "id": "bcd6746d-8298-495d-9d6c-2fadc6cba569" + }, + { + "type": 1, + "content": { + "json": "### Suspicious new senders (no threat verdict yet)
\r\n\r\n**External sending domains with no threat verdict yet, but that are either sending low-reputation-URL messages or showing unusual volume. These slip past threat filters - watch for new domains skewing toward 1:1 chats, an early social-engineering signal. Note: to exclude your own tenant domains, edit the query and uncomment the ExcludeDomains filter.**" + }, + "customWidth": "100", + "name": "teams newdom header", + "id": "9e3844f4-befc-4b76-a8cd-ca53fdf51d41" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query surfaces external sender domains in Microsoft Teams that have NO threat verdict yet but are sending messages with low-reputation URL TLDs or unusual volume, split by conversation type. These are early-warning senders that have not tripped a detection. Messages are de-duplicated to the latest record per message.\r\n// TIP: IsExternalThread may still surface your own accepted domains. To hide them, uncomment the\r\n// ExcludeDomains line below (add your tenant domains) and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"contoso.com\"]);\r\nlet suspTlds = dynamic([\"top\",\"xyz\",\"click\",\"link\",\"shop\",\"online\",\"site\",\"live\",\"icu\",\"cyou\",\"sbs\",\"rest\",\"quest\",\"cfd\",\"bond\",\"buzz\",\"fun\",\"space\",\"monster\",\"work\",\"tk\",\"ml\",\"ga\",\"cf\",\"gq\",\"dev\",\"app\",\"zip\",\"mov\",\"info\",\"win\",\"loan\",\"men\",\"stream\",\"country\"]);\r\nlet suspUrlMsgs = MessageUrlInfo\r\n | where isnotempty(UrlDomain)\r\n | extend Tld = tostring(split(UrlDomain, \".\")[-1])\r\n | where Tld in (suspTlds)\r\n | distinct TeamsMessageId;\r\nMessageEvents\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| where IsExternalThread == true\r\n| extend SenderDomain = tostring(split(SenderEmailAddress, \"@\")[1])\r\n| where isnotempty(SenderDomain)\r\n//| where SenderDomain !in~ (ExcludeDomains)\r\n| extend ConvType = case(isnotempty(GroupId), \"Channel\", array_length(todynamic(RecipientDetails)) > 1, \"Group chat\", \"1:1 chat\")\r\n| extend HasSuspUrl = TeamsMessageId in (suspUrlMsgs)\r\n| summarize Messages=count(), Senders=dcount(SenderEmailAddress), OneToOne=countif(ConvType==\"1:1 chat\"), GroupChat=countif(ConvType==\"Group chat\"), ChannelMsgs=countif(ConvType==\"Channel\"), ThreatMessages=countif(isnotempty(ThreatTypes)), SuspUrlMsgs=countif(HasSuspUrl), FirstSeen=min(Timestamp), LastSeen=max(Timestamp) by SenderDomain\r\n| where ThreatMessages == 0\r\n| where SuspUrlMsgs > 0 or Messages >= 5\r\n| order by SuspUrlMsgs desc, Messages desc\r\n| take 10\r\n| project ['Sender Domain']=SenderDomain, Messages, Senders, ['1:1']=OneToOne, ['Group']=GroupChat, ['Channel']=ChannelMsgs, ['Low-Rep URL Msgs']=SuspUrlMsgs, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams newdom table", + "id": "8036a5b7-b5b3-4af4-912f-bb092bb01b89" + }, + { + "type": 1, + "content": { + "json": "### Low-reputation link domains in Teams (IOC radar)
\r\n\r\n**URL domains shared in Teams that use TLDs commonly abused for phishing and malware (for example .xyz, .top, .click, .zip, .shop). Ranked by message reach, with first/last-seen. Review these domains as potential indicators - .zip and .mov are especially deceptive because links read like file names.**" + }, + "customWidth": "100", + "name": "teams tld header", + "id": "d48921f4-233c-4e0f-a97b-83e1bcaed399" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists URL domains shared in Microsoft Teams that use low-reputation TLDs commonly abused for phishing and malware, ranked by the number of Teams messages they appeared in, with first- and last-seen. Treat high-reach or newly-seen domains as candidate indicators of compromise.\r\nlet suspTlds = dynamic([\"top\",\"xyz\",\"click\",\"link\",\"shop\",\"online\",\"site\",\"live\",\"icu\",\"cyou\",\"sbs\",\"rest\",\"quest\",\"cfd\",\"bond\",\"buzz\",\"fun\",\"space\",\"monster\",\"work\",\"tk\",\"ml\",\"ga\",\"cf\",\"gq\",\"dev\",\"app\",\"zip\",\"mov\",\"info\",\"win\",\"loan\",\"men\",\"stream\",\"country\"]);\r\nMessageUrlInfo\r\n| where isnotempty(UrlDomain)\r\n| extend Tld = tostring(split(UrlDomain, \".\")[-1])\r\n| where Tld in (suspTlds)\r\n| summarize Messages=dcount(TeamsMessageId), FirstSeen=min(Timestamp), LastSeen=max(Timestamp) by ['URL Domain']=UrlDomain, ['TLD']=Tld\r\n| top 10 by Messages desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams tld table", + "id": "30d5588e-010c-474a-9c53-74b73dcc9676" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Targeted Users & Risky Senders", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "6fef737b-cb4e-4a51-9ced-bf11754a6b33" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Teams File Protection\r\n
\r\n\r\nMicrosoft Defender for Office 365 scans files shared in Microsoft Teams. These visuals show files scanned versus malware detected, and list the malicious files found.

**Recommended action:** Investigate each malicious file below and confirm it was quarantined and removed from the SharePoint or OneDrive location backing the chat. Enable Safe Attachments for SharePoint, OneDrive, and Microsoft Teams, and use attack surface reduction rules to block executable content delivered through collaboration." + }, + "name": "teams file banner", + "id": "2f01c905-dd65-4a13-9f67-c70402b2c175" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query summarizes Microsoft Teams file protection by Microsoft Defender for Office 365 - files scanned, files with malware detected, and files scanned with no detection - for the selected period.\r\nlet base = FileMaliciousContentInfo | where Workload == \"MicrosoftTeams\";\r\nunion\r\n(base | summarize Count = count() | extend Details = \"Teams Files Scanned\", Ord = 1),\r\n(base | where isnotempty(ThreatTypes) | summarize Count = count() | extend Details = \"Files with Malware Detected\", Ord = 2),\r\n(base | where isempty(ThreatTypes) | summarize Count = count() | extend Details = \"Files Scanned - No Detection\", Ord = 3)\r\n| sort by Ord asc\r\n| project Count, Details", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams file tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "9f555c51-1680-47ef-94d4-b1f8cf9dce3b" + }, + { + "type": 1, + "content": { + "json": "### Malicious files shared in Teams
\r\n\r\n**Files shared in Microsoft Teams that were detected with malware, with owner and file details.**" + }, + "customWidth": "100", + "name": "teams file table header", + "id": "4cd3274e-0c61-4722-83b7-1fccf8a94a57" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists Microsoft Teams files detected with malware by Microsoft Defender for Office 365 for the selected period.\r\nFileMaliciousContentInfo\r\n| where Workload == \"MicrosoftTeams\"\r\n| where isnotempty(ThreatTypes)\r\n| top 10 by Timestamp desc\r\n| project ['Time']=Timestamp, ['File Name']=FileName, ['Threat Type']=tostring(ThreatTypes), ['Threat Names']=ThreatNames, ['File Location']=FolderPath, ['File Owner']=FileOwnerUpn, SHA256", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams file table", + "id": "135e0e7d-7110-40ee-a377-1a5992b2ef9d" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams File Protection", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "8ecc1bae-4a06-4b1c-8952-59fb434b7cbc" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Post-Delivery ZAP Insights (Teams)\r\n
\r\n\r\nZero-hour auto purge (ZAP) removes malicious Microsoft Teams messages after delivery. These visuals summarize ZAP volume, type, result, and the senders whose messages were most often removed.

**Recommended action:** Confirm zero-hour auto purge is enabled for Microsoft Teams so newly-weaponized messages are pulled after delivery. Investigate senders with repeated ZAP removals as likely compromised or malicious accounts and block or restrict them. A rising ZAP trend can signal an active campaign that slipped past delivery-time filtering." + }, + "name": "teams zap banner", + "id": "136cfb4e-d2a5-4db0-9771-6b6380011ba0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query summarizes Microsoft Teams post-delivery ZAP (zero-hour auto purge) activity by Microsoft Defender for Office 365 for the selected period.\r\nlet zap = materialize(MessagePostDeliveryEvents);\r\nunion\r\n(zap | summarize Count = count() | extend Details = \"Total ZAP Actions\", Ord = 1),\r\n(zap | where ActionType == \"Malware ZAP\" | summarize Count = count() | extend Details = \"Malware ZAP\", Ord = 2),\r\n(zap | where ActionType == \"Phish ZAP\" | summarize Count = count() | extend Details = \"Phish ZAP\", Ord = 3),\r\n(zap | where ActionResult == \"Success\" | summarize Count = count() | extend Details = \"Successful Actions\", Ord = 4),\r\n(zap | where ActionResult == \"Failed\" | summarize Count = count() | extend Details = \"Failed Actions\", Ord = 5),\r\n(zap | where Action == \"Moved to quarantine\" | summarize Count = count() | extend Details = \"Moved to Quarantine\", Ord = 6)\r\n| sort by Ord asc\r\n| project Count, Details", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams zap tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "06980411-5e6b-4aa4-a746-351cd2b12dae" + }, + { + "type": 1, + "content": { + "json": "### ZAP actions over time
\r\n\r\n**Microsoft Teams post-delivery ZAP actions (per selected interval) split by Malware ZAP and Phish ZAP.**" + }, + "customWidth": "66", + "name": "teams zap trend header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "7fc1cfcd-3a9f-45b1-9f39-3820fce23c03" + }, + { + "type": 1, + "content": { + "json": "### ZAP by action type
\r\n\r\n**Distribution of Microsoft Teams post-delivery ZAP actions by type.**" + }, + "customWidth": "33", + "name": "teams zap pie header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "9bc0d0a3-876a-49d7-9046-31764511ca38" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Microsoft Teams post-delivery ZAP actions over time by ZAP type, summarizing the data per selected interval.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(MessagePostDeliveryEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(MessagePostDeliveryEvents | summarize max(Timestamp));\r\nlet agg = materialize(MessagePostDeliveryEvents\r\n| summarize MalwareZAP = countif(ActionType == \"Malware ZAP\"), PhishZAP = countif(ActionType == \"Phish ZAP\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, MalwareZAP = coalesce(MalwareZAP, 0), PhishZAP = coalesce(PhishZAP, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "teams zap trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "c78a509e-324f-4a8c-b2e7-bce3e0d20667" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows Microsoft Teams post-delivery ZAP actions by type for the selected period.\r\nMessagePostDeliveryEvents\r\n| summarize Count = count() by ActionType", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "teams zap pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "cfc94695-fb02-4b6c-a223-f79f7b947379" + }, + { + "type": 1, + "content": { + "json": "### Top senders whose messages were removed by ZAP
\r\n\r\n**Senders whose Microsoft Teams messages were most often removed by post-delivery ZAP.**" + }, + "customWidth": "100", + "name": "teams zap senders header", + "id": "f8677ffe-007a-41ca-81de-1ae5dd19d06a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 senders whose Microsoft Teams messages were removed by post-delivery ZAP for the selected period.\r\nMessagePostDeliveryEvents\r\n| where isnotempty(SenderEmailAddress)\r\n| summarize ZapActions = count(), MalwareZAP = countif(ActionType == \"Malware ZAP\"), PhishZAP = countif(ActionType == \"Phish ZAP\") by SenderEmailAddress\r\n| top 10 by ZapActions\r\n| project ['Sender']=SenderEmailAddress, ['ZAP Actions']=ZapActions, ['Malware ZAP']=MalwareZAP, ['Phish ZAP']=PhishZAP", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "ZAP Actions", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams zap senders table", + "id": "50c9a883-6442-40dc-b84f-57adfbb46a38" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams ZAP", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "f5cc2425-e5ae-4520-9a97-2e4c2c447dcd" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Teams Message and Call Submissions\r\n
\r\n\r\nMicrosoft Teams messages and calls reported by users, and messages submitted by admins, for review by Microsoft. Sourced from the submission records in CloudAppEvents.

**Recommended action:** Encourage users to report suspicious Teams messages and calls so Microsoft can tune protection, and triage admin submissions promptly. A cluster of reports naming the same sender, display name, or call identity is an early signal of a targeted campaign: pivot those identities into the impersonation and risky-sender views above to scope it." + }, + "name": "teams sub banner", + "id": "54cbfb29-2626-4b65-8cb5-a42ff4b41e63" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query summarizes Microsoft Teams message and call submissions reported to Microsoft for the selected period, split by user and admin reports. Only completed submissions are counted (submission triage/timeout lifecycle records are excluded).\r\nlet sub = materialize(CloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType in (\"ChatMessage\", \"TeamsCall\"));\r\nunion\r\n(sub | where SubmissionContentType == \"ChatMessage\" and ActionType == \"UserSubmission\" | summarize Count = count() | extend Details = \"Messages Reported by Users\", Ord = 1),\r\n(sub | where SubmissionContentType == \"TeamsCall\" and ActionType == \"UserSubmission\" | summarize Count = count() | extend Details = \"Calls Reported by Users\", Ord = 2),\r\n(sub | where SubmissionContentType == \"ChatMessage\" and ActionType == \"AdminSubmission\" | summarize Count = count() | extend Details = \"Messages Submitted by Admins\", Ord = 3)\r\n| sort by Ord asc\r\n| project Count, Details", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams sub tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "419ed645-ebc1-4df1-b9f0-c744403ab494" + }, + { + "type": 1, + "content": { + "json": "### Submissions over time
\r\n\r\n**Microsoft Teams user and admin submissions (per selected interval).**" + }, + "customWidth": "66", + "name": "teams sub trend header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "6a795b0a-82e2-427a-8ac0-abfb5bb5e447" + }, + { + "type": 1, + "content": { + "json": "### Submission mix
\r\n\r\n**Microsoft Teams submissions split by content type (message or call) and reporter (user or admin).**" + }, + "customWidth": "33", + "name": "teams sub pie header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "1f4c55f8-7290-4b6f-b02a-e3134568b9ff" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Microsoft Teams message and call submissions over time, summarizing the data per selected interval. Only completed submissions are counted (submission triage/timeout lifecycle records are excluded).\r\nlet gran = {Granularity};\r\nlet sub = materialize(CloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType in (\"ChatMessage\", \"TeamsCall\"));\r\nlet minTime = toscalar(sub | summarize min(Timestamp));\r\nlet maxTime = toscalar(sub | summarize max(Timestamp));\r\nlet agg = materialize(sub\r\n| summarize UserReports = countif(ActionType == \"UserSubmission\"), AdminReports = countif(ActionType == \"AdminSubmission\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, UserReports = coalesce(UserReports, 0), AdminReports = coalesce(AdminReports, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "teams sub trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "7dcb03da-de96-4388-90a4-0a3f3ca98dc6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows the mix of Microsoft Teams submissions by content type and reporter for the selected period. Only completed user submissions (chat and call) and admin submissions (chat) are counted; submission triage/timeout lifecycle records are excluded.\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\"\r\n| where (SubmissionContentType == \"ChatMessage\" and ActionType == \"UserSubmission\")\r\n or (SubmissionContentType == \"TeamsCall\" and ActionType == \"UserSubmission\")\r\n or (SubmissionContentType == \"ChatMessage\" and ActionType == \"AdminSubmission\")\r\n| extend Reporter = iif(ActionType == \"AdminSubmission\", \"Admin\", \"User\")\r\n| summarize Count = count() by SubmissionType = strcat(SubmissionContentType, \" (\", Reporter, \")\")", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "teams sub pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "84a0141e-51de-4423-acb0-3c4342a49bf2" + }, + { + "type": 1, + "content": { + "json": "### False Negative (FN) User Submissions by submission State
\r\n\r\n**Microsoft Teams messages reported by users as missed detections, broken down by submission state (for example Rescaned, Graded). Tracks the processing status of user reports.**" + }, + "customWidth": "50", + "name": "teams sub state header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "1b2bdffd-69b0-41b0-bdda-b242b7faaec0" + }, + { + "type": 1, + "content": { + "json": "### False Negative (FN) User Submissions by Triage Verdict
\r\n\r\n**Microsoft Teams user submissions grouped by the verdict assigned during grading (for example Phishing, NotSpam, Spam). Shows how reported messages were graded and highlights detection gaps.**" + }, + "customWidth": "50", + "name": "teams sub verdict header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "bdb97e09-44d2-41ad-a99f-931e4a8169cc" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows Microsoft Teams user (false negative) message submissions by submission state (for example Rescaned, Graded), to track processing status.\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend SubmissionState = tostring(RD.SubmissionState)\r\n| summarize Count = count() by tostring(SubmissionState)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub state pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "139ce840-5fc2-44d1-9872-91b37a74f0e7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows Microsoft Teams user (false negative) message submissions by the triage verdict assigned during grading (for example Phishing, NotSpam, Spam).\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend TriageVerdict = tostring(parse_json(tostring(RD.GradingResult)).TriageVerdict)\r\n| where isnotempty(TriageVerdict)\r\n| summarize Count = count() by TriageVerdict", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub verdict pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "538ce4a3-a1ff-4b8d-a466-2173edbb2cd7" + }, + { + "type": 1, + "content": { + "json": "### Top 10 P2 sender domains in FN User Submissions
\r\n\r\n**The sender domains most often reported by users as missed Microsoft Teams threats. High-volume domains are candidate sources of malicious messaging.**" + }, + "customWidth": "50", + "name": "teams sub domains header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "9b8db0c7-2bf2-4077-ae20-60146001bf23" + }, + { + "type": 1, + "content": { + "json": "### Top 10 individual P2 senders in FN User Submissions
\r\n\r\n**The individual senders most often reported by users as missed Microsoft Teams threats.**" + }, + "customWidth": "50", + "name": "teams sub senders header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "ffbe90ab-129c-47fa-9dac-50cab528ad55" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 P2 (envelope) sender domains of Microsoft Teams messages reported by users as false negatives (missed detections).\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend P2SenderDomain = tostring(RD.P2SenderDomain)\r\n| where isnotempty(P2SenderDomain)\r\n| summarize Submissions = count() by ['P2 Sender Domain']=P2SenderDomain\r\n| top 10 by Submissions", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub domains table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b18192fb-26a8-4bd1-9b07-7aeab496eae3" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 individual P2 (envelope) senders of Microsoft Teams messages reported by users as false negatives (missed detections).\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend P2Sender = tostring(RD.P2Sender)\r\n| where isnotempty(P2Sender)\r\n| summarize Submissions = count() by ['P2 Sender']=P2Sender\r\n| top 10 by Submissions", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub senders table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "7ead0a01-2b56-4225-b625-554b09350013" + }, + { + "type": 1, + "content": { + "json": "### Top 10 users performing the most FN User Submissions
\r\n\r\n**The users who report the most Microsoft Teams messages as missed detections - useful for recognising engaged reporters and spotting over-reporting.**" + }, + "customWidth": "50", + "name": "teams sub topusers header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "fb893cdd-d6d3-431a-a1d2-87652571a10d" + }, + { + "type": 1, + "content": { + "json": "### Top 10 admins performing the most FN Admin Submissions
\r\n\r\n**The admins who submit the most Microsoft Teams messages as missed detections.**" + }, + "customWidth": "50", + "name": "teams sub topadmins header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "14fca69b-e152-4a5d-bd2c-020c34c2226a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 users who reported the most Microsoft Teams messages as false negatives (missed detections), with each submitter's email (from the submission record) to disambiguate users with similar names.\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend Submitter = tostring(RD.SubmitterDisplayName), SubmitterEmail = tostring(RD.UserId)\r\n| where isnotempty(Submitter) and SubmitterEmail has \"@\"\r\n| summarize Submissions = count() by ['Submitter']=Submitter, ['Email']=SubmitterEmail\r\n| top 10 by Submissions", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub topusers table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a171a35b-35b0-46ce-a916-052a54101126" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 admins who submitted the most Microsoft Teams messages as false negatives (missed detections). The admin's own email is not present in the submission record (that would require the Identity table), so the Submitter ID (object GUID) is shown to disambiguate admins with similar names.\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"AdminSubmission\"\r\n| extend Submitter = tostring(RD.SubmitterDisplayName), SubmitterId = tostring(RD.SubmitterId)\r\n| where isnotempty(Submitter)\r\n| summarize Submissions = count() by ['Admin']=Submitter, ['Submitter ID']=SubmitterId\r\n| top 10 by Submissions", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub topadmins table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8bf37c2b-067a-4341-a192-2aa45699c3f7" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Submissions", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "eeea53a4-69d9-426e-bf9f-1789cd73bfed" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Recent Threat Detail\r\n
\r\n\r\nThe most recent Microsoft Teams phishing and malware messages, de-duplicated to the latest record per message, for investigation." + }, + "name": "teams detail banner", + "id": "4bdd917c-721f-450b-b455-45cbd5f59cc5" + }, + { + "type": 1, + "content": { + "json": "### Last 10 Teams phishing messages
\r\n\r\n**Most recent Microsoft Teams messages detected as phishing, with sender, delivery action, safety tip, team/group, and subject. TeamsMessageId is included to pivot to Advanced Hunting.**" + }, + "customWidth": "100", + "name": "teams detail phish header", + "id": "9bcf96c1-a958-4515-b171-10ec2f3ba660" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the 10 most recent Microsoft Teams messages detected as phishing by Microsoft Defender for Office 365, de-duplicated to the latest record per message. TeamsMessageId is included so analysts can pivot to Advanced Hunting.\r\nMessageEvents\r\n| where ThreatTypes has \"Phish\"\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| top 10 by Timestamp desc\r\n| project ['Time']=Timestamp, ['Sender']=SenderEmailAddress, ['Threat Types']=ThreatTypes, ['Delivery Action']=DeliveryAction, ['Safety Tip']=SafetyTip, ['Team / Group']=GroupName, ['External Thread']=IsExternalThread, ['Subject']=MessageSubject, TeamsMessageId", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams detail phish table", + "id": "3675d08f-1165-4f47-a633-e432cf96e3d5" + }, + { + "type": 1, + "content": { + "json": "### Last 10 Teams malware messages
\r\n\r\n**Most recent Microsoft Teams messages detected as malware, with sender, delivery action, safety tip, team/group, and subject. TeamsMessageId is included to pivot to Advanced Hunting.**" + }, + "customWidth": "100", + "name": "teams detail mal header", + "id": "6b9d66d2-8d89-47b0-a72a-5ee8623082dc" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the 10 most recent Microsoft Teams messages detected as malware by Microsoft Defender for Office 365, de-duplicated to the latest record per message. TeamsMessageId is included so analysts can pivot to Advanced Hunting.\r\nMessageEvents\r\n| where ThreatTypes has \"Malware\"\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| top 10 by Timestamp desc\r\n| project ['Time']=Timestamp, ['Sender']=SenderEmailAddress, ['Threat Types']=ThreatTypes, ['Delivery Action']=DeliveryAction, ['Safety Tip']=SafetyTip, ['Team / Group']=GroupName, ['External Thread']=IsExternalThread, ['Subject']=MessageSubject, TeamsMessageId", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams detail mal table", + "id": "d6e76d0a-7eee-4c05-8e92-10f9622b5ab3" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Detail", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "1e9c879b-d6be-4d36-9068-b5438abf7dd2" + }, + { + "type": 1, + "content": { + "json": "# Top Attacked Users, Top Senders, and Automatic External Email Forwarding\r\n\r\n---\r\nThis tab provides insights into **Top attacked users, Top Senders** in inbound email messages and details about **automatic external email forwarding**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "6" + }, + "name": "text - 24 - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f1a60054-44b1-432e-be7a-9d7d114ff5c7" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Top Attacked Users and Top Senders Insights\r\n
\r\n\r\nThis section provides key visuals that highlight top attacked users – individuals most frequently targeted by inbound email threats as detected by Microsoft Defender for Office 365. Offers insights into top email senders and sender domains across inbound email traffic, helping identify patterns and potential risk sources.

**Recommended action:** Apply the Strict preset to the most-attacked users and review the top sender domains as possible block-list candidates." + }, + "name": "text - 13 - Copy - Copy", + "id": "ff220902-30b8-4aef-9b79-14c913a1b2d2" + }, + { + "type": 1, + "content": { + "json": "### Top Attacked Users
\r\n\r\n**Displays the top 10 recipient email addresses that received inbound emails flagged as Spam, Phishing, or Malware. Helps identify high-risk users for targeted security awareness and policy enforcement.**" + }, + "name": "text - 13 - Copy - Copy - Copy", + "id": "58f34b9f-824d-4fcf-b2aa-d7d380aa08d5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 users that are receiving Spam, Phishing or Malware emails\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\" and EmailDirection ==\"Inbound\"\r\n| extend MDO_detection = parse_json(DetectionMethods) \r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),MalwareEmailCount = countif(FirstDetection == \"Malware\"),PhishEmailCount = countif(FirstDetection == \"Phish\"),SpamEmailCount = countif(FirstDetection == \"Spam\") by RecipientEmailAddress\r\n| extend ThreatEmailCount=(MalwareEmailCount+PhishEmailCount+SpamEmailCount)\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(ThreatEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| top 15 by ThreatEmailCount\r\n| project ['Recipient']=RecipientEmailAddress, ['Total Emails']=TotalEmailCount, ['Threat Emails']=ThreatEmailCount, ['Malware']=MalwareEmailCount, ['Phish']=PhishEmailCount, ['Spam']=SpamEmailCount, ['Bad Traffic %']=Bad_Traffic_Percentage_Inbound", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Threat Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Malware", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spam", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + } + } + ], + "filter": true, + "sortBy": [ + { + "itemKey": "$gen_bar_Threat Emails_2", + "sortOrder": 2 + } + ] + }, + "sortBy": [ + { + "itemKey": "$gen_bar_Threat Emails_2", + "sortOrder": 2 + } + ], + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 28", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e9459e78-6b43-4ef2-9596-32169d95c610" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Senders of Inbound Emails
\r\n\r\n**Displays the top 10 sender email addresses from external sources delivering inbound emails. Helps identify high-volume external senders for monitoring and policy enforcement.**" + }, + "name": "text - 13 - Copy - Copy - Copy - Copy", + "id": "eb4590a7-57c7-4728-af62-3d798afe6f2d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 senders by inbound email sending volume\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\" and EmailDirection ==\"Inbound\"\r\n| extend MDO_detection = parse_json(DetectionMethods) \r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),MalwareEmailCount = countif(FirstDetection == \"Malware\"),PhishEmailCount = countif(FirstDetection == \"Phish\"),SpamEmailCount = countif(FirstDetection == \"Spam\") by SenderFromAddress\r\n| extend ThreatEmailCount=(MalwareEmailCount+PhishEmailCount+SpamEmailCount)\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(ThreatEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| top 15 by TotalEmailCount\r\n| project ['Sender']=SenderFromAddress, ['Total Emails']=TotalEmailCount, ['Threat Emails']=ThreatEmailCount, ['Malware']=MalwareEmailCount, ['Phish']=PhishEmailCount, ['Spam']=SpamEmailCount, ['Bad Traffic %']=Bad_Traffic_Percentage_Inbound", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Threat Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Malware", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spam", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + } + } + ], + "filter": true + }, + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 28 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e4272979-1073-4c1e-9b1b-b971bc3efc33" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains of Inbound Emails
\r\n\r\n**Displays the top 10 sender domains from external sources delivering inbound emails. Helps identify high-volume external sender domains for monitoring and policy enforcement.**" + }, + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "id": "7ab63415-17ce-47f1-a614-e5e6edbe472e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 senders by inbound email sending volume\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\" and EmailDirection ==\"Inbound\"\r\n| extend MDO_detection = parse_json(DetectionMethods) \r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),MalwareEmailCount = countif(FirstDetection == \"Malware\"),PhishEmailCount = countif(FirstDetection == \"Phish\"),SpamEmailCount = countif(FirstDetection == \"Spam\") by SenderFromDomain\r\n| extend ThreatEmailCount=(MalwareEmailCount+PhishEmailCount+SpamEmailCount)\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(ThreatEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| top 15 by TotalEmailCount\r\n| project ['Sender Domain']=SenderFromDomain, ['Total Emails']=TotalEmailCount, ['Threat Emails']=ThreatEmailCount, ['Malware']=MalwareEmailCount, ['Phish']=PhishEmailCount, ['Spam']=SpamEmailCount, ['Bad Traffic %']=Bad_Traffic_Percentage_Inbound", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Threat Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Malware", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spam", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + } + } + ], + "filter": true + }, + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 28 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b593da94-b735-4fe3-a82d-18c90156e506" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "6" + }, + "name": "group - 10-Top attacked users and top senders", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "3e41cc1a-166e-4094-bc66-7e26a918b2e9" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Automatic External Email Forwarding Insights\r\n
\r\n\r\n**Email forwarding can be useful, but can also pose a security risk due to the potential disclosure of information.**\r\n
\r\n\r\nUsers can configure [Inbox rules](https://support.microsoft.com/en-US/Outlook/mail/use-rules-to-automatically-forward-messages) in Outlook or set up [SMTP forwarding](https://support.microsoft.com/en-us/office/turn-on-automatic-forwarding-in-outlook-7f2670a1-7fff-4475-8a3c-5822d63b0c8e) to automatically forward messages to external recipients. You can control automatic external email forwarding from cloud mailboxes using [Outbound spam policies](https://learn.microsoft.com/en-us/defender-office-365/outbound-spam-policies-external-email-forwarding) in Microsoft Defender for Office 365. \r\n**Attackers might exploit this capability to compromise your organization or its partners.**

**Recommended action:** Investigate external auto-forwarding - it is a common data-exfiltration path. Consider disabling auto-forwarding via the outbound spam policy unless a business case is documented." + }, + "name": "text - 8", + "id": "b04d1590-98e3-4650-9172-33e75561e1e5" + }, + { + "type": 1, + "content": { + "json": "### Automatic Email Forwarding by Type
\r\n\r\n**Displays counts of outbound emails automatically forwarded to external addresses, grouped by forwarding type (e.g., SMTP forwarding, inbox rules). Helps identify forwarding behaviors that may pose data exfiltration risks.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "c7cb7917-eaf4-4a1e-989a-75f4b6182851" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Internal Users Forwarding Emails Externally
\r\n\r\n**Displays the top 10 internal user accounts that have automatically forwarded emails to external addresses (regardless of the forwarding type used). Helps identify potential data exfiltration risks and enforce forwarding policies.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5a5d5a8c-c195-45db-a878-e6ac908cc919" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises automatic email forwarding to external email addresses by forwarding type\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| summarize count() by ForwardingType\r\n| sort by count_ desc \r\n", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "15094d98-add2-4b50-a0df-ee91fd34c6fb" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 internal senders who are automatically forwarding emails to external email addresses\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| summarize TotalForwardedMessages = count() by ForwardingUser\r\n| sort by TotalForwardedMessages desc \r\n| top 10 by TotalForwardedMessages\r\n| project ['Forwarding User']=ForwardingUser, ['Forwarded Messages']=TotalForwardedMessages\r\n\r\n", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "TotalForwardedMessages" + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "73d66038-2ea0-449d-9aeb-a1bd4b207d7f" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Internal Users Forwarding Emails Using Mailbox Rules
\r\n\r\n**Displays the top 10 internal user accounts that have automatically forwarded outbound emails to external addresses using Mailbox Rules. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "9a7b5fc3-da23-4e95-87df-542a5e3f6320" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 internal senders who are automatically forwarding emails to external email addresses using Mailbox Rules\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| where ForwardingType ==\"MbxRule\"\r\n| summarize TotalForwardedMessages = count() by ForwardingUser\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Forwarding User']=ForwardingUser, ['Forwarded Messages']=TotalForwardedMessages", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "TotalForwardedMessages" + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 30 - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f8d7b85d-944a-493f-a143-7e18277846c9" + }, + { + "type": 1, + "content": { + "json": "### Top 10 External domains Receiving Auto-Forwarded Emails (Mailbox Rules)
\r\n\r\n**Displays the top 10 external recipient email domains that received automatically forwarded emails from internal users via Mailbox Rules. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "cda99a50-b7c4-4d95-ac61-7231080a3f5d" + }, + { + "type": 1, + "content": { + "json": "### Top 10 External Recipients Receiving Auto-Forwarded Emails (Mailbox Rules)
\r\n\r\n**Displays the top 10 external recipient email addresses that received automatically forwarded emails from internal users via Mailbox Rules. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "72b01575-c33e-457c-98db-ea755c003bf0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 external domains who are recieving automatically forwarded emails using Mailbox Rules\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser),RecipientDomain = tostring(split(RecipientEmailAddress, \"@\")[1])\r\n| where ForwardingType ==\"MbxRule\"\r\n| summarize TotalForwardedMessages = count() by RecipientDomain\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Recipient Domain']=RecipientDomain, ['Forwarded Messages']=TotalForwardedMessages", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "823dec28-48b5-4be3-8e68-04301a952a62" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 external recipients who are recieving automatically forwarded emails using Mailbox Rules\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| where ForwardingType ==\"MbxRule\"\r\n| summarize TotalForwardedMessages = count() by RecipientEmailAddress\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Recipient']=RecipientEmailAddress, ['Forwarded Messages']=TotalForwardedMessages", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "14804990-bfc9-43b7-8c8d-95c2cf32ee56" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Internal Users Forwarding Emails via SMTP Forwarding
\r\n\r\n**Displays the top 10 internal user accounts that have automatically forwarded outbound emails to external addresses using SMTP Forwarding. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "fa04b313-5756-4ff7-9ee8-ec61e6b382cc" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 internal senders who are automatically forwarding emails to external email addresses using SmtpForwarding\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| where ForwardingType ==\"SmtpForwarding\"\r\n| summarize count() by ForwardingUser\r\n| top 10 by count_ desc\r\n| project ['Forwarding User']=ForwardingUser, ['Forwarded Messages']=count_", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 30 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "bed8e717-4ea7-4f71-aaa7-b70a31f4dc88" + }, + { + "type": 1, + "content": { + "json": "### Top 10 External domains receiving Auto-Forwarded Emails (SMTP Forwarding)
\r\n\r\n**Displays the top 10 external recipient email domains that received automatically forwarded emails from internal users using SMTP Forwarding. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f76bc717-3cf8-4d8d-92fa-3f2024065f8f" + }, + { + "type": 1, + "content": { + "json": "### Top 10 External Recipients Receiving Auto-Forwarded Emails (SMTP Forwarding)
\r\n\r\n**Displays the top 10 external recipient email addresses that received automatically forwarded emails from internal users using SMTP Forwarding. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "2190c799-ab4f-4bd8-87e1-f9c5c224cca4" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 external recipients who are recieving automatically forwarded emails using SmtpForwarding\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser),RecipientDomain = tostring(split(RecipientEmailAddress, \"@\")[1])\r\n| where ForwardingType ==\"SmtpForwarding\"\r\n| summarize TotalForwardedMessages = count() by RecipientDomain\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Recipient Domain']=RecipientDomain, ['Forwarded Messages']=TotalForwardedMessages", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "c3be87b3-8ce8-40f2-ad92-0651bed71117" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 external recipients who are recieving automatically forwarded emails using SmtpForwarding\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| where ForwardingType ==\"SmtpForwarding\"\r\n| summarize TotalForwardedMessages = count() by RecipientEmailAddress\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Recipient']=RecipientEmailAddress, ['Forwarded Messages']=TotalForwardedMessages", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "fb6b0113-f5bb-46a7-994b-92ebc3c7881d" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "6" + }, + "name": "group - 34 - Automatic email forwarding", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "02c91ebb-4f92-4843-a73b-6dea7a6ac2bd" + }, + { + "type": 1, + "content": { + "json": "# Email detection action overrides\r\n\r\n---\r\n\r\nThis tab provides insights into admin or end-user configured **detection overrides** where the message was detected as a threat by Microsoft Defender for Office 365, however an admin-configured policy or end-user setting overrode the detection action.[

Learn more

](https://learn.microsoft.com/en-us/defender-office-365/step-by-step-guides/understand-overrides-in-email-entity) " + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "text - 13 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "ae594968-00b9-40b8-b5dd-052a27440afb" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Admin configured Detection Overrides (Allow)\r\n
\r\n\r\nThis section consolidates key visuals that track emails subject to administrator policies (e.g., Transport Rules, Tenant Allow/Block List) with an \"Allow\" action, overriding Microsoft Defender for Office 365 detections (excluding SecOps Mailbox overrides).

**Recommended action:** Review Allow overrides that later carried threats and remove stale or overly broad allow entries - they weaken protection." + }, + "name": "text - AdminOverridesAllowHeader", + "id": "3d70a304-c590-4156-a6d4-da147fe106ab" + }, + { + "type": 1, + "content": { + "json": "### Admin Overrides (Allow) Trend\r\n**Displays the count (per {Granularity}) of emails where an administrator policy with an \"Allow\" action overrode detections (excluding SecOps Mailbox). Helps track the frequency of admin overrides over time.**" + }, + "name": "text - AdminOverridesAllowTrend", + "id": "a4ee104a-a0a1-4725-a60f-deedcc91af70" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to an admin policy with action of allow independent of action taken, summarizing the data daily\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where isnotempty(OrgLevelPolicy) and OrgLevelPolicy!=\"SecOps Mailbox\" and OrgLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalAdminOverrides = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Admin Overrides'] = coalesce(TotalAdminOverrides, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Admin Overrides", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 3", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "79928e9e-48ed-4d08-8ff7-c21fe027550e" + }, + { + "type": 1, + "content": { + "json": "### Total Emails by Admin Override type (Allow)\r\n**Summarizes the total count of emails subject to administrator policies with an \"Allow\" action, grouped by the type of override. Helps identify which policies are most frequently allowing emails.**" + }, + "customWidth": "50", + "name": "text - AdminOverridesAllowByType", + "id": "855fce09-2000-4d16-8521-8b4eeddfae00" + }, + { + "type": 1, + "content": { + "json": "### Admin Overrides (Allow) by Override Type and Threat Type\r\n**Details the count of emails allowed by administrator policies, categorized by the override type and the detected threat type. Helps assess the risk associated with allowed emails.**" + }, + "customWidth": "50", + "name": "text - AdminOverridesAllowByTypeAndThreat", + "id": "a2613078-b427-4b23-aca0-21989b1944db" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails subject to an admin policy with action of allow, independent of action taken, summarizing the data by type of override\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelPolicy!=\"SecOps Mailbox\" and OrgLevelAction == \"Allow\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by OrgLevelPolicy", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 16", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b21a0329-8f52-45c2-81f2-6df65c134673" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to an admin policy with action of allow, independent of action taken, summarizing the data by type of override and threats type found\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelPolicy!=\"SecOps Mailbox\" and OrgLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by OrgLevelAction,OrgLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=OrgLevelAction, ['Override Policy']=OrgLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 2", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "0bf4cbe6-7c84-49d4-801c-d955762b5699" + }, + { + "type": 1, + "content": { + "json": "### SecOps Mailbox Overrides (Allow)\r\nThis section focuses on emails allowed specifically due to the SecOps Mailbox override policy, typically used for investigation and analysis.[

Learn more

](https://learn.microsoft.com/en-us/defender-office-365/advanced-delivery-policy-configure) " + }, + "name": "text - SecOpsOverridesHeader", + "id": "f582dc86-4c40-4cdd-ba0b-ec6ef8820a27" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails subject to the \r\nEmailEvents \r\n| where OrgLevelPolicy==\"SecOps Mailbox\" and OrgLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by OrgLevelPolicy", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "statSettings": { + "valueAggregation": "None", + "colorSettings": { + "type": "static", + "mode": "background", + "heatmapPalette": "greenRed", + "thresholdsGrid": [] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "tagText": "", + "valueFontStyle": "auto", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 1", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8ad2fea4-dcd0-454e-a4d4-b5275c86fd9b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails delivered to the SecOps Mailbox by threat type\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelPolicy==\"SecOps Mailbox\" and OrgLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by OrgLevelAction,OrgLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=OrgLevelAction, ['Override Policy']=OrgLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", + "size": 1, + "showAnalytics": true, + "title": " ", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 4", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "52c04df2-69b5-46e4-a000-7c6d212a132a" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "group - 15 - Admin Detection Overrides - Allow", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "9b9baf2f-fd5f-41b6-8368-b515f8de4fd4" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Admin configured Detection Overrides (Block)\r\n
\r\n\r\nThis section provides insights into email messages blocked by administrative policies (e.g. Tenant allow/block list, Antimalware policy file type block), overriding detection actions defined by Microsoft Defender for Office 365.

**Recommended action:** Confirm these blocks are still needed and consolidate them into the Tenant Allow/Block List where appropriate." + }, + "name": "text - AdminOverridesBlockHeader", + "id": "6157683b-cce7-4165-886f-0da73e25ce86" + }, + { + "type": 1, + "content": { + "json": "### Admin Overrides (Block) Trend\r\n**Displays the count (per {Granularity}) of emails where an administrator policy with a \"Block\" action overrode detections. Helps track the frequency of admin blocks over time.**" + }, + "name": "text - AdminOverridesBlockTrend", + "id": "699820b4-a984-45cc-ab2f-607c3c8569d4" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to an admin policy with action of block, summarizing the data daily\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where isnotempty(OrgLevelPolicy) and OrgLevelAction == \"Block\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalAdminOverrides = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Admin Overrides'] = coalesce(TotalAdminOverrides, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Admin Overrides", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 5", + "styleSettings": { + "margin": "10", + "padding": "10" + }, + "id": "9ef5e7fb-843e-439b-b4f3-9b0bb149e74b" + }, + { + "type": 1, + "content": { + "json": "### Total Emails by Admin Override Type (Block)\r\n**Summarizes the total count of emails subject to administrator policies with a \"Block\" action, grouped by the type of override.**" + }, + "customWidth": "50", + "name": "text - AdminOverridesBlockByType", + "id": "5694a7c0-1ee5-40b4-ae2b-263d189c4b4e" + }, + { + "type": 1, + "content": { + "json": "### Admin Overrides (Block) by Override Type and Threat Type\r\n**Details the count of emails blocked by administrator policies, categorized by the override type and the detected threat type.**" + }, + "customWidth": "50", + "name": "text - AdminOverridesBlockByTypeAndThreat", + "id": "6e309742-37c0-4ad5-9b9a-63643059bfaf" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails subject to an admin policy with action of block, summarizing the data by type of override\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelAction == \"Block\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by OrgLevelPolicy", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 6", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "eabc80ed-d0e9-43d2-ab13-a5af478f11c8" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to an admin policy with action of block, summarizing the data by type of override and threats type found\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelAction == \"Block\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by OrgLevelAction,OrgLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=OrgLevelAction, ['Override Policy']=OrgLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 7", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1661bfa6-d8fd-4387-a334-1bc027a3f6d1" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "group - 36-Admin Detection Overrides - Block", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "7d514e9a-f67f-45a6-ba1b-6492348cc18b" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
User configured Detection Overrides (Allow)\r\n
\r\n\r\nThis section consolidates key visuals that track email messages subject to user policies (e.g. [Safe Senders list defined in Outlook](https://learn.microsoft.com/en-us/defender-office-365/create-safe-sender-lists-in-office-365#use-outlook-safe-senders)) with an \"Allow\" action, overriding Microsoft Defender for Office 365 detections.

**Recommended action:** Educate users that safe-sender allows can bypass protection; review high-risk user allow entries." + }, + "name": "text - UserOverridesAllowHeader", + "id": "4d41c560-0e73-40c5-b610-33e9500e88c4" + }, + { + "type": 1, + "content": { + "json": "### User Overrides (Allow) Trend\r\n**Displays the count (per {Granularity}) of emails where a user policy with an \"Allow\" action overrode detections. Helps track the frequency of user overrides over time.**" + }, + "name": "text - UserOverridesAllowTrend", + "id": "9432efff-9f03-4d74-8781-02be8b2d07fa" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to a user type policy with action of allow, summarizing the data daily\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalUserOverrides = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['User Overrides'] = coalesce(TotalUserOverrides, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "User Overrides", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 3", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "02da1d33-e477-479d-bdd3-95ab1ad7c75c" + }, + { + "type": 1, + "content": { + "json": "### Total Emails by User Override Type (Allow)\r\n**Summarizes the total count of emails subject to user policies with an \"Allow\" action, grouped by the type of override.**" + }, + "customWidth": "50", + "name": "text - UserOverridesAllowByType", + "id": "006a2e87-b1b6-4cc3-a763-ceebaa86b340" + }, + { + "type": 1, + "content": { + "json": "### User Overrides (Allow) by Override Type and Threat Type\r\n**Details the count of emails allowed by user policies, categorized by the override type and the detected threat type. Helps assess the risk associated with user-allowed emails.**" + }, + "customWidth": "50", + "name": "text - UserOverridesAllowByTypeAndThreat", + "id": "7c34bb4b-46c0-4054-9596-3dfd010bb036" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails subject to a user type policy with action of allow, summarizing the data by type of override\r\nEmailEvents \r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Allow\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by UserLevelPolicy", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 16", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d1d9021d-e6bf-47b1-bdd2-438a212d2767" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to a user type policy with action of allow, summarizing the data by type of override and threats type found\r\nEmailEvents \r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Allow\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by UserLevelAction,UserLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=UserLevelAction, ['Override Policy']=UserLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 2", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1acd913c-c945-4a58-b04e-d008ca53ffe3" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "group - 15 - User Detection Overrides - Allow", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "c939060e-6a8b-49ff-951b-a3abddbd9fb4" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
User configured Detection Overrides (Block)\r\n
\r\n\r\nThis section provides insights into emails blocked by user-configured policies (e.g., [Blocked Senders list in Outlook](https://support.microsoft.com/en-us/office/block-or-unblock-senders-in-outlook-9bf812d4-6995-4d19-901a-76d6e26939b0)).

**Recommended action:** Use user block trends to identify unwanted senders that may warrant tenant-wide blocking." + }, + "name": "text - UserOverridesBlockHeader", + "id": "be6c6a3e-08ee-47c5-b8e7-6a1078dd17d1" + }, + { + "type": 1, + "content": { + "json": "### User Overrides (Block) Trend\r\n**Displays the count (per {Granularity}) of emails where a user policy with a \"Block\" action overrode detections. Helps track the frequency of user blocks over time.**" + }, + "name": "text - UserOverridesBlockTrend", + "id": "7cd77d54-2e2b-4d23-a6a9-4bd6bca2642a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to a user type policy with action of block, summarizing the data daily\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Block\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalUserOverrides = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['User Overrides'] = coalesce(TotalUserOverrides, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "User Overrides", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 5", + "styleSettings": { + "margin": "10", + "padding": "10" + }, + "id": "0b21b66c-001d-4b3d-b47f-f3a420ccaaf8" + }, + { + "type": 1, + "content": { + "json": "### Total Emails by User Override Type (Block)\r\n**Summarizes the total count of emails subject to user policies with a \"Block\" action, grouped by the type of override.**" + }, + "customWidth": "50", + "name": "text - UserOverridesBlockByType", + "id": "fd513501-5e9d-45d9-9d0d-cd546002b8cf" + }, + { + "type": 1, + "content": { + "json": "### User Overrides (Block) by Override Type and Threat Type\r\n**Details the count of emails blocked by user policies, categorized by the override type and the detected threat type.**" + }, + "customWidth": "50", + "name": "text - UserOverridesBlockByTypeAndThreat", + "id": "4fbfa876-47ed-4c3b-81ee-1c40b982cecd" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails subject to a user type policy with action of block, summarizing the data by type of override\r\nEmailEvents \r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Block\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by UserLevelPolicy", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 6", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d3fccaa6-80fd-419d-bb37-aedf67263419" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to a user type policy with action of block, summarizing the data by type of override and threats type found\r\nEmailEvents \r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Block\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by UserLevelAction,UserLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=UserLevelAction, ['Override Policy']=UserLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 7", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e5e74ce1-fa67-45ea-bc80-97237342e370" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "group - 37-User Detection Overrides - Block", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "0c1d327a-c2f1-4b9b-b210-53c808b53b48" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
User & Sender Override Detail (Allow)\r\n
\r\n\r\nInbound messages that Microsoft Defender for Office 365 **detected as threats but delivered anyway** because of an admin- or user-configured **Allow** override (phishing-simulation and SecOps Mailbox traffic excluded). **Total Threats** is all detected threats to that recipient / sender domain in the selected range; **Overridden Threats** and **Override %** are the portion delivered due to an Allow override, and **Override Types** names the specific overrides responsible. **User-configured** overrides come from the recipient's own mailbox junk-email settings in Outlook / Outlook on the web (the mailbox \"safelist collection\") — the **Safe Senders** and **Safe Recipients** lists and **trusted contacts** (\"Also trust email from my Contacts\"). **Admin-configured** overrides come from the **Tenant Allow/Block List, Exchange mail flow (transport) rules, the IP Allow List, or allowed sender/domain lists in anti-spam policies**. Use this to spot users or domains where overrides are letting threats through — candidates for policy review or a Tenant Allow/Block List (TABL) block.

**Recommended action:** Focus on the users and sender domains with the most allow overrides - these are the biggest protection gaps." + }, + "name": "Overrides - User Detail Header", + "id": "3b0e83f3-f340-4b95-85c5-831783e8abc2" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top recipients receiving threats that were delivered due to an admin or user override, with the share of their threats that were overridden and a breakdown of which override types caused them.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend OverrideType = case(\r\n OrgLevelAction == \"Allow\" and OrgLevelPolicy != \"\" and OrgLevelPolicy != \"SecOps Mailbox\", OrgLevelPolicy,\r\n UserLevelAction == \"Allow\", strcat(\"User: \", UserLevelPolicy),\r\n \"(none)\")\r\n| summarize PerType = count() by RecipientEmailAddress, OverrideType\r\n| summarize TotalThreats = sum(PerType),\r\n OverriddenThreats = sumif(PerType, OverrideType != \"(none)\"),\r\n OverrideTypes = strcat_array(make_set_if(strcat(OverrideType, \" (\", PerType, \")\"), OverrideType != \"(none)\"), \"; \")\r\n by RecipientEmailAddress\r\n| where OverriddenThreats > 0\r\n| extend OverridePercent = round(OverriddenThreats * 100.0 / TotalThreats, 1)\r\n| top 15 by OverriddenThreats\r\n| project ['Recipient']=RecipientEmailAddress, ['Total Threats']=TotalThreats, ['Overridden Threats']=OverriddenThreats, ['Override %']=OverridePercent, ['Override Types']=OverrideTypes", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Overridden Threats", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Override %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ] + }, + "graphSettings": { + "type": 2, + "topContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Value", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + }, + "nodeIdField": "StatisticName", + "sourceIdField": "Value", + "targetIdField": "Value", + "graphOrientation": 3, + "showOrientationToggles": false, + "nodeSize": null, + "staticNodeSize": 100, + "colorSettings": null, + "hivesMargin": 5, + "edgeColorSettings": null + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "Overrides - Top Users", + "id": "d7e169a2-808a-4bbf-86ee-5be561c690f7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top sender domains sending threats to users, with the share of those threats that were delivered because of an admin or user override and a breakdown of which override types caused them. High override rates are strong candidates for policy review or a Tenant Allow/Block List (TABL) block.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend OverrideType = case(\r\n OrgLevelAction == \"Allow\" and OrgLevelPolicy != \"\" and OrgLevelPolicy != \"SecOps Mailbox\", OrgLevelPolicy,\r\n UserLevelAction == \"Allow\", strcat(\"User: \", UserLevelPolicy),\r\n \"(none)\")\r\n| summarize PerType = count() by SenderFromDomain, OverrideType\r\n| summarize TotalThreats = sum(PerType),\r\n OverriddenThreats = sumif(PerType, OverrideType != \"(none)\"),\r\n OverrideTypes = strcat_array(make_set_if(strcat(OverrideType, \" (\", PerType, \")\"), OverrideType != \"(none)\"), \"; \")\r\n by SenderFromDomain\r\n| where OverriddenThreats > 0\r\n| extend OverridePercent = round(OverriddenThreats * 100.0 / TotalThreats, 1)\r\n| top 10 by OverriddenThreats\r\n| project ['Sender Domain']=SenderFromDomain, ['Total Threats']=TotalThreats, ['Overridden Threats']=OverriddenThreats, ['Override %']=OverridePercent, ['Override Types']=OverrideTypes", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Overridden Threats", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Override %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ] + }, + "graphSettings": { + "type": 2, + "topContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Value", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + }, + "nodeIdField": "StatisticName", + "sourceIdField": "Value", + "targetIdField": "Value", + "graphOrientation": 3, + "showOrientationToggles": false, + "nodeSize": null, + "staticNodeSize": 100, + "colorSettings": null, + "hivesMargin": 5, + "edgeColorSettings": null + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "Overrides - Top Sender Domains", + "id": "0eda3153-10ea-4d4e-80ca-7e5ad99e9883" + } + ] + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "Overrides - User & Sender Detail", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "d5f38e54-a3c7-4df6-b569-bbabe85e1a36" + }, + { + "type": 1, + "content": { + "json": "# False Negative(FN) Submissions insights\r\n\r\n---\r\n\r\nThis tab provides insights into email message **False Negative(FN) Submissions** performed by users or administrators in Microsoft Defender for Office 365 where the message reported to have **Malware, Phish or Spam threat** within its **content, URLs or attachments**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "8" + }, + "name": "text - 13 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3b243dca-89ce-41e6-bccb-9ceb0953aa2e" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
False Negative(FN) Admin submissions\r\n
\r\n\r\nThis section provides insights into email message **False Negative(FN) Submissions performed by administrators** in Microsoft Defender for Office 365 where the message reported to have Malware, Phish or Spam threat within its content, URLs or attachments.

**Recommended action:** Prioritise admin-submitted misses for policy tuning; recurring sender domains may be block-list candidates." + }, + "name": "fn admin - section header", + "id": "64420254-0dae-4495-bd55-fc49e5bc1ed0" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) Admin Submissions per-{Granularity} trend by submission types \r\n**Displays counts (per {Granularity}) of False Negative(FN) Admin Submissions grouped by submission type (Spam, Phish, Malware) and content type (Mail, URL, Attachment). Helps to monitor where detections were missed and later submitted by admins as false negatives to Microsoft.**" + }, + "name": "fn admin - trend heading", + "id": "5f2de929-6f32-4079-a031-cbf689c15b29" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of admin false negative submission by submission type.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(CloudAppEvents\r\n| where ActionType contains \"Submission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| summarize Admin_Malware_FN=countif(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"), Admin_Phish_FN=countif(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"), Admin_Spam_FN=countif(SubmissionType == \"0\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"), Admin_Malware_URL_FN=countif(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\"), Admin_Malware_Attach_FN=countif(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\"), Admin_Phish_URL_FN=countif(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\"), Admin_Phish_Attach_FN=countif(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Malware (Mail)']=coalesce(Admin_Malware_FN,0), ['Phish (Mail)']=coalesce(Admin_Phish_FN,0), ['Spam (Mail)']=coalesce(Admin_Spam_FN,0), ['Malware (URL)']=coalesce(Admin_Malware_URL_FN,0), ['Malware (Attachment)']=coalesce(Admin_Malware_Attach_FN,0), ['Phish (URL)']=coalesce(Admin_Phish_URL_FN,0), ['Phish (Attachment)']=coalesce(Admin_Phish_Attach_FN,0) | sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "TotalAdminSubmissions", + "color": "redDark" + }, + { + "seriesName": "Phish (Mail)", + "color": "redBright" + }, + { + "seriesName": "Spam (Mail)", + "color": "orange" + }, + { + "seriesName": "Malware (Mail)", + "color": "redDark" + }, + { + "seriesName": "Phish (URL)", + "color": "purple" + }, + { + "seriesName": "Malware (Attachment)", + "color": "yellowDark" + }, + { + "seriesName": "Phish (Attachment)", + "color": "purpleDark" + }, + { + "seriesName": "Malware (URL)", + "color": "yellow" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "fn admin - submissions trend", + "id": "1b61155b-92a1-4533-9561-2e85e9a4dbf8" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) Admin Submissions by submission types \r\n**Displays counts (per {Granularity}) of False Negative(FN) Admin Submissions grouped by submission type (Spam, Phish, Malware) and content type (Mail, URL, Attachment).**" + }, + "customWidth": "50", + "name": "fn admin - by-type heading", + "id": "bbaa9ff9-a95d-495a-a44c-6b4cae888a24" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) Admin Submissions by submission State\r\n**Displays the total count of False Negative(FN) Admin Submissions by submission State (e.g., Pending, Completed, Failed). Helps track the processing status of admin submissions and identify bottlenecks or errors.**" + }, + "customWidth": "50", + "name": "fn admin - by-state heading", + "id": "b060c706-342a-4b2e-b81a-920bf4d8c5d9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of admin false negative submission by submission type.\r\nCloudAppEvents \r\n| where ActionType contains \"Submission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| extend Admin_SubmissionType=\r\niff(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Malware (Mail)\",\r\niff(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\r\niff(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\",\"Malware (URL)\",\r\niff(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\",\"Malware (Attachment)\",\r\niff(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\",\"Phish (URL)\",\r\niff(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\",\"Phish (Attachment)\",\r\n\"Other\")))))))\r\n| where Admin_SubmissionType!=\"Other\"\r\n| summarize count() by Admin_SubmissionType", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn admin - by-type pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "9d9d714a-357b-4ac3-bcb7-33601d3c3108" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of admin false negative submissions by the state of the submission.\r\nCloudAppEvents \r\n| where ActionType contains \"AdminSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType in (\"0\",\"1\",\"2\")\r\n| summarize count() by tostring(SubmissionState)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn admin - by-state pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "169f0f1c-1f1e-44fb-965e-850733f01879" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN)/False Positive(FP) Admin Submissions by Triage Verdict\r\n**Displays the total count of False Negative(FN)/False Positive(FP) Admin Submissions grouped by TriageVerdict (e.g., Malware, Spam, Phish, Clean). Helps assess how submissions were graded during triage and identify detection gaps.**" + }, + "customWidth": "50", + "name": "fn admin - triage-verdict heading", + "id": "3df841be-c1b0-4d61-8e38-316a34a48bd1" + }, + { + "type": 1, + "content": { + "json": "### Top Admins Submitting False Negatives \r\n**Displays the top 15 admin accounts that submitted the highest number of false negative messages (missed detections) via AdminSubmission. Helps identify key contributors to threat remediation and potential patterns in detection gaps.**" + }, + "customWidth": "50", + "name": "fn admin - top-admins heading", + "id": "e1e966f4-1f4d-4377-97c6-e2077fc0b8fa" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of admin false negative or false positive submissions by the verdict of the submission grading.\r\nCloudAppEvents \r\n| where ActionType contains \"AdminSubmissionTriage\" \r\n| extend UserKey = (parse_json(RawEventData)).UserKey, SubmissionState = (parse_json(RawEventData)).SubmissionState, SubmissionId=(parse_json(RawEventData)).SubmissionId, TriageVerdict=(parse_json(RawEventData)).GradingResult.TriageVerdict \r\n| summarize count() by tostring(TriageVerdict)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn admin - triage-verdict pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6df0db72-f9db-444e-856a-4369921d199b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top admins performing false negative submissions\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend Record= (parse_json(RawEventData)).RecordType,SubmissionState = (parse_json(RawEventData)).SubmissionState, UserId = (parse_json(RawEventData)).UserId,SubmissionType = parse_json(RawEventData).SubmissionType \r\n| where Record == 29 and SubmissionType in (\"0\",\"1\",\"2\")\r\n| summarize ['Submissions']=count() by ['Admin']=tostring(UserId)\r\n| top 15 by ['Submissions'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn admin - top-admins pie", + "id": "b5ccb4a1-9783-47cf-bf21-ded924f1a200" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) Admin Submissions by Top Sender Domains\r\n**For each top sender domain that admins reported missed threats for, shows the domain's MDO-detected threat profile (emails with threats and the Malware/Phish/Spam breakdown), the count of admin FN submissions, and the submission rate (Admin Submission % = admin submissions / total inbound from the domain). A high rate can flag a domain whose mail is frequently reported as missed.**" + }, + "customWidth": "100", + "name": "fn admin - top-sender-domains heading", + "id": "1a481c97-ac85-4b62-a86d-51b33b5a8e68" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top 10 sender domains that admins reported false negatives (missed threats) for, with each domain's MDO-detected threat profile for context.\r\nlet subs = CloudAppEvents\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType), SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), P2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"2\",\"1\",\"0\")\r\n| summarize AdminSubmissions=count() by P2SenderDomain;\r\nlet domainProfile = EmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalInbound=count(), EmailsWithThreats=countif(isnotempty(ThreatTypes)), Malware=countif(ThreatTypes has \"Malware\"), Phish=countif(ThreatTypes has \"Phish\"), Spam=countif(ThreatTypes has \"Spam\") by SenderFromDomain;\r\nsubs\r\n| join kind=leftouter (domainProfile) on $left.P2SenderDomain == $right.SenderFromDomain\r\n| extend AdminSubmissionPct = round(AdminSubmissions * 100.0 / todouble(coalesce(TotalInbound, AdminSubmissions)), 2)\r\n| top 10 by AdminSubmissions desc\r\n| project ['Sender Domain']=P2SenderDomain, ['Emails With Threats']=coalesce(EmailsWithThreats,0), ['Malware']=coalesce(Malware,0), ['Phish']=coalesce(Phish,0), ['Spam']=coalesce(Spam,0), ['Admin Submissions']=AdminSubmissions, ['Admin Submission %']=AdminSubmissionPct", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails With Threats", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Malware", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Phish", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Spam", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Admin Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "120px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Admin Submission %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "110px" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn admin - top-sender-domains table", + "id": "e56bed92-b0fb-4b76-90f3-169f4206418b" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) Admin Submissions by admin Detection override types\r\n**Displays the top 10 cases where emails were submitted as false negatives by admins, even though they were initially detected by Microsoft Defender for Office 365 but delivered due to an admin policy override. Includes details on PolicyOverride, PolicySource, and DetectionVerdict for deeper insight into override behaviour.**" + }, + "customWidth": "100", + "name": "fn admin - override-types heading", + "id": "293c174c-0197-4cf8-bbce-36fe42e5cf1b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises emails submitted as false negatives by admins where emails where already detected by MDO but there was a admin policy override\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| extend Admin_SubmissionType=\r\niff(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Malware (Mail)\",\r\niff(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\"))),\r\nP2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain),NetworkMessageId=tostring((parse_json(RawEventData).ObjectId)),DetectionVerdict=tostring((parse_json(RawEventData)).DeliveryMessageInfo.FinalFilterVerdict),PolicyOverride=tostring((parse_json(RawEventData)).DeliveryMessageInfo.PolicyOverride),PolicyPolicyOverrideType=tostring((parse_json(RawEventData)).DeliveryMessageInfo.PolicySource)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"2\",\"1\",\"0\") and PolicyOverride !=\"NoOverride\"\r\n| summarize count() by PolicyOverride, PolicyPolicyOverrideType,DetectionVerdict,Admin_SubmissionType\r\n| top 10 by count_ desc\r\n| project ['Policy Override']=PolicyOverride, ['Override Source']=PolicyPolicyOverrideType, ['Detection Verdict']=DetectionVerdict, ['Submission Type']=Admin_SubmissionType, ['Emails']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn admin - override-types table", + "id": "97799422-53e0-4e3b-8103-297fd1c744eb" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "8" + }, + "name": "group - 11-Fn Admin Submissions", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "45a1c185-4fbf-4e83-832e-1f20af427796" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
False Negative(FN) User submissions\r\n
\r\n\r\nThis section provides insights into email message **False Negative(FN) Submissions performed by end users** in Microsoft Defender for Office 365 where the message reported as having Phish, Spam threat within its content, URLs or attachments.

**Recommended action:** Recognise engaged reporters, coach over-reporters, and use graded phishing verdicts to tune anti-phishing policy." + }, + "name": "fn user - section header", + "id": "ca0b48e6-8bd8-4f99-956a-f9c72cc870db" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions per-{Granularity} trend by submission types \r\n**Displays counts (per {Granularity}) of False Negative(FN) User Submissions grouped by submission type (Spam, Phish and Attack simulations) . Helps to monitor where detections were missed and later submitted by users as false negatives.**" + }, + "name": "fn user - trend heading", + "id": "60ac8608-7875-45e6-8c83-e6bd0c34af8b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of users false negative submission by submission type, including phish simulations reported by users.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(CloudAppEvents\r\n| where ActionType contains \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| summarize User_Phish_FN=countif(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\"), User_Spam_FN=countif(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\"), User_AttackSim_Submission=countif(ActionType == \"AttackSimUserSubmission\" and SubmissionContentType==\"Mail\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Phish (Mail)']=coalesce(User_Phish_FN,0), ['Spam (Mail)']=coalesce(User_Spam_FN,0), ['Attack simulation reported']=coalesce(User_AttackSim_Submission,0) | sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "TotalAdminSubmissions", + "color": "redDark" + }, + { + "seriesName": "Phish (Mail)", + "color": "redDark" + }, + { + "seriesName": "Attack simulation reported", + "color": "green" + }, + { + "seriesName": "Spam (Mail)", + "color": "orangeDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "fn user - submissions trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "29355816-6cba-4264-938e-b0b27afdcb12" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions by submission State\r\n**Displays the total count of False Negative(FN) User Submissions by submission State (e.g., Pending, Completed, Failed). Helps track the processing status of user submissions and identify bottlenecks or errors.**" + }, + "customWidth": "50", + "name": "fn user - by-state heading", + "id": "6a4b32cc-b7e4-47bb-b1b9-f415df7e629c" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions by Triage Verdict\r\n**Displays the total count of False Negative(FN)/False Positive(FP) User Submissions grouped by TriageVerdict (e.g., Malware, Spam, Phish, Clean). Helps assess how submissions were graded during triage and identify detection gaps.**" + }, + "customWidth": "50", + "name": "fn user - triage-verdict heading", + "id": "1427e34f-be44-4517-ae73-cc4776a49fe7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of user false negative submissions by the state of the submission.\r\nCloudAppEvents \r\n| where ActionType contains \"UserSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType in (\"0\",\"1\")\r\n| summarize count() by tostring(SubmissionState)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - by-state pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a6151271-e925-4804-a3c1-06afee27c026" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of user false negative or false positive submissions by the verdict of the submission grading.\r\nCloudAppEvents \r\n| where ActionType contains \"UserSubmissionTriage\" \r\n| extend UserKey = (parse_json(RawEventData)).UserKey, SubmissionState = (parse_json(RawEventData)).SubmissionState, SubmissionId=(parse_json(RawEventData)).SubmissionId, TriageVerdict=(parse_json(RawEventData)).GradingResult.TriageVerdict \r\n| summarize count() by tostring(TriageVerdict)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - triage-verdict pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6ff319ea-b5c5-4e33-9e5c-065aadbf465d" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions of already detected Emails (from Junk folder)\r\n**Displays the total count of False Negative(FN) User Submissions where the email message was already detected by Microsoft Defender for Office 365 and the detection action was configured to deliver the message into the Junk folder of the user mailbox. It breaks down the result based on the original detection verdict determined by Microsoft Defender for Office 365. Helps track the user submissions of messages that already had a detection. Consider changing the detection action to Quarantine to avoid these submissions.**" + }, + "name": "fn user - junk-folder heading", + "id": "d6338907-489d-4c88-b82f-260fc0f9d302" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of user false negative submissions that are already detected by MDO and already delivered in the junk folder\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where DeliveryLocation == \"Junk folder\"\r\n| summarize count() by ThreatTypes,User_SubmissionType\r\n| project ThreatTypes,User_SubmissionType, Emails = count_", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - junk-folder pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "c13452cb-e864-4f01-8623-51f3ea13bbbc" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of user false negative submissions that are already detected by MDO and already delivered in the junk folder\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId,UserId = (parse_json(RawEventData)).UserId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where DeliveryLocation == \"Junk folder\"\r\n| extend MDO_detection = parse_json(DetectionMethods) \r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n| summarize TotalJunkSubmittedEmailCount=count(),PhishEmailCount = countif(FirstDetection == \"Phish\"),SpamEmailCount = countif(FirstDetection == \"Spam\") by tostring(UserId)\r\n| top 15 by TotalJunkSubmittedEmailCount desc\r\n| project ['User']=UserId, ['Junk Submissions']=TotalJunkSubmittedEmailCount, ['Phish']=PhishEmailCount, ['Spam']=SpamEmailCount", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Junk Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spam", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - junk-folder table", + "id": "b242f301-c9f7-41f9-aa73-03848bd58eae" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions - Admin review status (Mark and Notify)\r\n**Displays counts of False Negative(FN) User Submissions that were reviewed by admins and marked with a notify action. The Mark and Notify action also can be taken automatically with Automated investigation and response (AIR). Helps track cases where admins confirmed user reports and communicated the outcome, supporting transparency and user trust.**" + }, + "customWidth": "50", + "name": "fn user - mark-notify heading", + "id": "784bf171-53ae-4907-b2b0-7fc5039df231" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions accuracy vs Admin review verdict\r\n**Displays counts of False Negative(FN) User Submissions (Phish, Junk, NotJunk) compared to admin review results. Highlights whether submissions were Correct, Not Correct, or misclassified comparing user submission type with the Admin decision using Mark and Notify action in Microsoft Defender for Office 365 (e.g., “Phish reported as Junk”, “Reported but not malicious”).**" + }, + "customWidth": "50", + "name": "fn user - accuracy heading", + "id": "3d137383-6436-4213-9824-72f424b67290" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises user submissions where admin also performed 'mark and notify' action on the submission\r\nlet ReviewResults = CloudAppEvents | where ActionType == \"SubmissionNotification\" \r\n| extend SubmissionId = tostring(parse_json(RawEventData).SubmissionId)\r\n| extend Properties = parse_json(RawEventData.ExtendedProperties)\r\n| mv-expand element = Properties\r\n| where element.Name == \"AdminReviewResult\"\r\n| project SubmissionId, AdminReviewResult = element.Value;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionId = tostring(parse_json(RawEventData).SubmissionId), SubmissionType = parse_json(RawEventData).SubmissionType\r\n| join kind=leftouter ReviewResults on SubmissionId\r\n| extend UserReportedAs=iif(SubmissionType == 1, \"Phish\",iif(SubmissionType == 2, \"Junk\",iif(SubmissionType == 3, \"NotJunk\",\"\")))\r\n| extend ReviewedAccuracy=iif(UserReportedAs==AdminReviewResult, 1,0)\r\n| extend Reviewed=iif(isempty(AdminReviewResult),\"Not Reviewed\",\"Reviewed\")\r\n| project SubmissionId,UserReportedAs,Reviewed,AdminReviewResult, ReviewedAccuracy\r\n| summarize count() by Reviewed", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - mark-notify pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "7bb7d116-bd61-4e46-81dd-d634a31e7369" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises user submissions type compared to admin review verdict. \r\n//Eg. User reporting a phish but admin review is 'not threat found'\r\nlet ReviewResults = CloudAppEvents | where ActionType == \"SubmissionNotification\" \r\n| extend SubmissionId = tostring(parse_json(RawEventData).SubmissionId)\r\n| extend Properties = parse_json(RawEventData.ExtendedProperties)\r\n| mv-expand element = Properties\r\n| where element.Name == \"AdminReviewResult\"\r\n| project SubmissionId, AdminReviewResult = element.Value;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionId = tostring(parse_json(RawEventData).SubmissionId), SubmissionType = parse_json(RawEventData).SubmissionType\r\n| join kind=leftouter ReviewResults on SubmissionId\r\n| extend UserReportedAs=iif(SubmissionType == 1, \"Phish\",iif(SubmissionType == 2, \"Junk\",iif(SubmissionType == 3, \"NotJunk\",\"\")))\r\n| extend ReviewedAccuracy=iif(AdminReviewResult==UserReportedAs, \"Correct\", iif(AdminReviewResult==\"Phish\" and UserReportedAs == \"Junk\", \"Phish reported as junk\",iif(AdminReviewResult==\"Junk\" and UserReportedAs == \"Phish\",\"Junk reported as Phish\",iif(AdminReviewResult==\"NotJunk\",\"Reported but not malicious or spam\",iif(isempty(AdminReviewResult),\"Not Reviewed\",\"Not correct\")))))\r\n| extend Reviewed=iif(isempty(AdminReviewResult),\"Not Reviewed\",\"Reviewed\")\r\n| project SubmissionId,UserReportedAs,Reviewed,AdminReviewResult, ReviewedAccuracy\r\n| where Reviewed==\"Reviewed\"\r\n| summarize count() by ReviewedAccuracy", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - accuracy pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8af1b9f0-995c-4c58-9960-8e69c6960987" + }, + { + "type": 1, + "content": { + "json": "### Top 10 P2 Email Senders domains in False Negative(FN) User Submissions \r\n**Displays the top 10 P2 email sender domains of inbound emails reported by users as false negatives (missed detections). Includes total inbound email volume and calculates the percentage of user submissions per domain to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "fn user - top-p2-domains heading", + "id": "78dab1f9-09ec-46e2-aee4-f256e368cdd5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises top 10 sender domains of inbound emails submitted as false negatives by users.\r\nlet TotalInboundbySender=\r\nEmailEvents\r\n| where EmailDirection ==\"Inbound\"\r\n| summarize count() by SenderFromDomain;\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType),RecipientObjectId=AccountObjectId,NetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\"\r\n| summarize UserSubmissions=count() by SenderFromDomain\r\n| join TotalInboundbySender on SenderFromDomain\r\n| extend UserSubmissions_Percentage = todouble(round(UserSubmissions / todouble(count_) * 100, 2))\r\n| top 10 by UserSubmissions desc\r\n| project ['Sender Domain']=SenderFromDomain, ['User Submissions']=UserSubmissions, ['Total Inbound']=count_, ['User Submission %']=UserSubmissions_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "User Submission %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "12ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - top-p2-domains table", + "id": "6e6a59d4-70e1-4d85-bebb-6bb23d25d2d9" + }, + { + "type": 1, + "content": { + "json": "### Top 10 P2 Individual Email Senders in False Negative(FN) User Submissions \r\n**Displays the top 10 P2 individual email sender addresses of inbound emails reported by users as false negatives (missed detections). Includes total inbound email volume and calculates the percentage of user submissions per sender to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "fn user - top-p2-senders heading", + "id": "a6e8fda5-dd05-49ed-87e2-16443495396e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises top 10 sender email addresses of inbound emails submitted as false negatives by users.\r\nlet TotalInboundbySender=\r\nEmailEvents\r\n| where EmailDirection ==\"Inbound\"\r\n| summarize count() by SenderFromAddress;\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType),P2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain),RecipientObjectId=AccountObjectId,NetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\"\r\n| summarize UserSubmissions=count() by SenderFromAddress\r\n| join TotalInboundbySender on SenderFromAddress\r\n| extend UserSubmissions_Percentage = todouble(round(UserSubmissions / todouble(count_) * 100, 2))\r\n| top 10 by UserSubmissions desc\r\n| project ['Sender Address']=SenderFromAddress, ['User Submissions']=UserSubmissions, ['Total Inbound']=count_, ['User Submission %']=UserSubmissions_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "User Submission %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "12ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - top-p2-senders table", + "id": "878fd15f-2607-4d6d-b919-0b4bea6a1850" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Intra-org Email Senders in False Negative(FN) User Submissions \r\n**Displays the top 10 email senders of intra-org emails reported by users as false negatives (missed detections). Includes total intra-org email volume and calculates the percentage of user submissions per sender to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "fn user - intraorg-senders heading", + "id": "87a51814-7f01-42e3-aea2-4136c869d39d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises top 10 sender email address of intra-org emails submitted as false negatives by users.\r\nlet TotalInboundbySender=\r\nEmailEvents\r\n| where EmailDirection ==\"Intra-org\"\r\n| summarize count() by SenderFromAddress;\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType),P2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain),RecipientObjectId=AccountObjectId,NetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Intra-org\"\r\n| summarize UserSubmissions=count() by SenderFromAddress\r\n| join TotalInboundbySender on SenderFromAddress\r\n| extend UserSubmissions_Percentage = todouble(round(UserSubmissions / todouble(count_) * 100, 2))\r\n| top 10 by UserSubmissions desc\r\n| project ['Sender Address']=SenderFromAddress, ['User Submissions']=UserSubmissions, ['Total Intra-org']=count_, ['User Submission %']=UserSubmissions_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Intra-org", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "User Submission %", + "formatter": 4, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "12ch" + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - intraorg-senders table", + "id": "38edca4b-a403-41e8-8c2b-7c0595e93b7a" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Intra-org Email Subjects in False Negative(FN) User Submissions \r\n**Displays the top 10 Email Subjects of intra-org emails reported by users as false negatives (missed detections). Helps to highlight high-risk intra-org email sources.**" + }, + "customWidth": "100", + "name": "fn user - intraorg-subjects heading", + "id": "52b0bc5b-7e54-4a5b-a487-8a736a8c2397" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises top 10 subjects of intra-org emails submitted as false negatives by users.\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Intra-org\"\r\n| summarize count() by Subject\r\n| top 10 by count_ desc\r\n| project ['Subject']=Subject, ['User Submissions']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Subject", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "70ch" + } + }, + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - intraorg-subjects table", + "id": "ee2c1d2e-3d4e-4024-8422-985b22cb7475" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Detection Overrides defined by Admins in False Negative(FN) User Submissions \r\n**Displays the top 10 use cases where users submitted emails as false negatives (Spam or Phish) that were already detected by Microsoft Defender for Office 365 but delivered due to an admin-defined policy override. Includes details on OrgLevelAction, OrgLevelPolicy, and ThreatTypes for deeper insight into override behaviour.**" + }, + "customWidth": "100", + "name": "fn user - admin-override heading", + "id": "0dd9b3ce-9716-42bb-93de-495f0af2d075" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises emails submitted as false negatives by users where emails where already detected by MDO but there was an admin definded policy override.\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where ThreatTypes !=\"\"and OrgLevelAction!=\"\"\r\n| summarize count() by OrgLevelAction, OrgLevelPolicy,ThreatTypes,User_SubmissionType\r\n| top 10 by count_ desc\r\n| project ['Override Action']=OrgLevelAction, ['Override Policy']=OrgLevelPolicy, ['Threat Type']=ThreatTypes, ['Submission Type']=User_SubmissionType, ['User Submissions']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Override Policy", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "48ch" + } + }, + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - admin-override table", + "id": "100de6ca-beb0-44d7-a715-449a389e9e8a" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Detection Overrides defined by Users in False Negative(FN) User Submissions \r\n**Displays the top 10 use cases where users submitted emails as false negatives (Spam or Phish) that were already detected by Microsoft Defender for Office 365 but delivered due to a user-defined override. Includes details on UserLevelAction, UserLevelPolicy, and ThreatTypes for deeper insight into override behaviour.**" + }, + "customWidth": "100", + "name": "fn user - user-override heading", + "id": "67057c7d-c0af-4373-b23a-4001fbced888" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises emails submitted as false negatives by users where emails where already detected by MDO but there was an policy override.\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where ThreatTypes !=\"\"and UserLevelAction!=\"\"\r\n| summarize count() by UserLevelAction, UserLevelPolicy,ThreatTypes,User_SubmissionType\r\n| top 10 by count_ desc\r\n| project ['Override Action']=UserLevelAction, ['Override Policy']=UserLevelPolicy, ['Threat Type']=ThreatTypes, ['Submission Type']=User_SubmissionType, ['User Submissions']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Override Policy", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "48ch" + } + }, + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - user-override table", + "id": "1b97f7d2-152d-4eb0-bfac-e161fbfa4046" + }, + { + "type": 1, + "content": { + "json": "### Top 10 users performing the most False Negative(FN) User Submissions\r\n**Displays the Top 10 user accounts that performed the highest number of False Negative(FN) User Submissions (missed detections). Helps identify individuals most engaged in reporting suspicious, malicious messages and potential patterns in detection gaps.**" + }, + "customWidth": "100", + "name": "fn user - top-users heading", + "id": "7799a0a0-a835-4080-b59a-736b08ad809e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top 10 users performing false negative submissions\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType in (\"0\",\"1\")\r\n| extend UserId = (parse_json(RawEventData)).UserId\r\n| summarize ['Submissions']=count() by ['User']=tostring(UserId)\r\n| top 10 by ['Submissions'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - top-users pie", + "id": "44838734-43a0-4301-9ddb-a644c7ec509a" + }, + { + "type": 1, + "content": { + "json": "### Top 10 users performing the most User Submissions of Attack simulation messages\r\n**Displays the top 10 user accounts that reported phishing simulation emails during cyber security awareness campaigns. Supports evaluation of cyber security awareness programme effectiveness and identifies highly engaged users.**" + }, + "customWidth": "100", + "name": "fn user - attacksim-users heading", + "id": "8a96e90f-765f-40c0-8476-30c97d43c328" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top users reporting the phishing simulation emails.\r\nCloudAppEvents \r\n| extend Record= (parse_json(RawEventData)).RecordType \r\n| extend SubmissionState = (parse_json(RawEventData)).SubmissionState \r\n| extend UserId = (parse_json(RawEventData)).UserId\r\n| where Record == 29\r\n| where ActionType == \"AttackSimUserSubmission\" \r\n| summarize ['Submissions']=count() by ['User']=tostring(UserId)\r\n| top 10 by ['Submissions'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - attacksim-users pie", + "id": "ab648c4a-4c46-4c73-96f0-784c9bcef961" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "8" + }, + "name": "group - 11 - FN User submissions", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "348ce24a-7cbc-4b66-a471-dfe3827bed2d" + }, + { + "type": 1, + "content": { + "json": "# False Positive(FP) Submissions insights\r\n\r\n---\r\n\r\nThis tab provides insights into email message **False Positive(FP) Submissions** performed by users or administrators in Microsoft Defender for Office 365 where the message was flagged as a threat by Microsoft Defender for Office 365 but was later reported as No Threat by administrators or users." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "10" + }, + "name": "fp - tab description", + "id": "78e2df52-a0d2-499a-95fe-708f67db5ad6" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
False Positive(FP) Admin Submissions\r\n
\r\n\r\nAdministrator submissions represent escalated false positive reports submitted by security team members rather than end users. These typically involve more complex cases requiring expert review, such as recurring issues affecting multiple users, business-critical communications being blocked, or suspected policy misconfigurations. Admin submissions carry higher priority and can result in actions as allow-list additions or global policy changes to prevent widespread user impact.

**Recommended action:** Review recurring false-positive sender domains and consider allow entries or policy tuning to reduce business disruption." + }, + "name": "fp admin - section header", + "id": "02d54e9c-e989-4cde-a128-68a6381ed9d7" + }, + { + "type": 1, + "content": { + "json": "### Admin Submission Volume and Type Breakdown\r\n\r\n**These charts track the volume and composition of administrator-initiated false positive submissions. The trend chart shows submission patterns (per {Granularity}) across Email, URL, and Attachment types, while the pie chart reveals the distribution among these categories. Spikes in admin submissions often signal systemic issues requiring immediate policy review, as admins typically escalate only the most impactful or recurring problems.**" + }, + "name": "fp admin - volume/type heading", + "id": "103b8362-a10f-4b46-a757-8290c4269a5c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of admin false positive submission by submission type.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(CloudAppEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(CloudAppEvents | summarize max(Timestamp));\r\nlet agg = materialize(CloudAppEvents\r\n| where ActionType contains \"Submission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| summarize Admin_Email_FP=countif(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"), Admin_URL_FP=countif(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\"), Admin_Attach_FP=countif(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Email']=coalesce(Admin_Email_FP,0), ['URL']=coalesce(Admin_URL_FP,0), ['Attachment']=coalesce(Admin_Attach_FP,0) | sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "TotalAdminSubmissions", + "color": "redDark" + }, + { + "seriesName": "Admin_Phish_FN", + "color": "redBright" + }, + { + "seriesName": "Admin_Spam_FN", + "color": "orange" + }, + { + "seriesName": "Admin_Malware_FN", + "color": "redDark" + }, + { + "seriesName": "Admin_Phish_URL_FN", + "color": "purple" + }, + { + "seriesName": "Admin_Malware_Attach_FN", + "color": "yellowDark" + }, + { + "seriesName": "Admin_Phish_Attach_FN", + "color": "purpleDark" + }, + { + "seriesName": "Admin_Malware_URL_FN", + "color": "yellow" + }, + { + "seriesName": "Admin_Email_FP", + "color": "redDark" + }, + { + "seriesName": "Admin_URL_FP", + "color": "orangeDark" + }, + { + "seriesName": "Admin_Attach_FP", + "color": "yellow" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "fp admin - submissions trend", + "id": "326762ca-1f2b-48e9-90d6-ff2aa6a75e95" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of admin false positive submission by submission type.\r\nCloudAppEvents \r\n| where ActionType contains \"Submission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| extend Admin_SubmissionType=\r\niff(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Email\",\r\niff(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\",\"URL\",\r\niff(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\",\"Attachment\",\r\n\"Other\")))\r\n| where Admin_SubmissionType!=\"Other\"\r\n| summarize count() by Admin_SubmissionType", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "fp admin - by-type pie", + "id": "be925c4c-5718-4385-8e82-59c57b975ac5" + }, + { + "type": 1, + "content": { + "json": "### False Positive(FP) Admin Submissions by submission state
\r\n\r\n**Displays the total count of False Positive(FP) Admin Submissions by submission State (e.g., Pending, Completed, Failed). Helps track the processing status of admin submissions and identify bottlenecks or errors.**" + }, + "customWidth": "50", + "name": "fp admin - by-state heading", + "id": "2b2acb67-c070-48bd-acf1-025c05aae8b5" + }, + { + "type": 1, + "content": { + "json": "### Top Admins Submitting False Positives
\r\n\r\n**Displays the top 15 admin accounts that submitted the highest number of false positive messages via AdminSubmission.**" + }, + "customWidth": "50", + "name": "fp admin - top-admins heading", + "id": "52206f40-fae9-460f-97b8-2cf9b633098f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of admin false positive submissions by the state of the submission.\r\nCloudAppEvents \r\n| where ActionType contains \"AdminSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType == \"3\"\r\n| summarize count() by tostring(SubmissionState)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp admin - by-state pie", + "id": "96133d9e-24fb-417e-a3cd-df98dda4c60a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top admins performing false positive submissions.\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend Record= (parse_json(RawEventData)).RecordType,SubmissionState = (parse_json(RawEventData)).SubmissionState, UserId = (parse_json(RawEventData)).UserId,SubmissionType = parse_json(RawEventData).SubmissionType \r\n| where Record == 29 and SubmissionType ==\"3\"\r\n| summarize ['Submissions']=count() by ['Admin']=tostring(UserId)\r\n| top 15 by ['Submissions'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp admin - top-admins pie", + "id": "da7b4c89-904d-4917-b6cd-04b32e02d4a1" + }, + { + "type": 1, + "content": { + "json": "### Admin Submission False Positive Malware Detection Breakdown\r\n**Shows the count of administrator-submitted false positive reports (legitimate emails flagged as malware) grouped by the detection method that flagged them. Helps identify which filtering technologies most often misclassify valid messages as malware.**" + }, + "customWidth": "100", + "name": "fp admin - malware-detection heading", + "id": "69d649e0-86fd-4c08-afd4-e6c200b11c86" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Admin false positive submissions whose original verdict was Malware, grouped by the detection method that flagged them. A high count means that method most often misclassifies legitimate mail as Malware.\r\nlet total = toscalar(CloudAppEvents\r\n | where ActionType == \"AdminSubmissionSubmitted\"\r\n | extend R = parse_json(RawEventData)\r\n | where tostring(R.SubmissionContentType) == \"Mail\" and tostring(R.SubmissionType) == \"3\" and tostring(R.DeliveryMessageInfo.FinalFilterVerdict) == \"Malware\"\r\n | count);\r\nCloudAppEvents\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), DetectionMethod = tostring(R.DeliveryMessageInfo.FinalFilterVerdictControlSource), DetectionVerdict = tostring(R.DeliveryMessageInfo.FinalFilterVerdict), P2SenderDomain = tostring(R.P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\" and DetectionVerdict == \"Malware\"\r\n| extend DetectionMethod = iif(isempty(DetectionMethod), \"Not specified\", DetectionMethod)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(P2SenderDomain) by DetectionMethod\r\n| extend Pct = iif(total == 0, 0.0, round(FPSubmissions * 100.0 / total, 1))\r\n| sort by FPSubmissions desc\r\n| project ['Detection Method'] = DetectionMethod, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains, ['% of Malware FPs'] = Pct", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "% of", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp admin - malware-detection table", + "id": "607eb19b-1ded-488d-98db-8b23f9e90967" + }, + { + "type": 1, + "content": { + "json": "### Admin Submission False Positive Phish Detection Breakdown\r\n**Shows the count of administrator-submitted false positive reports (legitimate emails flagged as phishing) grouped by the detection method that flagged them. Helps identify which filtering technologies most often misclassify valid messages as phishing.**" + }, + "customWidth": "100", + "name": "fp admin - phish-detection heading", + "id": "c1f1e12f-d0aa-4023-9172-8182772b3331" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Admin false positive submissions whose original verdict was Phish, grouped by the detection method that flagged them. A high count means that method most often misclassifies legitimate mail as Phish.\r\nlet total = toscalar(CloudAppEvents\r\n | where ActionType == \"AdminSubmissionSubmitted\"\r\n | extend R = parse_json(RawEventData)\r\n | where tostring(R.SubmissionContentType) == \"Mail\" and tostring(R.SubmissionType) == \"3\" and tostring(R.DeliveryMessageInfo.FinalFilterVerdict) == \"Phish\"\r\n | count);\r\nCloudAppEvents\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), DetectionMethod = tostring(R.DeliveryMessageInfo.FinalFilterVerdictControlSource), DetectionVerdict = tostring(R.DeliveryMessageInfo.FinalFilterVerdict), P2SenderDomain = tostring(R.P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\" and DetectionVerdict == \"Phish\"\r\n| extend DetectionMethod = iif(isempty(DetectionMethod), \"Not specified\", DetectionMethod)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(P2SenderDomain) by DetectionMethod\r\n| extend Pct = iif(total == 0, 0.0, round(FPSubmissions * 100.0 / total, 1))\r\n| sort by FPSubmissions desc\r\n| project ['Detection Method'] = DetectionMethod, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains, ['% of Phish FPs'] = Pct", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "% of", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp admin - phish-detection pie", + "id": "b6c074f9-affa-41a3-802a-53541394ae73" + }, + { + "type": 1, + "content": { + "json": "### Admin Submission False Positive Spam Detection Breakdown\r\n**Shows the count of administrator-submitted false positive reports (legitimate emails flagged as spam) grouped by the detection method that flagged them. Helps identify which filtering technologies most often misclassify valid messages as spam.**" + }, + "customWidth": "100", + "name": "fp admin - spam-detection heading", + "id": "f0f2adb9-34af-4df0-90e6-087a265bedf6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Admin false positive submissions whose original verdict was Spam, grouped by the detection method that flagged them. A high count means that method most often misclassifies legitimate mail as Spam.\r\nlet total = toscalar(CloudAppEvents\r\n | where ActionType == \"AdminSubmissionSubmitted\"\r\n | extend R = parse_json(RawEventData)\r\n | where tostring(R.SubmissionContentType) == \"Mail\" and tostring(R.SubmissionType) == \"3\" and tostring(R.DeliveryMessageInfo.FinalFilterVerdict) == \"Spam\"\r\n | count);\r\nCloudAppEvents\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), DetectionMethod = tostring(R.DeliveryMessageInfo.FinalFilterVerdictControlSource), DetectionVerdict = tostring(R.DeliveryMessageInfo.FinalFilterVerdict), P2SenderDomain = tostring(R.P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\" and DetectionVerdict == \"Spam\"\r\n| extend DetectionMethod = iif(isempty(DetectionMethod), \"Not specified\", DetectionMethod)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(P2SenderDomain) by DetectionMethod\r\n| extend Pct = iif(total == 0, 0.0, round(FPSubmissions * 100.0 / total, 1))\r\n| sort by FPSubmissions desc\r\n| project ['Detection Method'] = DetectionMethod, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains, ['% of Spam FPs'] = Pct", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "% of", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp admin - spam-detection pie", + "id": "e877d9c9-3bd3-4368-997e-945f18ffcf5f" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains for Admin False Positive Submissions
\r\n\r\n**Lists the top 10 sender domains of emails reported as false positives by administrators (legitimate messages incorrectly flagged as spam or phishing). Helps identify domains frequently misclassified.**" + }, + "customWidth": "50", + "name": "fp admin - top-sender-domains heading", + "id": "37680101-7e4b-4bcc-9e7e-0ccd2d914881" + }, + { + "type": 1, + "content": { + "json": "### Admin False Positive Submissions by Original Threat Verdict
\r\n\r\n**Displays all administrator-submitted false positive emails by their original filter verdict (e.g., spam, phishing) and policy override details. Helps identify which threat categories are most often misclassified.**" + }, + "customWidth": "50", + "name": "fp admin - by-verdict heading", + "id": "879e81ad-00a6-4a10-bcb6-56879133bb9f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top 10 sender domains of emails which are submitted as false positive by admins\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType),P2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType ==\"3\"\r\n| summarize count() by P2SenderDomain\r\n| top 10 by count_ desc\r\n| project ['Sender Domain']=P2SenderDomain, ['Emails']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp admin - top-sender-domains table", + "id": "42844dc9-4418-487b-a5ad-31e1f6b4b487" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises all emails submitted as false positive by admins summarizing by the original filter verdict threat type\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| extend Admin_SubmissionType=\r\niff(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\" ,\"Email\",\r\n\"Other\"),\r\nP2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain),NetworkMessageId=tostring((parse_json(RawEventData).ObjectId)),DetectionVerdict=tostring((parse_json(RawEventData)).DeliveryMessageInfo.FinalFilterVerdict),PolicyOverride=tostring((parse_json(RawEventData)).DeliveryMessageInfo.PolicyOverride),PolicyPolicyOverrideType=tostring((parse_json(RawEventData)).DeliveryMessageInfo.PolicySource)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| summarize count() by PolicyOverride,DetectionVerdict,Admin_SubmissionType\r\n| top 10 by count_ desc\r\n| project ['Policy Override']=PolicyOverride, ['Detection Verdict']=DetectionVerdict, ['Submission Type']=Admin_SubmissionType, ['Emails']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp admin - by-verdict table", + "id": "3ebbd402-06ef-45a7-b4ee-c5938b98b540" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "10" + }, + "name": "fp admin - group", + "styleSettings": { + "showBorder": true + }, + "id": "b6215b53-c181-4693-a14f-441809f65f38" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
False Positive (FP) User Submissions\r\n
\r\n\r\nThis section provides insights into email message False Postive(FP) Submissions performed by end users in Microsoft Defender for Office 365 where the message was flagged as a threat by Microsoft Defender for Office 365 but was later reported as No Threat by users. User submissions are critical feedback mechanisms that help security teams identify overly aggressive detection rules, refine security policies, and reduce user friction. High false positive rates can erode user trust and lead to security fatigue, so monitoring these metrics helps balance protection with productivity.

**Recommended action:** High user false-positive volume suggests over-aggressive filtering - review the affected senders and adjust policy." + }, + "name": "fp user - section header", + "id": "0d93d7ee-a61e-43b7-bdcd-172bd79ad050" + }, + { + "type": 1, + "content": { + "json": "### User Submission Trend\r\n\r\n**Displays the volume (per {Granularity}) of false positive submissions from end users. A sudden spike may indicate a new detection rule causing widespread misclassification, while a declining trend suggests improving detection accuracy. Monitoring this trend helps security teams respond quickly to detection issues before they impact user productivity.**" + }, + "name": "fp user - trend heading", + "id": "c3f8ae45-0498-4fa8-b9d1-35e926932639" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of user false positive submission by submission type.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(CloudAppEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(CloudAppEvents | summarize max(Timestamp));\r\nlet agg = materialize(CloudAppEvents\r\n| where ActionType contains \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where SubmissionType == \"3\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\"\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['User FP Submissions'] = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "User FP Submissions", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - submissions trend", + "id": "847032f5-56a8-4681-9665-9e917c7c9355" + }, + { + "type": 1, + "content": { + "json": "### User False Positive Submissions by State
\r\n\r\n**Displays the total number of user-reported false positive email submissions grouped by their processing state (e.g., pending, completed). Helps track submission workflow and resolution progress.**" + }, + "customWidth": "50", + "name": "fp user - by-state heading", + "id": "7bd03278-7734-4fbf-a502-95b42e90160e" + }, + { + "type": 1, + "content": { + "json": "### Top Users Performing False Positive Submissions
\r\n\r\n**Lists the top 15 users who reported emails as false positives (legitimate messages incorrectly flagged as threats). Helps identify frequent reporters and potential training or policy adjustment needs.**" + }, + "customWidth": "50", + "name": "fp user - top-users heading", + "id": "7e2b987b-325d-4f69-8d6b-fafd6676a03a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of user false positive submission by submission state.\r\nCloudAppEvents \r\n| where ActionType contains \"UserSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType == \"3\"\r\n| summarize count() by tostring(SubmissionState)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp user - by-state pie", + "id": "df79d08b-3eac-4101-a3f2-3a4a3bf450ce" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top users performing false positive submissions.\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType == \"3\"\r\n| extend UserId = (parse_json(RawEventData)).UserId\r\n| summarize ['Submissions']=count() by ['User']=tostring(UserId)\r\n| top 15 by ['Submissions'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp user - top-users pie", + "id": "ec7505d8-3a70-4bde-a985-baf5a0c4ec34" + }, + { + "type": 1, + "content": { + "json": "### User Submission False Positive Malware Detection Breakdown\r\n**Shows the count of user-submitted false positive reports (legitimate emails flagged as malware) grouped by the detection technique that flagged them. Malware quarantine is admin-only by default, so this table only populates when a custom quarantine policy lets users view and report their own malware detections - it is usually empty.**" + }, + "customWidth": "100", + "name": "fp user - malware-verdict heading", + "id": "693b1072-5ddd-49d0-a0f5-2bba4c287edf" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//User false positive submissions whose email was originally flagged as Malware, by the detection technique that flagged it. A high count means that technique most often misclassifies legitimate mail as Malware.\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has \"Malware\"\r\n| mv-expand Technique = parse_json(DetectionMethods).Malware to typeof(string)\r\n| where isnotempty(Technique)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(SenderFromDomain) by Technique\r\n| sort by FPSubmissions desc\r\n| project ['Detection Technique'] = Technique, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "22ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - malware-verdict table", + "id": "10ea55bd-937e-454d-b6cc-a9dccfdf3417" + }, + { + "type": 1, + "content": { + "json": "### User Submission False Positive Phish Detection Breakdown\r\n**Shows the count of user-submitted false positive reports (legitimate emails flagged as phishing) grouped by the detection technique that flagged them. Helps identify which filtering technologies most often misclassify valid messages as phishing.**" + }, + "customWidth": "100", + "name": "fp user - phish-verdict heading", + "id": "6dd14abb-2772-4271-89d8-8c0dcdbfd9e5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//User false positive submissions whose email was originally flagged as Phish, by the detection technique that flagged it. A high count means that technique most often misclassifies legitimate mail as Phish.\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has \"Phish\"\r\n| mv-expand Technique = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Technique)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(SenderFromDomain) by Technique\r\n| sort by FPSubmissions desc\r\n| project ['Detection Technique'] = Technique, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "22ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - phish-verdict pie", + "id": "57049aad-eb17-4e65-a8a4-b5d05b0501cd" + }, + { + "type": 1, + "content": { + "json": "### User Submission False Positive Spam Detection Breakdown\r\n**Shows the count of user-submitted false positive reports (legitimate emails flagged as spam) grouped by the detection technique that flagged them. Helps identify which filtering technologies most often misclassify valid messages as spam.**" + }, + "customWidth": "100", + "name": "fp user - spam-verdict heading", + "id": "5479b2ed-b629-41e7-9857-c91191b09c8f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//User false positive submissions whose email was originally flagged as Spam, by the detection technique that flagged it. A high count means that technique most often misclassifies legitimate mail as Spam.\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has \"Spam\"\r\n| mv-expand Technique = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Technique)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(SenderFromDomain) by Technique\r\n| sort by FPSubmissions desc\r\n| project ['Detection Technique'] = Technique, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "22ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - spam-verdict pie", + "id": "45a2122e-0281-4602-906d-a0406ed20d54" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains for User False Positive Submissions
\r\n\r\n**Lists the top 10 sender domains of emails reported as false positives by users (legitimate messages incorrectly flagged as threats). Helps identify domains frequently misclassified.**" + }, + "customWidth": "100", + "name": "fp user - top-sender-domains heading", + "id": "2751fca4-3ac5-45fe-a965-8c811018926a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top 10 sender domains reported as false positives by users, with each domain's total inbound volume and the share of it reported as FP (a high rate flags a domain whose legitimate mail is most often misclassified).\r\nlet totalByDomain = EmailEvents | where EmailDirection == \"Inbound\" | summarize TotalInbound = count() by SenderFromDomain;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), P2SenderDomain = tostring(R.P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| summarize FPSubmissions = count() by P2SenderDomain\r\n| join kind=leftouter (totalByDomain) on $left.P2SenderDomain == $right.SenderFromDomain\r\n| extend FPPct = iif(isnull(TotalInbound) or TotalInbound == 0, 0.0, round(FPSubmissions * 100.0 / TotalInbound, 2))\r\n| top 10 by FPSubmissions desc\r\n| project ['Sender Domain'] = P2SenderDomain, ['FP Submissions'] = FPSubmissions, ['Total Inbound'] = coalesce(TotalInbound, 0), ['FP Submission %'] = FPPct", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "18ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "FP Submission %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - top-sender-domains table", + "id": "c69b126d-9f25-44a0-b96d-601d89a563f1" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Senders in User False Positive Submissions
\r\n\r\n**Displays the top 10 email senders whose messages were reported as false positives by users (legitimate emails incorrectly flagged as threats). Helps identify senders frequently misclassified.**" + }, + "customWidth": "100", + "name": "fp user - top-senders heading", + "id": "b39966ad-2b40-4144-ae3f-c7ac6b9fb97c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top 10 email senders reported as false positives by users, with each sender's total inbound volume and the share reported as FP.\r\nlet totalBySender = EmailEvents | where EmailDirection == \"Inbound\" | summarize TotalInbound = count() by SenderMailFromAddress;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\"\r\n| summarize FPSubmissions = count() by SenderMailFromAddress\r\n| join kind=leftouter (totalBySender) on SenderMailFromAddress\r\n| extend FPPct = iif(isnull(TotalInbound) or TotalInbound == 0, 0.0, round(FPSubmissions * 100.0 / TotalInbound, 2))\r\n| top 10 by FPSubmissions desc\r\n| project ['Sender Address'] = SenderMailFromAddress, ['FP Submissions'] = FPSubmissions, ['Total Inbound'] = coalesce(TotalInbound, 0), ['FP Submission %'] = FPPct", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "18ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "FP Submission %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - top-senders table", + "id": "077ab610-58ed-4d23-886c-dbf912cef2d7" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Subjects in User False Positive Submissions
\r\n\r\n**Displays the top 10 email subjects reported as false positives by users (legitimate messages incorrectly flagged as threats). Helps identify common patterns in misclassified emails.**" + }, + "customWidth": "100", + "name": "fp user - top-subjects heading", + "id": "a5b939e1-0fbf-4ee1-a6a3-01fa7639af3a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top 10 email subjects reported as false positives by users, with how many distinct recipients reported each (a subject reported by many users is a broad misclassification pattern).\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\"\r\n| summarize FPSubmissions = count(), DistinctRecipients = dcount(RecipientObjectId) by Subject\r\n| top 10 by FPSubmissions desc\r\n| project ['Subject'] = Subject, ['FP Submissions'] = FPSubmissions, ['Distinct Recipients'] = DistinctRecipients", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Subject", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "70ch" + } + }, + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Recipients", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "18ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - top-subjects table", + "id": "71d5c290-f5d0-493c-b821-b5345dbe7312" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Intra-Org Senders in User False Positive Submissions
\r\n\r\n**Displays the top 10 internal senders whose emails were reported as false positives by users (legitimate intra-org messages incorrectly flagged as threats). Helps identify internal communication patterns causing misclassification.**" + }, + "customWidth": "100", + "name": "fp user - intraorg-senders heading", + "id": "1d38f458-dfde-4608-ad7d-ee8628e85ee7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top 10 internal senders whose emails were reported as false positives by users, with total intra-org volume and the share reported as FP.\r\nlet totalBySender = EmailEvents | where EmailDirection == \"Intra-org\" | summarize TotalIntraOrg = count() by SenderMailFromAddress;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Intra-org\"\r\n| summarize FPSubmissions = count() by SenderMailFromAddress\r\n| join kind=leftouter (totalBySender) on SenderMailFromAddress\r\n| extend FPPct = iif(isnull(TotalIntraOrg) or TotalIntraOrg == 0, 0.0, round(FPSubmissions * 100.0 / TotalIntraOrg, 2))\r\n| top 10 by FPSubmissions desc\r\n| project ['Sender Address'] = SenderMailFromAddress, ['FP Submissions'] = FPSubmissions, ['Total Intra-org'] = coalesce(TotalIntraOrg, 0), ['FP Submission %'] = FPPct", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Intra-org", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "18ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "FP Submission %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - intraorg-senders table", + "id": "b6699a7f-897a-4016-ae2c-d816f3a9492b" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "10" + }, + "name": "fp user - group", + "styleSettings": { + "showBorder": true + }, + "id": "2ad3311e-e92b-4a49-bdd0-775f085c4587" + }, + { + "type": 1, + "content": { + "json": "# File Malware Detections (SharePoint, Teams and OneDrive)\r\n\r\n---\r\n\r\nThis tab provides insights into malicious file detections across Microsoft collaboration platforms such as SharePoint, OneDrive, and Teams.\r\n\r\n[

Safe Attachments for SharePoint, OneDrive, and Microsoft Teams

](https://learn.microsoft.com/en-us/defender-office-365/safe-attachments-for-spo-odfb-teams-about)\r\n[

Built-in virus protection in SharePoint, SharePoint Embedded, OneDrive, and Microsoft Teams

](https://learn.microsoft.com/en-us/defender-office-365/anti-malware-protection-for-spo-odfb-teams-about) " + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "9" + }, + "name": "filemal - tab description", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "cefcac88-f373-4748-b0ea-e7600f63edd7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Microsoft Defender for Office 365 value for files in SharePoint / OneDrive / Teams: total files processed, how many had a malware detection, and how many were scanned with no detection. A per-period Trend series feeds the tile sparkline.\r\nlet gran = {Granularity};\r\nlet base = FileMaliciousContentInfo;\r\nlet counts = union\r\n(base | summarize Count = count() | extend Cat = \"Total Files Processed (SPO/ODB/Teams)\", Ord = 1),\r\n(base | where isnotempty(ThreatTypes) | summarize Count = count() | extend Cat = \"Files with Malware Detected\", Ord = 2),\r\n(base | where isempty(ThreatTypes) | summarize Count = count() | extend Cat = \"Files Scanned - No Detection\", Ord = 3);\r\nlet tagged = union\r\n(base | extend Cat = \"Total Files Processed (SPO/ODB/Teams)\"),\r\n(base | where isnotempty(ThreatTypes) | extend Cat = \"Files with Malware Detected\"),\r\n(base | where isempty(ThreatTypes) | extend Cat = \"Files Scanned - No Detection\");\r\nlet trends = tagged | make-series Trend = count() default = 0 on Timestamp step gran by Cat;\r\ncounts\r\n| join kind=leftouter (trends) on Cat\r\n| sort by Ord asc\r\n| project Count, Details = Cat, Trend", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "filemal - MDO value tiles", + "id": "843e58a9-6324-4a90-a652-bfb0549e79dc", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "9" + } + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
File Malware Detection (SharePoint, OneDrive, and Teams)\r\n
\r\n\r\nThis section monitors malware detections in files stored across Microsoft 365 collaboration platforms. Microsoft Defender for Office 365 and built-in SharePoint Online antivirus work together to scan files uploaded to SharePoint, OneDrive, and Teams. Understanding file-based malware patterns helps protect collaborative workspaces and identify potential security risks in shared content.

**Recommended action:** For repeat file owners or sites, investigate possible compromise and confirm Safe Attachments for SharePoint, OneDrive and Teams is enabled." + }, + "name": "filemal - section header", + "id": "373fe4e5-fc90-49cf-93ba-c8b100efce57" + }, + { + "type": 1, + "content": { + "json": "### File Malware Detection Trend
\r\n\r\n**This visual tracks the volume (per {Granularity}) of malware detections in files across all Microsoft 365 workloads. Spikes in detection activity may indicate targeted attacks or emerging malware campaigns affecting collaborative platforms. Regular monitoring helps identify unusual patterns that require investigation.**" + }, + "name": "filemal - trend heading", + "id": "30145585-8998-443a-b6ec-062d136c621f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total files located on SharePoint, OneDrive and Teams with Malware detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(FileMaliciousContentInfo\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Files']=coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "tileSettings": { + "showBorder": false + }, + "graphSettings": { + "type": 0 + }, + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Files", + "color": "blueDark" + } + ], + "showDataPoints": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "filemal - detection trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d39cea9b-75a8-4c29-bfdb-2e0db855e98a" + }, + { + "type": 1, + "content": { + "json": "### Malware Family Analysis - Defender for Office 365\r\n**Provides a breakdown of malware detections in files scanned by Microsoft Defender for Office 365 (Safe Attachments detonation) across SharePoint, OneDrive, and Teams. The table lists each malware family with total detections, distinct files, affected locations and when it was last seen, helping identify dominant threats and their spread across collaboration platforms.**" + }, + "customWidth": "100", + "name": "filemal - family MDO heading", + "id": "4e330873-f732-4d37-a7b0-dced08b019b0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query summarizes File malware detections by Microsoft Defender for Office 365 (Safe Attachments detonation) into a per-family table: total detections, distinct files, affected locations (file owner or site) and when the family was last seen.\r\nFileMaliciousContentInfo\r\n| where tostring(DetectionMethods) contains \"detonation\"\r\n| extend Owner = iff(isnotempty(FileOwnerUpn), FileOwnerUpn, strcat(\"Site: \", tostring(split(FolderPath, \"/\")[4])))\r\n| summarize ['Files']=count(), ['Distinct Files']=dcount(SHA256), ['Affected Locations']=dcount(Owner), ['Last Seen']=max(Timestamp) by ThreatNames\r\n| sort by ['Files'] desc\r\n| project ['Threat Name']=ThreatNames, ['Files'], ['Distinct Files'], ['Affected Locations'], ['Last Seen']", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "tileSettings": { + "showBorder": false, + "titleContent": { + "columnMatch": "RawinfoVirusInfo", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "count_", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "graphSettings": { + "type": 0, + "topContent": { + "columnMatch": "RawinfoVirusInfo", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "count_", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "chartSettings": { + "xAxis": "RawinfoVirusInfo", + "createOtherGroup": 15 + }, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Files", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "filemal - family MDO table", + "id": "c3fbb1c9-be67-43b9-9a32-7fb265a84ffc" + }, + { + "type": 1, + "content": { + "json": "### Malware Family Analysis - SharePoint AV\r\n**Provides a breakdown of malware detections in files across SharePoint, OneDrive, and Teams caught by the built-in SharePoint antivirus (Antimalware engine). The table lists each malware family with total detections, distinct files, affected locations and when it was last seen, helping identify prevalent threats and their spread across collaboration environments.**" + }, + "customWidth": "100", + "name": "filemal - family SPO-AV heading", + "id": "331a8361-6e81-4615-b33a-97ebb3e31529" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query summarizes File malware detections by the built-in SharePoint antivirus (Antimalware engine) into a per-family table: total detections, distinct files, affected locations (file owner or site) and when the family was last seen.\r\nFileMaliciousContentInfo\r\n| where tostring(DetectionMethods) contains \"Antimalware engine\"\r\n| extend Owner = iff(isnotempty(FileOwnerUpn), FileOwnerUpn, strcat(\"Site: \", tostring(split(FolderPath, \"/\")[4])))\r\n| summarize ['Files']=count(), ['Distinct Files']=dcount(SHA256), ['Affected Locations']=dcount(Owner), ['Last Seen']=max(Timestamp) by ThreatNames\r\n| sort by ['Files'] desc\r\n| project ['Threat Name']=ThreatNames, ['Files'], ['Distinct Files'], ['Affected Locations'], ['Last Seen']", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "chartSettings": { + "xAxis": "RawinfoVirusInfo", + "createOtherGroup": 10 + }, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Files", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "filemal - family SPO-AV table", + "id": "bbcdccd9-eedb-476a-a0e7-8504f8770229" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by Location
\r\n\r\n**Displays the number of malware detections grouped by specific SharePoint sites or OneDrive locations. Helps identify which sites have the highest volume of detected threats for targeted remediation and security hardening.**" + }, + "customWidth": "50", + "name": "filemal - by-location heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "c5668d6e-7c0e-4ce3-9509-ca93dda3efad" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by Application
\r\n\r\n**Summarizes malware detections across Microsoft collaboration apps, including SharePoint, OneDrive, and Teams. Helps identify which applications experience the highest volume of detected threats for targeted security measures.**" + }, + "customWidth": "50", + "name": "filemal - by-application heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "07e64ca9-04a2-44b2-a044-e927bc73ef1b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists total Malware detections of files on SharePoint, OneDrive and Teams by the location (site or personal path) where the file resides.\r\nFileMaliciousContentInfo\r\n| extend ['Site / Location'] = tostring(split(FolderPath, '/')[4])\r\n| summarize ['Detections'] = count() by ['Site / Location']\r\n| sort by ['Detections'] desc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "filemal - by-location table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3ce3ea65-a4df-450f-871c-8956d59818a9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total Malware detections of files located on SharePoint, OneDrive and Teams summarizing the data by the Microsoft collaboration application (workload).\r\nFileMaliciousContentInfo\r\n| summarize count() by Workload\r\n| sort by count_ desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "filemal - by-application pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "003afc8e-0403-4aa9-9084-a3c2e435216a" + }, + { + "type": 1, + "content": { + "json": "### Top File Owners Holding Malware\r\n**Lists the users (or the SharePoint/Teams site, when a file has no individual owner) whose files in SharePoint, OneDrive or Teams were flagged as malware, with the count of malicious files, distinct files, affected workloads and sample threat names. Helps pinpoint the accounts and collaboration locations most affected by malicious content for targeted remediation.**" + }, + "customWidth": "100", + "name": "filemal - top-owners heading", + "id": "c2f8d3b5-0a4e-4b7c-9d23-8e6f0a1b2c34" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top file owners (or the SharePoint/Teams site, when a file has no user owner) whose SharePoint/OneDrive/Teams files were flagged as malware, with distinct files, workloads and sample threat names.\r\nFileMaliciousContentInfo\r\n| extend Owner = iff(isnotempty(FileOwnerUpn), FileOwnerUpn, strcat(\"Site: \", tostring(split(FolderPath, \"/\")[4])))\r\n| summarize ['Malicious Files'] = count(),\n ['Distinct Files'] = dcount(SHA256),\n ['Workloads'] = make_set(Workload, 3),\n ['Sample Threats'] = make_set_if(ThreatNames, isnotempty(ThreatNames), 5),\n ['Last Seen'] = max(Timestamp)\n by ['Owner']=Owner\n| top 20 by ['Malicious Files']", + "size": 0, + "title": "Top File Owners Holding Malware", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Malicious Files", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Distinct Files", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "filemal - top-owners table", + "id": "36d9a683-9f9d-4a70-84d9-ec351542f827" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "9" + }, + "name": "filemal - group", + "styleSettings": { + "showBorder": true + }, + "id": "50886cd9-87bf-4a84-bd80-d7f44441b3f7" + }, + { + "type": 1, + "content": { + "json": "# Post-Delivery & Quarantine Insights\r\n\r\n---\r\nThis tab covers what happens to threats **after delivery**: Zero-hour Auto Purge (ZAP) remediation of malicious messages already in mailboxes, and quarantine management - what is held, released, and by whom. Together they show how effectively post-delivery response contains threats that reached the inbox." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "11" + }, + "name": "postdelivery - tab description", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "93371620-d968-4987-bddd-6c9b9e5a0344" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Post Delivery Protection offered by ZAP\r\n
\r\n\r\nThis section provides insights into Microsoft Defender for Office 365's post-delivery protection capabilities through Zero-Hour Auto Purge (ZAP). ZAP is a critical security feature that continuously monitors delivered emails and automatically removes messages that are later identified as malicious. These visuals help track ZAP effectiveness, response times, and remediation patterns.

**Recommended action:** High post-delivery ZAP volume means threats are reaching inboxes before being caught - review pre-delivery filtering and detection latency." + }, + "name": "postdelivery - section header", + "id": "b22ee5f1-a2dc-4509-92a3-1dbcad3a6ee7" + }, + { + "type": 1, + "content": { + "json": "### ZAP Post-Delivery Actions (per {Granularity})
\r\n\r\n**Shows the count (per {Granularity}) of emails that were remediated post-delivery by Zero-Hour Auto Purge (ZAP). Helps track how often threats are detected and removed after reaching user mailboxes.**" + }, + "customWidth": "50", + "name": "postdelivery - zap-actions heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "af1aa73f-d952-4827-bcc9-b97a19016829" + }, + { + "type": 1, + "content": { + "json": "### ZAP Actions by Detection Type (per {Granularity})
\r\n\r\n**Visualizes the count (per {Granularity}) of post-delivery remediation actions performed by Zero-Hour Auto Purge (ZAP), broken down by detection type (Spam ZAP, Phish ZAP, Malware ZAP). Helps track which threat categories are most frequently remediated after delivery.**" + }, + "customWidth": "50", + "name": "postdelivery - by-detection-type heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8eb38cb1-4e2d-435a-81be-e661c9b89ff4" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of emails that had a post delivery action from zero-hour auto purge.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailPostDeliveryEvents \r\n| where ActionType has \"ZAP\"\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Zapped Emails'] = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Zapped Emails", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "postdelivery - zap-actions trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "dd60fd71-4e14-4b38-ad22-39f1e3e3f55a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of emails that had a post delivery action from zero-hour auto purge, summarizing by phish,spam or malware detection action\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailPostDeliveryEvents\r\n| where ActionType has \"ZAP\"\r\n| summarize [\"Spam ZAP\"]=countif(ActionType has 'Spam ZAP'), [\"Phish ZAP\"]=countif(ActionType has 'Phish ZAP'), [\"Malware ZAP\"]=countif(ActionType has 'Malware ZAP') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, [\"Spam ZAP\"]=coalesce([\"Spam ZAP\"],0), [\"Phish ZAP\"]=coalesce([\"Phish ZAP\"],0), [\"Malware ZAP\"]=coalesce([\"Malware ZAP\"],0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "postdelivery - by-detection-type trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "511f4a43-9f56-48ad-a644-b72722af82d7" + }, + { + "type": 1, + "content": { + "json": "### ZAP Remediation by Destination
\r\n\r\n**This visual shows where ZAP moves malicious emails during remediation. Post-delivery actions can send emails to different locations: Quarantine (isolated for admin review), Deleted Items (soft delete), Junk Email folder, or back to Inbox (for false positive corrections). Understanding these patterns helps evaluate ZAP policy configurations and ensures malicious content is properly isolated from users.**" + }, + "name": "postdelivery - by-destination heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "dc7b9b6c-36fb-4ae4-a3e8-ff11da681c97" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails that had a post delivery action, summarizing the data daily by the final location as a result of the action\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailPostDeliveryEvents\r\n| where ActionType contains \"ZAP\"\r\n| summarize Quarantine=countif(DeliveryLocation has 'Quarantine'), ['Deleted Items']=countif(DeliveryLocation has 'Delete'), Junk=countif(DeliveryLocation has 'Junk'), Inbox=countif(DeliveryLocation has 'Inbox') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, Quarantine=coalesce(Quarantine,0), ['Deleted Items']=coalesce(['Deleted Items'],0), Junk=coalesce(Junk,0), Inbox=coalesce(Inbox,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "name": "postdelivery - by-destination trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "cbb737ef-1c7e-4b3e-af26-a553fe6147c9" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "11" + }, + "name": "postdelivery - group", + "styleSettings": { + "showBorder": true + }, + "id": "e436ecee-8886-4179-a578-9e4a42e75b9e" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Quarantine Management and Insights\r\n
\r\n\r\nThis section provides comprehensive insights into quarantine operations, including release patterns, detection methods, and threat categorization. It helps security teams understand what types of threats are being quarantined and monitor quarantine release activity to identify potential false positives or security policy effectiveness.

**Recommended action:** Investigate high release rates - they indicate false positives or risky user releases; review quarantine policies and release permissions." + }, + "name": "quarantine - section header", + "id": "c4862977-6670-4716-8109-252a361d7478" + }, + { + "type": 1, + "content": { + "json": "### Quarantine Release Trend
\r\n\r\n**This visual displays the per-{Granularity} trend of emails released from quarantine by administrators. Monitoring this metric helps identify patterns in quarantine management and potential areas where policy adjustments may be needed to reduce unnecessary quarantines.**" + }, + "name": "quarantine - release-trend heading", + "id": "8526a5e0-c6a4-44e3-b00a-5e135374f58e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of emails released from quarantine\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailPostDeliveryEvents\r\n| where ActionTrigger has \"AdminAction\" and Action has 'Quarantine release'\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Quarantine Releases'] = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Quarantine Releases", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - release trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3625d1f1-f34a-4cbf-a78f-eb2e5506bad4" + }, + { + "type": 1, + "content": { + "json": "### Quarantine Release Percentage
\r\n\r\n**Calculates the percentage of quarantined emails that were successfully released compared to the total quarantined messages. This metric helps measure engagement with quarantine and assess the effectiveness of quarantine policies.**" + }, + "customWidth": "40", + "name": "quarantine - release-pct heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e3a9502c-9030-4621-b248-55cdf69f81ae" + }, + { + "type": 1, + "content": { + "json": "### Quarantine Release Analysis by Detection Type
\r\n\r\n**For each detection technology, this shows the share of its quarantined emails that were later released from quarantine (Release % = released / quarantined). A high release rate flags a detector that may be over-flagging legitimate mail - a strong candidate for policy or rule tuning. The Released count shows the volume behind each rate.**" + }, + "customWidth": "60", + "name": "quarantine - release-by-detection heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "976fc90f-bf46-4315-b05e-4e501b37b869" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the percentage of emails released from quarantine out of the total ammount of quarantined emails\r\nlet Quarantine_Releases = toscalar(EmailPostDeliveryEvents\r\n| where Action == \"Quarantine release\"\r\n| join kind=leftouter (EmailEvents | where DeliveryLocation == \"Quarantine\") on NetworkMessageId\r\n| summarize count());\r\nlet Quarantined_Mailflow = toscalar(EmailEvents | where DeliveryLocation == \"Quarantine\"\r\n| summarize count());\r\nprint\r\nQuarantine_Releases = toreal(Quarantine_Releases),\r\nQuarantined_Mailflow = toreal(Quarantined_Mailflow),\r\nRelease_Percentage = abs(round(((toreal(Quarantine_Releases)/toreal(Quarantined_Mailflow))*100),2))", + "size": 0, + "showAnalytics": true, + "title": " ", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "tileSettings": { + "titleContent": { + "columnMatch": "Release_Percentage", + "formatter": 12, + "formatOptions": { + "palette": "none" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + "showBorder": true, + "sortCriteriaField": "Release_Percentage", + "size": "auto" + }, + "statSettings": { + "valueField": "Release_Percentage", + "valueAggregation": "None", + "colorSettings": { + "type": "thresholds", + "mode": "foreground", + "heatmapPalette": "greenRed", + "thresholdsGrid": [ + { + "operator": "<", + "thresholdValue": "5", + "representation": "green" + }, + { + "operator": ">", + "thresholdValue": "5", + "representation": "redDark" + } + ] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "numberFormatSettings": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "tagText": "Quarantine Release Percentage", + "valueFontStyle": "mega", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "40", + "name": "quarantine - release-pct stat", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "64e157ce-2f6a-423f-9ce5-eade8b6f41d5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Per detection technology: the share of its quarantined emails that were later released from quarantine.\r\n//Release % = released / quarantined for that detection technology - a high rate flags a detector that may be over-flagging legitimate mail (potential false positives). Detectors with fewer than 10 quarantined emails are excluded so the rate is statistically meaningful.\r\nEmailEvents\r\n| where DeliveryLocation == \"Quarantine\"\r\n| extend MDO_detection = parse_json(DetectionMethods)\r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0]))\r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\")\r\n| where FirstSubcategory contains \"Malware\" or FirstSubcategory contains \"Phish\" or FirstSubcategory contains \"Spam\"\r\n| join kind=leftouter (\r\n EmailPostDeliveryEvents\r\n | where Action == \"Quarantine release\"\r\n | distinct NetworkMessageId\r\n | extend ReleasedFlag = \"yes\"\r\n ) on NetworkMessageId\r\n| summarize Quarantined = dcount(NetworkMessageId), Released = dcountif(NetworkMessageId, ReleasedFlag == \"yes\") by FirstSubcategory\r\n| where Quarantined >= 10 and Released > 0\r\n| extend ReleaseRate = round(Released * 100.0 / Quarantined, 2)\r\n| project ['Detection Type']=FirstSubcategory, ['Quarantined Emails']=Quarantined, ['Released']=Released, ['Release %']=ReleaseRate\r\n| order by ['Release %'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Quarantined Emails", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Released", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Release %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "60", + "name": "quarantine - release-by-detection pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "9a6d21b7-7542-4ae5-8f3f-b18474b52a20" + }, + { + "type": 1, + "content": { + "json": "### Malware Email Quarantine Analysis
\r\n\r\n**These visuals break down quarantined malware emails by their specific detection methods. Microsoft Defender for Office 365 employs multiple malware detection techniques including file detonation, file reputation analysis, and advanced filters. Understanding which detection methods are most frequently triggered helps optimize anti-malware policies and identify emerging malware tactics.
The line chart shows per-{Granularity} trends across all malware detection methods, while the table provides an overall distribution of detection reasons.**" + }, + "name": "quarantine - malware heading", + "id": "59f84161-a010-44c2-aec1-b72ed98ccdff" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of malware emails that are quarantined, summarized daily by the detection method\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has \"Malware\" and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Details = parse_json(DetectionMethods).Malware to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - malware trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a54a8daf-0be2-4c0e-a8d7-4ff0e0879fd2" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of malware emails that are quarantined, summarized by the detection method\r\n//(QA 2026-07-14) mv-expand over DetectionMethods.Malware (matching the sibling line chart) so each slice is a clean single method name instead of a bracketed JSON array.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has 'Malware' and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Malware = parse_json(DetectionMethods).Malware to typeof(string)\r\n| where isnotempty(Malware)\r\n| summarize count() by Malware\r\n| sort by count_ desc\r\n| project ['Detection Technology']=Malware, ['Detections']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - malware table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b5d0d022-cf41-47e5-ae06-cf2176b47758" + }, + { + "type": 1, + "content": { + "json": "### Phishing Email Quarantine Analysis
\r\n\r\n**These visuals break down quarantined phishing emails by their specific detection methods. Microsoft Defender for Office 365 employs multiple phishing detection techniques including impersonation protection, URL detonation, spoof detection, and advanced filters. Understanding which detection methods are most frequently triggered helps optimize anti-phishing policies and identify emerging phishing tactics.
The line chart shows per-{Granularity} trends across all phishing detection methods, while the table provides an overall distribution of detection reasons.**" + }, + "name": "quarantine - phish heading", + "id": "aca50104-cb68-4a8f-82ee-ea8eee25fe14" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of phish emails that are quarantined, summarized daily by the detection method\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has \"Phish\" and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - phish trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "57151360-0577-45ce-8fc6-10a3790865ce" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of phish emails that are quarantined, summarized by the detection method\r\n//(QA 2026-07-14) mv-expand over DetectionMethods.Phish (matching the sibling line chart) so each slice is a clean single method name instead of a bracketed JSON array.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has 'Phish' and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Phish = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Phish)\r\n| summarize count() by Phish\r\n| sort by count_ desc\r\n| project ['Detection Technology']=Phish, ['Detections']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - phish pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "df78c64b-76f6-4980-80df-d0d432e780a5" + }, + { + "type": 1, + "content": { + "json": "### Spam Email Quarantine Analysis
\r\n\r\n**These visuals provide detailed insights into quarantined spam emails categorized by detection methods. Spam detection technologies include advanced filters, general filters, bulk email filtering, reputation-based systems (IP, domain, URL), and mixed analysis detection. Analyzing spam quarantine patterns helps fine-tune spam filtering policies to balance security with user productivity and reduce false positives.
The line chart displays per-{Granularity} trends for each spam detection method, while the table shows the overall distribution.**" + }, + "name": "quarantine - spam heading", + "id": "e131910f-0233-474a-a9b8-9f70a49246cf" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of spam emails that are quarantined, summarized daily by the detection method\r\nlet gran = {Granularity};\r\nlet baseQuery = EmailEvents\r\n| where DetectionMethods has \"Spam\" and DeliveryLocation == \"Quarantine\";\r\nlet agg = materialize(baseQuery\r\n| mv-expand Details = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - spam trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5762bcc7-bbda-4a3d-91cf-de18fbdd2775" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of spam emails that are quarantined, summarized by the detection method\r\n//(QA 2026-07-14) mv-expand over DetectionMethods.Spam (matching the sibling line chart) so each slice is a clean single method name instead of a bracketed JSON array.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has 'Spam' and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Spam = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Spam)\r\n| summarize count() by Spam\r\n| sort by count_ desc\r\n| project ['Detection Technology']=Spam, ['Detections']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - spam pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "2995f55b-17f9-458b-8630-e0370d14522a" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "11" + }, + "name": "quarantine - group", + "id": "430294af-c68f-4427-8b55-d552a3d89d42", + "styleSettings": { + "showBorder": true + } + }, + { + "type": 1, + "content": { + "json": "# Security Operations Center (SOC) Insights \r\n\r\n---\r\n\r\nThis tab provides a view for security operations. Combines incident response metrics with investigation insights to evaluate the effectiveness of both automated systems and manual interventions." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "13" + }, + "name": "soc - tab description", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "fd65243c-514c-4813-978f-fb908226d049" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Security Incident Response Metrics\r\n
\r\n\r\n**Operational efficiency insights.** Tracks incident volume, resolution speed, automation efficacy, and classification accuracy to evaluate SOC performance.

**Recommended action:** Track mean time to close by severity against your SLA and investigate any severity trending upward." + }, + "name": "soc - incident-metrics section header", + "id": "f92c3e24-3e0f-4f4c-8ee9-3ec60832f7b1" + }, + { + "type": 1, + "content": { + "json": "### Email Security Incidents
\r\n\r\n**These visuals display the per-{Granularity} trend of email-related security incidents, as well as the proportion of email incidents compared to the total number of incidents in Defender.**" + }, + "name": "soc - email-incidents heading", + "id": "c1cf6796-6071-4d2e-bf2c-c5e8d2a99a12" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "customWidth": "75", + "name": "soc - email-incidents trend", + "id": "e23cfcda-1017-4fd0-ac71-8a861c450f71" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "customWidth": "25", + "name": "soc - incident-category pie", + "id": "baae2150-1b04-43b4-9713-48fd3cc6247f" + }, + { + "type": 1, + "content": { + "json": "### Average Incident Time To Close (minutes)\r\n**This visual displays the average time, in minutes, to close email-related security incidents (per {Granularity}), split by severity, so you can see how resolution speed changes over time. Reference SLA targets: High 60, Medium 120, Low 240, Informational 480 minutes.**" + }, + "name": "soc - time-to-close heading", + "id": "e23ccc6c-b0f0-407b-8e01-d8b69c40a745" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "name": "soc - sla-by-severity trend", + "id": "3f7d1f17-8d2f-4a1b-a97e-17973812ca6f" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "### Closed Incident Classification (True Positive vs False Positive)\r\n\r\nThis visual shows the distribution of closed email-related incidents classified as True Positive versus False Positive. It helps assess detection accuracy and provides insight into validation trends." + }, + "customWidth": "33.3", + "name": "soc - classification heading", + "styleSettings": { + "margin": "10px" + }, + "id": "48db10ce-8246-4f5e-8b68-f618d9c7f77c" + }, + { + "type": 1, + "content": { + "json": "### True Positive Incident Classification Rate\r\n\r\nThis visual displays the percentage of email-related incidents confirmed as True Positive. It offers a clear measure of classification accuracy and highlights changes in detection effectiveness over time." + }, + "customWidth": "33.3", + "name": "soc - tp-rate heading", + "styleSettings": { + "margin": "10px" + }, + "id": "34a84dbf-609a-407f-afef-f1592eb4a92b" + }, + { + "type": 1, + "content": { + "json": "### Incidents Automated vs Manual Closure\r\n\r\nThis visual illustrates the proportion of email-related incidents closed automatically versus manually. It provides visibility into operational efficiency and the impact of automation on incident resolution.\r\n
⚠️ *You will have to review the underlying query and add any automation system specific to your organization.*" + }, + "customWidth": "33.3", + "name": "soc - auto-vs-manual-closure heading", + "styleSettings": { + "margin": "10px" + }, + "id": "a1fd9136-7a12-4d80-b3e1-e2704a84f734" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "customWidth": "33.3", + "name": "soc - classification pie", + "styleSettings": { + "margin": "10px" + }, + "id": "cfa5b7c5-50cc-4b3b-8bba-1a93c57bff43" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "customWidth": "33.3", + "name": "soc - tp-rate stat", + "styleSettings": { + "margin": "10px" + }, + "id": "eca235aa-38aa-46dd-a569-74dd8f83b2f0" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "customWidth": "33.3", + "name": "soc - closure pie", + "styleSettings": { + "margin": "10px" + }, + "id": "a4bc160f-1ba6-4779-86cd-ef44422f1e29" + } + ] + }, + "name": "soc - incident-insights group", + "id": "3083ac4d-0bdd-4db7-a5f0-0d41cb67a4eb" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "13" + }, + "name": "soc - incident-metrics group", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "18ff8970-e5f6-4c51-918a-aa693a45d18f" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Investigation & Response Actions\r\n
\r\n\r\n**Remediation efficacy analysis.** Compares automated (AIR) and manual admin actions to evaluate response times and investigation outcomes.\r\n

**Recommended action:** Reduce AIR pending-action latency by reviewing why approvals take long, and increase automation where it is safe to do so." + }, + "name": "soc - air section header", + "id": "5e0b06c8-7774-4eb4-8b7f-572b3732de84" + }, + { + "type": 1, + "content": { + "json": "### Automated Investigation and Response (AIR) Actions (per {Granularity})\r\n\r\nThis visual shows the per-{Granularity} trend of Automated Investigation and Response (AIR) actions, including the number of successful and failed attempts (because of prior remediation)." + }, + "customWidth": "100", + "name": "soc - air-actions heading", + "styleSettings": { + "margin": "10px" + }, + "id": "05f14dec-e76c-413c-83a0-31a05dce65e7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query attempts to show AIR Efficiency Over Time by displaying the number of successes and failures over time\r\nEmailPostDeliveryEvents\r\n| where ActionType =~ \"Automated Remediation\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Count = count() by bin(Timestamp, {Granularity}), ActionResult", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "graphSettings": { + "type": 0, + "topContent": { + "columnMatch": "AlertId", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Count", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "soc - air-efficiency trend", + "styleSettings": { + "margin": "10px" + }, + "id": "ae2a1850-5b7e-49f7-bac4-d888053ab49b" + }, + { + "type": 1, + "content": { + "json": "### Automated Investigation and Response (AIR) Response Time After Email Delivery (per {Granularity})\r\n\r\nThis visual displays the average (per {Granularity}), 80th percentile (p80), 90th percentile (p90) and 99th percentile (p99) time needed, measured in minutes, from email delivery to AIR action. It serves as a SOC metric to monitor responsiveness (security team members reviewing and manually approving AIR Pending Actions) and identify potential latency in automated incident handling. If the latency is high focus on reviewing why reviwing AIR Pending Actions takes longer time for admins and consider auto-aproval of URL, Files and Email clusters. \r\n" + }, + "customWidth": "100", + "name": "soc - air-response-time heading", + "styleSettings": { + "margin": "10px" + }, + "id": "98c66d9e-efdf-40fc-b8b0-be35d7fd97a9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// SOC metric: Daily average/p75 delay (in minutes) from email delivery to AIR action\r\nlet deliveries = EmailEvents\r\n | where DeliveryAction == \"Delivered\"// delivered emails\r\n | extend MsgKey = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n | summarize FirstDelivery = min(Timestamp) by MsgKey, Threat = tostring(ThreatTypes);\r\nlet remediations = EmailPostDeliveryEvents\r\n | where ActionType =~ \"Automated Remediation\"// automated remediation events\r\n | extend MsgKey = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n | summarize FirstRemediation = min(Timestamp) by MsgKey;\r\ndeliveries\r\n| join kind=inner remediations on MsgKey\r\n| extend DelayMinutes = datetime_diff(\"minute\", FirstRemediation, FirstDelivery)\r\n| where DelayMinutes >= 0\r\n| summarize ['Avg (min)'] = avg(DelayMinutes),\r\n ['P80 (min)'] = percentile(DelayMinutes, 80),\r\n ['P90 (min)'] = percentile(DelayMinutes, 90),\r\n ['P99 (min)'] = percentile(DelayMinutes, 99),\r\n CountEmails = count()\r\n by bin(FirstRemediation, 1d) ", + "size": 0, + "aggregation": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "gridSettings": { + "sortBy": [ + { + "itemKey": "FirstRemediation", + "sortOrder": 1 + } + ] + }, + "sortBy": [ + { + "itemKey": "FirstRemediation", + "sortOrder": 1 + } + ], + "chartSettings": { + "xAxis": "FirstRemediation", + "yAxis": [ + "P99 (min)", + "P90 (min)", + "P80 (min)", + "Avg (min)" + ], + "showLegend": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "soc - air-latency area", + "styleSettings": { + "margin": "10px" + }, + "id": "900383f1-6443-4d50-b15d-26e4ac11b255" + }, + { + "type": 1, + "content": { + "json": "### Automated Investigation and Response (AIR) Investigation Results Trend\r\n\r\nThis visual displays the per-{Granularity} trend of AIR investigation outcomes, categorized as **Threat Detected** or **Clean**. It helps track the effectiveness of automated investigations over time and highlights patterns in threat detection." + }, + "customWidth": "67", + "name": "soc - air-outcomes heading", + "styleSettings": { + "margin": "10px" + }, + "id": "d1cabfbe-6040-4b6e-9ce5-f48e9973dfc9" + }, + { + "type": 1, + "content": { + "json": "### Investigation Actions Taken: Automated Investigation and Response (AIR) vs Manual (Human)\r\n\r\nThis visual shows whether actions taken after an Automated Investigation and Response (AIR) required manual approval by an administrator or were executed automatically. It provides insight into the level of automation versus human intervention in post-investigation remediation." + }, + "customWidth": "33", + "name": "soc - air-auto-vs-manual heading", + "styleSettings": { + "margin": "10px" + }, + "id": "2f98514b-0172-4c4e-ba25-9a5e4138c570" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// AIR investigation outcomes by day: ThreatDetected vs. Clean\r\n\r\n// Step 1: Deduplicate automated remediation events by message and recipient\r\nlet AutoRemediations = \r\n EmailPostDeliveryEvents\r\n | where ActionType == \"Automated Remediation\"\r\n | summarize arg_max(Timestamp, ActionResult) by NetworkMessageId, RecipientEmailAddress\r\n | project NetworkMessageId, RecipientEmailAddress, Timestamp;\r\n\r\n// Step 2: Derive threat verdicts using AlertEvidence\r\nlet EvidenceVerdicts =\r\n AlertEvidence\r\n | where EntityType in (\"MailMessage\", \"MailCluster\")\r\n | extend extra = todynamic(AdditionalFields)\r\n // If this is a mail cluster, use provided NetworkMessageIds array; otherwise wrap NetworkMessageId as a single-item array\r\n | extend networkIds = iff(\r\n isnull(extra.NetworkMessageIds) or array_length(extra.NetworkMessageIds) == 0,\r\n pack_array(NetworkMessageId), // create a single-element array using pack_array\r\n extra.NetworkMessageIds // use the array as-is if it exists\r\n )\r\n | mv-expand nmID = networkIds // expand to individual message IDs\r\n // Derive verdict from LastVerdict, ThreatAnalysisSummary, and ThreatIntelligence\r\n | extend \r\n lastVerdict = tolower(tostring(extra.LastVerdict)),\r\n threatAIList = extra.ThreatAnalysisSummary,\r\n threatInt = extra.ThreatIntelligence\r\n | extend verdictFromAnalysis = iff(array_length(threatAIList) > 0, tolower(tostring(threatAIList[0].Verdict)), \"\"),\r\n verdictTI = iff(array_length(threatInt) > 0, \"malicious\", \"\") // any item in ThreatIntelligence indicates malicious\r\n // Mark as threat-detected if verdict is malicious/suspicious or threat evidence is present\r\n | extend ThreatDetectedFlag = \r\n case(\r\n lastVerdict in (\"malicious\",\"suspicious\") or verdictFromAnalysis in (\"malicious\",\"suspicious\")\r\n or verdictTI == \"malicious\",\r\n true,\r\n false\r\n )\r\n // Weight mail clusters by MailCount; default to 1 for single messages\r\n | extend MailCountInt = toint(extra.MailCount)\r\n | extend Weight = iff(EntityType == \"MailCluster\", \r\n coalesce(MailCountInt, 1), // default to 1 if MailCount is missing\r\n 1)\r\n | summarize IsThreatDetected = any(ThreatDetectedFlag), \r\n WeightSum = sum(Weight) \r\n by nmID = tostring(nmID);\r\n\r\n// Step 3: Join remediation events with verdicts and aggregate by day\r\nAutoRemediations\r\n| join kind=leftouter EvidenceVerdicts on $left.NetworkMessageId == $right.nmID\r\n| extend isThreat = coalesce(IsThreatDetected, false), \r\n effectiveWeight= coalesce(WeightSum, 1)\r\n| extend InvestigationOutcome = iif(isThreat, \"Threat Detected\", \"Clean\")\r\n| summarize PreventionCount = sum(effectiveWeight) by Day = bin(Timestamp, {Granularity}), InvestigationOutcome\r\n| order by Day asc, InvestigationOutcome asc", + "size": 0, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "67", + "name": "soc - air-outcomes trend", + "styleSettings": { + "margin": "10px" + }, + "id": "18552ccb-d8d4-45c4-a3cf-072203df9325" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows if the action taken after an Automated Investigation required manual approval by and admin or was automatically taken\r\nEmailPostDeliveryEvents\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ActionType == \"Automated Remediation\"\r\n| summarize count() by ActionTrigger", + "size": 3, + "showAnalytics": true, + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "soc - air-auto-vs-manual pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "03bc6e3c-05de-426d-91d8-b48a36b4ea74" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "### Post-Delivery Actions by Admin\r\n\r\nThis visual displays the number (per {Granularity}) of emails where an administrator performed a post-delivery action. Actions are summarized by type, including **Soft Delete**, **Hard Delete**, **Moved to Junk Folder**, **Moved to Inbox**, and **Quarantine Release**, providing insight into manual intervention trends after email delivery." + }, + "name": "soc - post-delivery-by-admin heading", + "styleSettings": { + "margin": "10px" + }, + "id": "a0961ca9-da58-49c4-9a1c-873c5569bed9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of emails that had an admin post delivery action, summarizing the data by action type\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailPostDeliveryEvents\r\n| where ActionTrigger has \"AdminAction\"\r\n| summarize [\"Soft Delete\"]=countif(Action has 'Soft Delete'), [\"Hard Delete\"]=countif(Action has 'Hard Delete'), [\"Moved to junk folder\"]=countif(Action has 'Moved to junk folder'), [\"Moved to inbox\"]=countif(Action has 'Moved to inbox'), [\"Quarantine release\"]=countif(Action has 'Quarantine release') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, [\"Soft Delete\"]=coalesce([\"Soft Delete\"],0), [\"Hard Delete\"]=coalesce([\"Hard Delete\"],0), [\"Moved to junk folder\"]=coalesce([\"Moved to junk folder\"],0), [\"Moved to inbox\"]=coalesce([\"Moved to inbox\"],0), [\"Quarantine release\"]=coalesce([\"Quarantine release\"],0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "name": "soc - post-delivery-by-admin trend", + "styleSettings": { + "margin": "10px" + }, + "id": "d2ea8eac-a3db-46b0-bcb4-3abbb95ba4ad" + } + ] + }, + "customWidth": "100", + "name": "soc - post-delivery group", + "id": "ebca14d5-954d-4e35-a225-cb0f8a3ea81b" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "13" + }, + "name": "soc - air group", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "0a05394d-f813-4408-ac4d-8f481ae34c0b" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Top Malicious Email Campaigns (Clustered)\r\n
\r\n\r\n**Groups malicious inbound emails into campaigns (attack waves) using the Email Cluster ID assigned by Microsoft Defender for Office 365, showing one row per campaign with the message count, distinct recipients, sender domains, threat mix and sample subjects. Helps the SOC understand the scale and shape of coordinated attacks rather than viewing individual messages in isolation.**

**Recommended action:** Pivot on the top campaign clusters to hunt related messages and consider blocking shared sender infrastructure." + }, + "name": "soc - campaigns heading", + "id": "d3a9e4c6-1b5f-4c8d-ae34-9f7a1b2c3d45" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Largest malicious inbound email campaigns clustered by EmailClusterId - one row per attack wave (messages, recipients, URL clicks, sender domains, threat mix, sample subjects).\r\n//URL Clicks = clicks by recipients on URLs within the campaign's messages (UrlClickEvents joined via NetworkMessageId).\r\nlet clicksByCluster = UrlClickEvents\r\n| join kind=inner (EmailEvents | where EmailClusterId > 0 | distinct NetworkMessageId, EmailClusterId) on NetworkMessageId\r\n| summarize UrlClicks = count() by EmailClusterId;\r\nlet qrClusters = EmailUrlInfo\r\n| where UrlLocation == \"QRCode\"\r\n| join kind=inner (EmailEvents | where EmailClusterId > 0 | distinct NetworkMessageId, EmailClusterId) on NetworkMessageId\r\n| summarize QrMessages = dcount(NetworkMessageId) by EmailClusterId;\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and EmailClusterId > 0\r\n| where OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Messages = count(),\r\n Recipients = dcount(RecipientEmailAddress),\r\n SenderDomains = dcount(SenderFromDomain),\r\n SampleSenderDomains = make_set(SenderFromDomain, 5),\r\n ThreatTypesRaw = make_set(ThreatTypes, 50),\r\n SampleSubjects = make_set(Subject, 5),\r\n FirstSeen = min(Timestamp),\r\n LastSeen = max(Timestamp)\r\n by EmailClusterId\r\n| join kind=leftouter (clicksByCluster) on EmailClusterId\r\n| extend UrlClicks = coalesce(UrlClicks, 0)\r\n| join kind=leftouter (qrClusters) on EmailClusterId\r\n| extend ['QR Code'] = iif(coalesce(QrMessages, 0) > 0, \"QR code\", \"\")\r\n| extend ThreatMix = array_sort_asc(set_union(split(strcat_array(ThreatTypesRaw, \", \"), \", \"), dynamic([])))\r\n| top 20 by Messages\r\n| project ['Email Cluster ID']=EmailClusterId, ['Messages']=Messages, ['Recipients']=Recipients, ['URL Clicks']=UrlClicks, ['Sender Domains']=SenderDomains, ['Sample Sender Domains']=SampleSenderDomains, ['Threat Mix']=ThreatMix, ['QR Code']=['QR Code'], ['Sample Subjects']=SampleSubjects, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", + "size": 0, + "title": "", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Recipients", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "URL Clicks", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "soc - campaigns table", + "id": "a2a391e1-0e26-4e0e-a8d3-26e3c7132079" + }, + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Most-Clicked Email Campaigns (Recipient Engagement)\r\n
\r\n\r\n**Ranks malicious inbound campaigns by recipient URL clicks, surfacing the attack waves that reached a mailbox and drew engagement regardless of raw message volume. The highest-volume campaigns are usually quarantined before delivery, so the clusters that draw clicks are often smaller, targeted waves. A non-zero URL Clicks count means a recipient opened a URL within the campaign's messages. Because attackers often mix legitimate URLs with malicious ones to build credibility, and a per-URL threat verdict is not available here, treat these as clicks on potentially malicious URLs that warrant review rather than confirmed malicious clicks.**

**Recommended action:** Focus on these clusters for user follow-up (awareness and, where credentials may be exposed, password reset) and hunt for related messages sharing sender infrastructure." + }, + "name": "soc - mostclicked heading", + "id": "e9e41b47-0434-42e5-8b04-4170ab061b81" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Malicious inbound campaigns ranked by recipient URL clicks - the attack waves that reached a mailbox and drew engagement, regardless of message volume.\r\n//URL Clicks = clicks by recipients on URLs within the campaign's messages (UrlClickEvents joined via NetworkMessageId).\r\nlet clicksByCluster = UrlClickEvents\r\n| join kind=inner (EmailEvents | where EmailClusterId > 0 | distinct NetworkMessageId, EmailClusterId) on NetworkMessageId\r\n| summarize UrlClicks = count() by EmailClusterId;\r\nlet qrClusters = EmailUrlInfo\r\n| where UrlLocation == \"QRCode\"\r\n| join kind=inner (EmailEvents | where EmailClusterId > 0 | distinct NetworkMessageId, EmailClusterId) on NetworkMessageId\r\n| summarize QrMessages = dcount(NetworkMessageId) by EmailClusterId;\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and EmailClusterId > 0\r\n| where OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Messages = count(),\r\n Recipients = dcount(RecipientEmailAddress),\r\n SenderDomains = dcount(SenderFromDomain),\r\n SampleSenderDomains = make_set(SenderFromDomain, 5),\r\n ThreatTypesRaw = make_set(ThreatTypes, 50),\r\n SampleSubjects = make_set(Subject, 5),\r\n FirstSeen = min(Timestamp),\r\n LastSeen = max(Timestamp)\r\n by EmailClusterId\r\n| join kind=inner (clicksByCluster) on EmailClusterId\r\n| where UrlClicks > 0\r\n| join kind=leftouter (qrClusters) on EmailClusterId\r\n| extend ['QR Code'] = iif(coalesce(QrMessages, 0) > 0, \"QR code\", \"\")\r\n| extend ThreatMix = array_sort_asc(set_union(split(strcat_array(ThreatTypesRaw, \", \"), \", \"), dynamic([])))\r\n| top 20 by UrlClicks\r\n| project ['Email Cluster ID']=EmailClusterId, ['URL Clicks']=UrlClicks, ['Messages']=Messages, ['Recipients']=Recipients, ['Sender Domains']=SenderDomains, ['Sample Sender Domains']=SampleSenderDomains, ['Threat Mix']=ThreatMix, ['QR Code']=['QR Code'], ['Sample Subjects']=SampleSubjects, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", + "size": 0, + "title": "", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "URL Clicks", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Recipients", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "soc - mostclicked table", + "id": "1ffe8f97-ad79-47d9-9598-dd73ee54cd8d" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "13" + }, + "name": "soc - campaigns group", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "b8f2a1c4-5d6e-4a7b-9c8d-0e1f2a3b4c5d" + } + ], + "isLocked": false, + "fallbackResourceIds": [], + "$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json", + "contentProvenance": { + "packageId": "azuresentinel.azure-sentinel-solution-microsoftdefenderforo365", + "packageVersion": "3.2.0", + "contentId": "55a394cc-f0af-55c1-8ff2-ec483e3e68a3", + "contentVersion": "3.2.0" + } + } + } + } + } + }, + "packageKind": "Solution", + "packageVersion": "3.2.0", + "packageName": "Microsoft Defender for Office 365", + "packageId": "azuresentinel.azure-sentinel-solution-microsoftdefenderforo365", + "contentSchemaVersion": "3.0.0", + "contentId": "55a394cc-f0af-55c1-8ff2-ec483e3e68a3", + "contentKind": "DefenderWorkbook", + "displayName": "Microsoft Defender for Office 365 Detections and Insights - ISOC", + "contentProductId": "[concat(take(variables('_solutionId'),50),'-','dwb','-', uniqueString(concat(variables('_solutionId'),'-','DefenderWorkbook','-','55a394cc-f0af-55c1-8ff2-ec483e3e68a3','-','3.2.0')))]", + "id": "[concat(take(variables('_solutionId'),50),'-','dwb','-', uniqueString(concat(variables('_solutionId'),'-','DefenderWorkbook','-','55a394cc-f0af-55c1-8ff2-ec483e3e68a3','-','3.2.0')))]", + "version": "3.2.0", + "contentProvenance": { + "packageId": "azuresentinel.azure-sentinel-solution-microsoftdefenderforo365", + "packageVersion": "3.2.0", + "contentId": "55a394cc-f0af-55c1-8ff2-ec483e3e68a3", + "contentVersion": "3.2.0", + "requiredWorkloads": [ + { + "workload": "mda", + "dataTypes": [ + "CloudAppEvents" + ] + }, + { + "workload": "mdo", + "dataTypes": [ + "EmailEvents", + "EmailPostDeliveryEvents", + "EmailUrlInfo", + "FileMaliciousContentInfo", + "MessageEvents", + "MessagePostDeliveryEvents", + "MessageUrlInfo", + "UrlClickEvents" + ] + }, + { + "workload": "mtp", + "dataTypes": [ + "AlertEvidence" + ] + } + ], + "requiredDataConnectors": [], + "requiredWorkspaceFunctions": [] + } + }, + "condition": "[parameters('DeployDefenderWorkbook')]" } ], "outputs": {} diff --git a/Solutions/Microsoft Defender for Office 365/ReleaseNotes.md b/Solutions/Microsoft Defender for Office 365/ReleaseNotes.md index 482452550cf..056f65122dd 100644 --- a/Solutions/Microsoft Defender for Office 365/ReleaseNotes.md +++ b/Solutions/Microsoft Defender for Office 365/ReleaseNotes.md @@ -1,6 +1,6 @@ | **Version** | **Date Modified (DD-MM-YYYY)** | **Change History** | |-------------|--------------------------------|--------------------------------------------------------------------------| -| 3.2.0 | 14-10-2026 | Added an **XDR Workbook** alongside the existing Sentinel workbook, preserving the connector and playbooks. | +| 3.2.0 | 15-10-2026 | Added the investigation **XDR Workbook** and native Defender **Detections and Insights XDR Workbook**, preserving the existing Sentinel workbook, connector and playbooks. | | 3.0.3 | 07-04-2025 | Updated ConnectivityCriteria Type in **Data Connector**. | | 3.0.2 | 24-04-2024 | Updated link for **Custom Connector** redirection in playbooks | | 3.0.1 | 29-09-2023 | 1 new **Playbook** added to the solution | diff --git a/Solutions/Microsoft Defender for Office 365/Workbook Sources/Native/MicrosoftDefenderForOffice365DetectionsAndInsights.json b/Solutions/Microsoft Defender for Office 365/Workbook Sources/Native/MicrosoftDefenderForOffice365DetectionsAndInsights.json new file mode 100644 index 00000000000..b9f238cd60c --- /dev/null +++ b/Solutions/Microsoft Defender for Office 365/Workbook Sources/Native/MicrosoftDefenderForOffice365DetectionsAndInsights.json @@ -0,0 +1,14895 @@ +{ + "version": "Notebook/1.0", + "items": [ + { + "type": 1, + "content": { + "json": "# Microsoft Defender for Office 365 Detections and Insights\n\nThis workbook provides email and collaboration security insights directly in Microsoft Defender using Advanced Hunting. It is designed for customers using workspace-less Workbooks in the Integrated Security Operations Center (ISOC) and does not require Microsoft Sentinel or a Log Analytics workspace.\n\n[Learn about Integrated Security Operations Center in Microsoft Defender](https://techcommunity.microsoft.com/blog/microsoftthreatprotectionblog/integrated-security-operations-center-in-microsoft-defender/4559097)\n\n- The time selector is bounded by the Defender data available to this tenant.\n- The default range is 7 days and the maximum selectable range is 90 days.\n- Subscription, workspace, cross-workspace, and MSSP selectors are not available in the workspace-less experience.\n- Incident visuals that depend on Microsoft Sentinel tables show an explicit ISOC workspace-required notice." + }, + "name": "text - 2", + "id": "d2b45ab8-a1c1-43d2-853d-290640bf4c94" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "2e238f92-709c-410b-93e0-60eab6150a75", + "version": "KqlParameterItem/1.0", + "name": "TimeRange", + "type": 4, + "isRequired": true, + "isGlobal": true, + "typeSettings": { + "selectableValues": [ + { + "durationMs": 3600000 + }, + { + "durationMs": 14400000 + }, + { + "durationMs": 43200000 + }, + { + "durationMs": 86400000 + }, + { + "durationMs": 172800000 + }, + { + "durationMs": 259200000 + }, + { + "durationMs": 604800000 + }, + { + "durationMs": 1209600000 + }, + { + "durationMs": 2592000000 + }, + { + "durationMs": 5184000000 + }, + { + "durationMs": 7776000000 + } + ], + "allowCustom": true + }, + "timeContext": { + "durationMs": 86400000 + }, + "value": { + "durationMs": 604800000 + }, + "key": "2e238f92-709c-410b-93e0-60eab6150a75" + }, + { + "id": "165f2f4a-e49f-4561-adc5-d0527a4caf32", + "version": "KqlParameterItem/1.0", + "name": "Granularity", + "label": "Trend interval", + "type": 2, + "isRequired": true, + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "jsonData": "[{\"value\":\"1d\",\"label\":\"Daily (1d)\",\"selected\":true},{\"value\":\"7d\",\"label\":\"Weekly (7d)\",\"selected\":false},{\"value\":\"30d\",\"label\":\"Monthly (30d)\",\"selected\":false},{\"value\":\"90d\",\"label\":\"Quarterly (90d)\",\"selected\":false}]", + "timeContext": { + "durationMs": 86400000 + }, + "value": "1d" + } + ], + "style": "pills" + }, + "name": "parameters - 1", + "id": "0021e733-42b4-461f-8f6c-14e6e765389d" + }, + { + "type": 11, + "content": { + "version": "LinkItem/1.0", + "style": "tabs", + "links": [ + { + "id": "3d26d949-bba8-486c-9af7-2b85bd5c8ab0", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Executive Summary", + "subTarget": "1", + "style": "link", + "key": "3d26d949-bba8-486c-9af7-2b85bd5c8ab0" + }, + { + "id": "a5f95467-84c1-4d8b-858c-7819339af748", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Email - Malware", + "subTarget": "2", + "style": "link", + "key": "a5f95467-84c1-4d8b-858c-7819339af748" + }, + { + "id": "b6c93de8-16d9-4c90-999b-837935de5645", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Email - Phish", + "subTarget": "3", + "style": "link", + "key": "b6c93de8-16d9-4c90-999b-837935de5645" + }, + { + "id": "9e006e81-4fd4-40b9-9d20-3705dd6c17ad", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Email - Impersonation & BEC", + "subTarget": "15", + "style": "link", + "key": "75f1e28f-e95a-4810-af40-6b47b35cda46" + }, + { + "id": "df2c53b4-b6ed-4151-95fb-b3f08b849b84", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Email - Spam", + "subTarget": "4", + "style": "link", + "key": "df2c53b4-b6ed-4151-95fb-b3f08b849b84" + }, + { + "id": "fd2006c9-39b5-43ac-b05d-47309ee22deb", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Teams & Collaboration", + "subTarget": "14", + "style": "link", + "key": "fd2006c9-39b5-43ac-b05d-47309ee22deb" + }, + { + "id": "ee01f95a-c5f7-4864-82e8-54a164741ba2", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "File - Malware (SharePoint, Teams and OneDrive)", + "subTarget": "9", + "style": "link", + "key": "ee01f95a-c5f7-4864-82e8-54a164741ba2" + }, + { + "id": "9df30067-3266-48a8-b9e3-d65952098d46", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "URL & Clicks", + "subTarget": "5", + "style": "link", + "key": "9df30067-3266-48a8-b9e3-d65952098d46" + }, + { + "id": "b4be0ac3-3f48-44a8-b4b6-b46e17c710cd", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Top Users & Exfiltration", + "subTarget": "6", + "style": "link", + "key": "b4be0ac3-3f48-44a8-b4b6-b46e17c710cd" + }, + { + "id": "e1d34091-7b3c-4e2d-a032-8be82a989313", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Email - Detection Overrides", + "subTarget": "7", + "style": "link", + "key": "e1d34091-7b3c-4e2d-a032-8be82a989313" + }, + { + "id": "a1e6264d-8f85-4a94-9ffd-eee36c04a0d5", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Post-Delivery & Quarantine", + "subTarget": "11", + "style": "link", + "key": "a1e6264d-8f85-4a94-9ffd-eee36c04a0d5" + }, + { + "id": "08c43a4f-f502-4813-9b8d-3f6b0b62b2fd", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "False Negative(FN) Submissions", + "subTarget": "8", + "style": "link", + "key": "08c43a4f-f502-4813-9b8d-3f6b0b62b2fd" + }, + { + "id": "638d931f-f319-4914-b72d-8d68e914c7d4", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "False Positive(FP) Submissions", + "subTarget": "10", + "style": "link", + "key": "638d931f-f319-4914-b72d-8d68e914c7d4" + }, + { + "id": "b2920bee-c32a-4fdd-9d32-b004db2f3ac8", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Security Operations Center (SOC) Insights", + "subTarget": "13", + "style": "link", + "key": "b2920bee-c32a-4fdd-9d32-b004db2f3ac8" + } + ] + }, + "name": "links - 14", + "id": "5c9a1d6b-c248-432b-a1c0-496337635775" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Defender for Office 365 - Protection Insights\r\n
\r\n\r\n**Microsoft Defender for Office 365** is a comprehensive security solution designed to protect organizations from advanced threats targeting their email and collaboration tools. It leverages a multi-layered approach to safeguard against phishing, malware, business email compromise (BEC), and other sophisticated attacks.\r\n" + }, + "name": "text - 13", + "styleSettings": { + "margin": "0", + "padding": "0" + }, + "id": "46119f93-fad9-413c-8e10-7615c6fdde2f" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows the number behind the effectiveness of phish and malware false positives including post delivery events but without edge data detections.\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\n\r\n// Get all mailflow detected as clean at time of delivery \r\nlet EmailEventsClean = materialize( \r\n EmailEvents \r\n | where Timestamp between (toscalar(minTime) .. toscalar(maxTime)) and EmailDirection == \"Inbound\" \r\n // | where ThreatTypes !contains \"Phish\" and ThreatTypes !contains \"Malware\" // Streaming-SIEM branch disabled for Advanced Hunting current-state semantics.\r\n // this alteration is due to the threat types being updated directly within advanced hunting.\r\n | where DeliveryLocation != \"Quarantine\" // Advanced Hunting current-state branch.\r\n | project NetworkMessageId,ThreatTypes \r\n); \r\n// Get all mailflow detected as phish or malware at time of delivery \r\nlet EmailEventsThreats = materialize( \r\n EmailEvents \r\n | where Timestamp between (toscalar(minTime) .. toscalar(maxTime)) and EmailDirection == \"Inbound\" \r\n | where ThreatTypes contains \"Phish\" or ThreatTypes contains \"Malware\" \r\n | extend MDO_detection = parse_json(DetectionMethods) \r\n | extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n | extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n | project NetworkMessageId,FirstDetection,FirstSubcategory,MDO_detection,ThreatTypes \r\n); \r\n// Get all post delivery ZAP / Redelivery events, and arg_max them to ensure we have the latest verdict to work with for each \r\nlet EmailPostDeliveryFiltered = materialize( \r\n EmailPostDeliveryEvents \r\n | where Timestamp between (toscalar(minTime) .. datetime_add('day', 7, toscalar(maxTime))) \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") or Action has_any (\"Redelivery\",\"Reprocessed\") \r\n | extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n | summarize arg_max(Timestamp, *) by Key \r\n | project Action,ActionType,ActionResult,ThreatTypes,NetworkMessageId \r\n); \r\n// Optional - get all admin submissions for malware or phish, so we can also count these in the miss bucket. \r\nlet CloudAppEventsFiltered = materialize( \r\n CloudAppEvents \r\n | where Timestamp between (toscalar(minTime) .. datetime_add('day', 7, toscalar(maxTime)))\r\n | where ActionType == \"AdminSubmissionSubmitted\" \r\n | extend SubmissionType = tostring(parse_json(RawEventData).SubmissionType) \r\n | extend NetworkMessageId = tostring(parse_json(RawEventData).ObjectId) \r\n | where SubmissionType in (\"1\", \"2\") \r\n | project SubmissionType,NetworkMessageId \r\n); \r\n// get the number of threats caught in mailflow \r\nlet Mal_Phish_Mailflow = toscalar( \r\n EmailEventsThreats \r\n | summarize count() \r\n); \r\n// get the number of threats caught in mailflow which turned out to be false positives (FPs) so we can correct the calculation \r\nlet FP_ZAP = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ThreatTypes !contains \"Phish\" and ThreatTypes !contains \"Malware\" and Action has_any (\"Redelivery\",\"Reprocessed\") \r\n | join kind=leftsemi (EmailEventsThreats) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// get the number of threats successfully cleaned up post delivery, ignoring where administrative policy stopped action \r\nlet FN_ZAP_Successful = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") and ActionResult in (\"Success\",\"AdminPolicy\") \r\n | join kind=leftsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// get the number of threats unsuccessfully cleaned up post delivery. \r\nlet FN_ZAP_Unsuccessful = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") and ActionResult !in (\"Success\",\"AdminPolicy\") \r\n | join kind=leftsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// join the administrative submissions to clean mailflow to find the additional miss \r\nlet FN_Admin_Submissions = toscalar( \r\n CloudAppEventsFiltered \r\n | join kind=rightsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n ); \r\n // print each result, and run the calculation to work out effectiveness at time of delivery and post delivery. \r\n\r\nprint StatisticName=\"Effectiveness Post Delivery\", Value=abs(round(((toreal(toscalar(FN_Admin_Submissions))+toreal(toscalar(FN_ZAP_Unsuccessful)))/(toreal(toscalar(Mal_Phish_Mailflow))+toreal(toscalar(FN_ZAP_Successful))+toreal(toscalar(FN_ZAP_Unsuccessful))+toreal(toscalar(FN_Admin_Submissions))-toreal(toscalar(FP_ZAP)))*100-100),2))", + "size": 1, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "tileSettings": { + "showBorder": false, + "titleContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Value", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "graphSettings": { + "type": 0, + "topContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Value", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "statSettings": { + "valueField": "Value", + "valueAggregation": "None", + "colorSettings": { + "type": "thresholds", + "mode": "foreground", + "heatmapPalette": "greenRed", + "thresholdsGrid": [ + { + "operator": ">", + "thresholdValue": "95", + "representation": "green" + }, + { + "operator": "<=", + "thresholdValue": "95", + "representation": "orange" + }, + { + "operator": "<=", + "thresholdValue": "90", + "representation": "red" + } + ] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "numberFormatSettings": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "tagText": "Phish / Malware Effectiveness - Post Delivery", + "valueFontStyle": "superLarge", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 5", + "id": "62de2a91-a809-48ec-a111-e697d556b2b3" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the percentage of emails released from quarantine out of the total ammount of quarantined emails\r\nlet Quarantine_Releases = toscalar(EmailPostDeliveryEvents\r\n| where Action == \"Quarantine release\"\r\n| join kind=leftouter (EmailEvents | where DeliveryLocation == \"Quarantine\") on NetworkMessageId\r\n| summarize count());\r\nlet Quarantined_Mailflow = toscalar(EmailEvents | where DeliveryLocation == \"Quarantine\"\r\n| summarize count());\r\nprint\r\nQuarantine_Releases = toreal(Quarantine_Releases),\r\nQuarantined_Mailflow = toreal(Quarantined_Mailflow),\r\nRelease_Percentage = abs(round(((toreal(Quarantine_Releases)/toreal(Quarantined_Mailflow))*100),2))", + "size": 1, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "tileSettings": { + "titleContent": { + "columnMatch": "Release_Percentage", + "formatter": 12, + "formatOptions": { + "palette": "none" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + "showBorder": true, + "sortCriteriaField": "Release_Percentage", + "size": "auto" + }, + "graphSettings": { + "type": 0, + "topContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Value", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "statSettings": { + "valueField": "Release_Percentage", + "valueAggregation": "None", + "colorSettings": { + "type": "thresholds", + "mode": "foreground", + "heatmapPalette": "greenRed", + "thresholdsGrid": [ + { + "operator": "<", + "thresholdValue": "5", + "representation": "green" + }, + { + "operator": ">", + "thresholdValue": "5", + "representation": "redDark" + } + ] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "numberFormatSettings": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "tagText": "Quarantine Release Percentage", + "valueFontStyle": "superLarge", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 1", + "id": "858ac1a4-8828-45e9-968c-d3cfc1216c64" + } + ] + }, + "name": "TopNr", + "id": "1369c97e-848b-475a-b447-3a435cb7a1f1" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "**Effectiveness visually represents the protection given by Defender for Office 365 against phishing and malware in email messages.**
\r\nWe consider messages that your users report, as well as decisions that are made after delivery." + }, + "name": "text - 9", + "styleSettings": { + "margin": "1px" + }, + "id": "25e2e19e-aefb-4e37-b28f-b4138d63e109" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows the number behind the effectiveness of phish and malware false positives including post delivery events but without edge data detections.\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\n\r\n// Get all mailflow detected as clean at time of delivery \r\nlet EmailEventsClean = materialize( \r\n EmailEvents \r\n | where Timestamp between (toscalar(minTime) .. toscalar(maxTime)) and EmailDirection == \"Inbound\" \r\n // | where ThreatTypes !contains \"Phish\" and ThreatTypes !contains \"Malware\" // Streaming-SIEM branch disabled for Advanced Hunting current-state semantics.\r\n // this alteration is due to the threat types being updated directly within advanced hunting.\r\n | where DeliveryLocation != \"Quarantine\" // Advanced Hunting current-state branch.\r\n | project NetworkMessageId,ThreatTypes \r\n); \r\n// Get all mailflow detected as phish or malware at time of delivery \r\nlet EmailEventsThreats = materialize( \r\n EmailEvents \r\n | where Timestamp between (toscalar(minTime) .. toscalar(maxTime)) and EmailDirection == \"Inbound\" \r\n | where ThreatTypes contains \"Phish\" or ThreatTypes contains \"Malware\" \r\n | extend MDO_detection = parse_json(DetectionMethods) \r\n | extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n | extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n | project NetworkMessageId,FirstDetection,FirstSubcategory,MDO_detection,ThreatTypes \r\n); \r\n// Get all post delivery ZAP / Redelivery events, and arg_max them to ensure we have the latest verdict to work with for each \r\nlet EmailPostDeliveryFiltered = materialize( \r\n EmailPostDeliveryEvents \r\n | where Timestamp between (toscalar(minTime) .. datetime_add('day', 7, toscalar(maxTime))) \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") or Action has_any (\"Redelivery\",\"Reprocessed\") \r\n | extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n | summarize arg_max(Timestamp, *) by Key \r\n | project Action,ActionType,ActionResult,ThreatTypes,NetworkMessageId \r\n); \r\n// Optional - get all admin submissions for malware or phish, so we can also count these in the miss bucket. \r\nlet CloudAppEventsFiltered = materialize( \r\n CloudAppEvents \r\n | where Timestamp between (toscalar(minTime) .. datetime_add('day', 7, toscalar(maxTime)))\r\n | where ActionType == \"AdminSubmissionSubmitted\" \r\n | extend SubmissionType = tostring(parse_json(RawEventData).SubmissionType) \r\n | extend NetworkMessageId = tostring(parse_json(RawEventData).ObjectId) \r\n | where SubmissionType in (\"1\", \"2\") \r\n | project SubmissionType,NetworkMessageId \r\n); \r\n// get the number of threats caught in mailflow \r\nlet Mal_Phish_Mailflow = toscalar( \r\n EmailEventsThreats \r\n | summarize count() \r\n); \r\n// get the number of threats caught in mailflow which turned out to be false positives (FPs) so we can correct the calculation \r\nlet FP_ZAP = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ThreatTypes !contains \"Phish\" and ThreatTypes !contains \"Malware\" and Action has_any (\"Redelivery\",\"Reprocessed\") \r\n | join kind=leftsemi (EmailEventsThreats) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// get the number of threats successfully cleaned up post delivery, ignoring where administrative policy stopped action \r\nlet FN_ZAP_Successful = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") and ActionResult in (\"Success\",\"AdminPolicy\") \r\n | join kind=leftsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// get the number of threats unsuccessfully cleaned up post delivery. \r\nlet FN_ZAP_Unsuccessful = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") and ActionResult !in (\"Success\",\"AdminPolicy\") \r\n | join kind=leftsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// join the administrative submissions to clean mailflow to find the additional miss \r\nlet FN_Admin_Submissions = toscalar( \r\n CloudAppEventsFiltered \r\n | join kind=rightsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n ); \r\n // print each result, and run the calculation to work out effectiveness at time of delivery and post delivery. \r\nunion withsource=Table \r\n (print StatisticName=\"Mal/Phish Mailflow totals - Minus FPs\", Value=toreal(Mal_Phish_Mailflow) - toreal(FP_ZAP)), \r\n (print StatisticName=\"Admin Mal/Phish FNs Submitted\", Value=toreal(FN_Admin_Submissions)), \r\n (print StatisticName=\"Mal/Phish FPs Reverse Zapped\", Value=toreal(FP_ZAP)), \r\n (print StatisticName=\"Mal / Phish Successfully Zapped\", Value=toreal(FN_ZAP_Successful)), \r\n (print StatisticName=\"Mal / Phish UN-Successfully Zapped\", Value=toreal(FN_ZAP_Unsuccessful)), \r\n (print StatisticName=\"Effectiveness Post Delivery (%)\", Value=abs(round(((toreal(FN_Admin_Submissions)+toreal(FN_ZAP_Unsuccessful))/(toreal(Mal_Phish_Mailflow)+toreal(FN_ZAP_Successful)+toreal(FN_ZAP_Unsuccessful)+toreal(FN_Admin_Submissions)-toreal(FP_ZAP))*100-100),2))), \r\n (print StatisticName=\"Effectiveness Pre-Delivery (%)\", Value=abs(round(((toreal(FN_Admin_Submissions)+toreal(FN_ZAP_Unsuccessful)+toreal(FN_ZAP_Successful))/(toreal(Mal_Phish_Mailflow)+toreal(FN_ZAP_Successful)+toreal(FN_ZAP_Unsuccessful)+toreal(FN_Admin_Submissions)-toreal(FP_ZAP))*100-100),2))) \r\n| project StatisticName, Value", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Value", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "tileSettings": { + "showBorder": false, + "titleContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Value", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "graphSettings": { + "type": 2, + "topContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Value", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + }, + "nodeIdField": "StatisticName", + "sourceIdField": "Value", + "targetIdField": "Value", + "graphOrientation": 3, + "showOrientationToggles": false, + "nodeSize": null, + "staticNodeSize": 100, + "colorSettings": null, + "hivesMargin": 5, + "edgeColorSettings": null + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 7", + "id": "9e09ff94-8092-49c7-860f-341049e1398c" + } + ] + }, + "customWidth": "50", + "name": "Effectiveness Nr", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "31081a73-9a54-4668-9e26-ad7347f1e06e" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "**Quarantine release rate by detection technology.** \r\n
\r\nFor each detector, the share of its quarantined mail that was later released (Release % = released / quarantined). A high rate can indicate false positives worth reviewing." + }, + "name": "text - 1", + "styleSettings": { + "margin": "1px" + }, + "id": "e9848043-03dd-4ada-9e73-238067463f74" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Per detection technology: the share of its quarantined emails later released from quarantine (a high rate can indicate false positives). Top 7 by release rate; detectors with <10 quarantined excluded so the rate is meaningful.\r\nEmailEvents\r\n| where DeliveryLocation == \"Quarantine\"\r\n| extend MDO_detection = parse_json(DetectionMethods)\r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0]))\r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\")\r\n| where FirstSubcategory contains \"Malware\" or FirstSubcategory contains \"Phish\"\r\n| join kind=leftouter (\r\n EmailPostDeliveryEvents\r\n | where Action == \"Quarantine release\"\r\n | distinct NetworkMessageId\r\n | extend ReleasedFlag = \"yes\"\r\n ) on NetworkMessageId\r\n| summarize Quarantined = dcount(NetworkMessageId), Released = dcountif(NetworkMessageId, ReleasedFlag == \"yes\") by FirstSubcategory\r\n| where Quarantined >= 10 and Released > 0\r\n| extend ReleaseRate = round(Released * 100.0 / Quarantined, 2)\r\n| project ['Detection Technology']=FirstSubcategory, ['Quarantined Emails']=Quarantined, ['Released']=Released, ['Release %']=ReleaseRate\r\n| order by ['Release %'] desc\r\n| take 7", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Quarantined Emails", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Released", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Release %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 2", + "id": "1bbae9d1-d6f8-446a-817c-8fdc2df83d4c" + } + ] + }, + "customWidth": "50", + "name": "Quarantine Overview Relese", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "36fd8f20-ece7-4889-9fb1-f5b85b97b45a" + } + ] + }, + "customWidth": "100", + "name": "group - Exec Protection Insights", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "1d8e22e0-22f7-453e-aed2-9e56ace1363a" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Protection details\r\n
\r\n\r\nThis Overview provides an executive summary of your Microsoft Defender for Office 365 email security posture: the volume of mail processed, threats detected and filtered (phishing, malware, spam), overall protection effectiveness, and the mix of threats targeting your organization. Use it as a starting point, then drill into the dedicated tabs for detailed investigation." + }, + "name": "text - 13", + "id": "24cf577c-e12a-4747-95a7-1c19bee17397" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "5c0f0101-0a11-4b22-9c33-000000000101", + "version": "KqlParameterItem/1.0", + "name": "ProtectionView", + "label": "Protection view", + "type": 2, + "isRequired": true, + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "jsonData": "[{ \"value\": \"Table\", \"label\": \"Summary table\", \"selected\": true }, { \"value\": \"Tiles\", \"label\": \"Detailed tiles\" }]", + "value": "Tiles" + } + ], + "style": "pills" + }, + "name": "Protection view selector", + "id": "5c0f0102-0a11-4b22-9c33-000000000102" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let base = materialize(EmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| summarize arg_max(Timestamp, ThreatTypes, DeliveryAction, OrgLevelPolicy, OrgLevelAction, UserLevelAction) by Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress));\r\nlet agg = materialize(base | summarize\r\n Total = count(),\r\n Filtered = countif(isnotempty(ThreatTypes) and DeliveryAction != \"Delivered\" and OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")),\r\n FMal = countif(ThreatTypes has \"Malware\" and OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")),\r\n FPhish = countif(ThreatTypes has \"Phish\" and not(ThreatTypes has \"Malware\") and DeliveryAction != \"Delivered\" and OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")),\r\n FSpam = countif(ThreatTypes == \"Spam\" and DeliveryAction != \"Delivered\" and OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")),\r\n Deliv = countif(isnotempty(ThreatTypes) and DeliveryAction == \"Delivered\" and (isnotempty(OrgLevelAction) or isnotempty(UserLevelAction))),\r\n Blocked = countif(isempty(ThreatTypes) and DeliveryAction != \"Delivered\" and (isnotempty(OrgLevelAction) or isnotempty(UserLevelAction))),\r\n Clean = countif(isempty(ThreatTypes) and DeliveryAction == \"Delivered\"));\r\nlet pd = materialize(EmailPostDeliveryEvents | where ActionResult == \"Success\" | summarize MalZap = countif(ActionType == \"Malware ZAP\"), PhishZap = countif(ActionType == \"Phish ZAP\"), SpamZap = countif(ActionType == \"Spam ZAP\"));\r\nlet sub = materialize(CloudAppEvents | extend R = tostring(parse_json(RawEventData).RecordType), SCT = tostring(parse_json(RawEventData).SubmissionContentType) | where R == \"29\" | summarize Adm = countif(ActionType == \"AdminSubmissionSubmitted\" and SCT == \"Mail\"), Usr = countif(ActionType == \"UserSubmission\"));\r\nlet Total = toscalar(agg | project Total);\r\nlet Filtered = toscalar(agg | project Filtered);\r\nlet FMal = toscalar(agg | project FMal);\r\nlet FPhish = toscalar(agg | project FPhish);\r\nlet FSpam = toscalar(agg | project FSpam);\r\nlet Deliv = toscalar(agg | project Deliv);\r\nlet Blocked = toscalar(agg | project Blocked);\r\nlet Clean = toscalar(agg | project Clean);\r\nlet MalZap = toscalar(pd | project MalZap);\r\nlet PhishZap = toscalar(pd | project PhishZap);\r\nlet SpamZap = toscalar(pd | project SpamZap);\r\nlet Adm = toscalar(sub | project Adm);\r\nlet Usr = toscalar(sub | project Usr);\r\nunion\r\n (print o = 1, Name = \"Total Inbound Emails\", Count = Total),\r\n (print o = 2, Name = \"    Filtering Totals\", Count = Filtered),\r\n (print o = 3, Name = \"        Filtered as Malware\", Count = FMal),\r\n (print o = 4, Name = \"        Filtered as Phish\", Count = FPhish),\r\n (print o = 5, Name = \"        Filtered as Spam\", Count = FSpam),\r\n (print o = 6, Name = \"    Delivered with Detection\", Count = Deliv),\r\n (print o = 7, Name = \"    User/Admin Blocked\", Count = Blocked),\r\n (print o = 8, Name = \"    Clean Emails\", Count = Clean),\r\n (print o = 9, Name = \"Post-Delivery ZAP Removals\", Count = MalZap + PhishZap + SpamZap),\r\n (print o = 10, Name = \"    Removed by Malware ZAP\", Count = MalZap),\r\n (print o = 11, Name = \"    Removed by Phish ZAP\", Count = PhishZap),\r\n (print o = 12, Name = \"    Removed by Spam ZAP\", Count = SpamZap),\r\n (print o = 13, Name = \"User/Admin Reported\", Count = Adm + Usr),\r\n (print o = 14, Name = \"    Reported by Admins\", Count = Adm),\r\n (print o = 15, Name = \"    Reported by Users\", Count = Usr)\r\n| sort by o asc\r\n| extend [\"% of Inbound\"] = round(Count * 100.0 / Total, 1)\r\n| project Name, Count, [\"% of Inbound\"]", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Name", + "formatter": 1, + "formatOptions": { + "customColumnWidthSetting": "3fr" + } + }, + { + "columnMatch": "Count", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "3fr" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "% of Inbound", + "formatter": 3, + "formatOptions": { + "palette": "green", + "min": 0, + "max": 100, + "customColumnWidthSetting": "2fr" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "ProtectionView", + "comparison": "isEqualTo", + "value": "Table" + }, + "name": "query - option 1 grid", + "id": "5c0f0005-0a11-4b22-9c33-000000000005" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "title": "Total Emails", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| summarize Count = count()\r\n| extend Details = \"Total Inbound Emails\";", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Count", + "formatter": 4, + "formatOptions": { + "palette": "greenRed" + } + } + ] + }, + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1, + "formatOptions": { + "compositeBarSettings": { + "labelText": "" + } + } + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "blue", + "compositeBarSettings": { + "labelText": "" + } + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "chartSettings": { + "xAxis": "Count", + "createOtherGroup": 0 + }, + "mapSettings": { + "locInfo": "LatLong", + "sizeSettings": "Count", + "sizeAggregation": "Sum", + "legendMetric": "Count", + "legendAggregation": "Sum", + "itemColorSettings": { + "type": "heatmap", + "colorAggregation": "Sum", + "nodeColorField": "Count", + "heatmapPalette": "greenRed" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 1", + "id": "84e8d60b-7937-46f5-b2f4-a1a4adf06c9f" + } + ] + }, + "name": "Total Inbound", + "id": "1aeed046-9ea5-4583-b966-722847997fc7" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "title": "Filtering Totals", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where isnotempty(ThreatTypes) and EmailDirection == \"Inbound\" and DeliveryAction != 'Delivered'\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| summarize Count = count()\r\n| extend Details = \"Filtering Totals\";", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1, + "formatOptions": { + "compositeBarSettings": { + "labelText": "" + } + } + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "redDark", + "compositeBarSettings": { + "labelText": "" + } + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 1", + "id": "bae9a200-589f-4ca6-a3cf-f1110f644c49" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Total emails detected as Malware\r\nEmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| where ThreatTypes has ('Malware') and EmailDirection == \"Inbound\"\r\n| summarize Count= count()\r\n| extend Details = \"Emails Filtered as Malware\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "red" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 4", + "id": "0984d05b-fd2c-48e1-835f-41afc5a2385a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Total emails detected as Phish\r\nEmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| where ThreatTypes has \"Phish\" and not(ThreatTypes has \"Malware\") and EmailDirection == \"Inbound\" and DeliveryAction != 'Delivered'\r\n| summarize Count= count()\r\n| extend Details = \"Emails Filtered as Phish\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "orange" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 4", + "id": "ced2d054-76d1-40df-a412-0bc86a6c3336" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Total emails by detected as Spam\r\nEmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| where ThreatTypes == 'Spam' and EmailDirection == \"Inbound\" and DeliveryAction != 'Delivered'\r\n| summarize Count= count()\r\n| extend Details = \"Emails Filtered as Spam\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "yellow" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 4", + "id": "14456a0d-f5ac-46a0-a007-c72c7c40c58f" + } + ] + }, + "customWidth": "50", + "name": "group - 9", + "id": "d4e69885-f1b2-4c2b-85c2-188a6708dc4b" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "title": " ", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and DeliveryAction == 'Delivered'\r\n| where isnotempty(OrgLevelAction) or isnotempty(UserLevelAction)\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| summarize Count= count()\r\n| extend Details = \"Delivered with Detection\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "red" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "394d1ed4-7089-4291-bc80-f9948e3be6a9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\" and isempty(ThreatTypes) \r\n| where isnotempty(OrgLevelAction) or isnotempty(UserLevelAction)\r\n| where DeliveryAction != 'Delivered'\r\n| summarize Count= count()\r\n| extend Details = \"User/Admin Blocked\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "gray" + }, + "tooltipFormat": { + "tooltip": "Emails blocked from being delivered because of User or Admin overriddes" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "c29a2268-67d1-4958-a9a3-696384075987" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where isempty(ThreatTypes) and EmailDirection == \"Inbound\" and DeliveryAction == 'Delivered'\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| summarize Count= count()\r\n| extend Details = \"Clean Emails\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "gray" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "89a02ac7-971c-4672-bf5d-64709c479536" + } + ] + }, + "customWidth": "50", + "name": "group - 8", + "id": "761e74d4-279e-465f-ba47-5eeec4cf05d2" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "title": "Post-Delivery ZAP Removals", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailPostDeliveryEvents\r\n| where ActionResult == \"Success\"\r\n| where ActionType == \"Malware ZAP\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Removed by Malware ZAP\"\r\n", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "red" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "b06666bc-6ec0-49e7-a332-77e278d2320f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailPostDeliveryEvents\r\n| where ActionResult == \"Success\"\r\n| where ActionType == \"Phish ZAP\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Removed by Phish ZAP\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "orange" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "6fbac01b-0c42-46dc-8ca8-68e285593a45" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailPostDeliveryEvents\r\n| where ActionResult == \"Success\"\r\n| where ActionType == \"Spam ZAP\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Removed by Spam ZAP\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "yellow" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "7bd27a3b-be13-4ca0-9964-0f872f826b45" + } + ] + }, + "name": "Post Delivery", + "id": "4d20339e-5215-4edf-99d6-728cac183d16" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails reported by user and total emails reported by Admins as false positive or false negative detection\r\nCloudAppEvents\r\n| extend Record= (parse_json(RawEventData)).RecordType\r\n| extend SubmissionState = (parse_json(RawEventData)).SubmissionState,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Reported by Admins\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "palette": "none" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 3", + "id": "7490fa3a-e287-4fc3-b025-8772b9edb601" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails reported by user and total emails reported by Admins as false positive or false negative detection\r\nCloudAppEvents\r\n| extend Record= (parse_json(RawEventData)).RecordType\r\n| extend SubmissionState = (parse_json(RawEventData)).SubmissionState\r\n| where Record == 29 and ActionType == \"UserSubmission\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Reported by Users\"\r\n", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "palette": "none" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 2", + "id": "7af222dc-fd74-40ec-8ab7-741e179c07bf" + } + ] + }, + "name": "Reported", + "id": "8151e242-1c30-4550-ae9c-83f159e1a456" + } + ] + }, + "conditionalVisibility": { + "parameterName": "ProtectionView", + "comparison": "isEqualTo", + "value": "Tiles" + }, + "name": "Protection - Tiles view", + "id": "5c0f0103-0a11-4b22-9c33-000000000103" + }, + { + "type": 1, + "content": { + "json": "## Most Attacked Users
\r\n\r\n**The users most targeted by inbound email threats across all threat types (malware, phishing, and spam) in the selected period. Concentrated targeting of a few individuals is a strong signal of deliberate campaigns.**

**Recommended action:** Prioritise these users for security awareness training, tighter protection policies (for example the Strict preset), and closer monitoring - they are your highest-risk people." + }, + "name": "exec vap banner", + "id": "1fe431fb-cc96-4e81-b164-3a1a3823ebeb" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query surfaces the users most targeted by inbound email threats across all threat types (malware, phishing, spam) for the selected period, so SecOps can prioritise the highest-risk individuals. Similar to a \"Most Attacked People\" view.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| where isnotempty(ThreatTypes)\r\n| summarize\r\n ['Total Threats'] = count(),\r\n Malware = countif(ThreatTypes has \"Malware\"),\r\n Phish = countif(ThreatTypes has \"Phish\"),\r\n Spam = countif(ThreatTypes has \"Spam\"),\r\n ['Last Seen'] = max(Timestamp)\r\n by ['User']=RecipientEmailAddress\r\n| top 10 by ['Total Threats']\r\n| project ['User'], ['Total Threats'], Malware, Phish, Spam, ['Last Seen']", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Malware", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "145px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Phish", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "145px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Spam", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "145px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Total Threats", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "145px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "exec vap table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "2dfd91b1-b8d3-4a72-aaf4-a30a1886bed7" + }, + { + "type": 1, + "content": { + "json": "## Detection trend over time - grouped by {Granularity}\r\n**Represents total emails, total detections, total user submissions and admin email submissions over time summarizing the data per {Granularity} interval**" + }, + "name": "text - 14", + "id": "ddbbdaef-b374-42a8-821c-7fcd7ee53ba9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails, total detections, total user, and admin email submissions over time summarizing the data daily\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet scaffold = range Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran;\r\nlet baseQuery = materialize(EmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where isnotempty(Timestamp));\r\nlet sub = materialize(CloudAppEvents\r\n| extend Record = (parse_json(RawEventData)).RecordType, SubmissionContentType = tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29);\r\nlet zapbase = EmailPostDeliveryEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ActionResult == \"Success\"\r\n| where ActionType == \"Phish ZAP\" or ActionType == \"Malware ZAP\" or ActionType == \"Spam ZAP\";\r\nunion\r\n(scaffold | join kind=leftouter (baseQuery | where EmailDirection == \"Inbound\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Inbound Emails\"),\r\n(scaffold | join kind=leftouter (baseQuery | where ThreatTypes has ('Phish') | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Emails Detected as Phish\"),\r\n(scaffold | join kind=leftouter (baseQuery | where ThreatTypes has ('Malware') | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Emails Detected as Malware\"),\r\n(scaffold | join kind=leftouter (baseQuery | where ThreatTypes has ('Spam') | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Emails Detected as Spam\"),\r\n(scaffold | join kind=leftouter (baseQuery | where EmailDirection == \"Intra-org\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Intra-org Emails\"),\r\n(scaffold | join kind=leftouter (baseQuery | where EmailDirection == \"Outbound\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Outbound Emails\"),\r\n(scaffold | join kind=leftouter (baseQuery | where isnotempty(ThreatTypes) | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Emails with Threat\"),\r\n(scaffold | join kind=leftouter (sub | where ActionType == \"UserSubmission\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Emails Reported by Users\"),\r\n(scaffold | join kind=leftouter (zapbase | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Emails Removed by ZAP\"),\r\n(scaffold | join kind=leftouter (sub | where ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType == \"Mail\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Emails Reported by Admins\")", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp", + "seriesLabelSettings": [ + { + "seriesName": "Total Inbound Emails", + "label": "Inbound Emails", + "color": "green" + }, + { + "seriesName": "Total Emails with Threat", + "label": "Emails with Threat", + "color": "redDark" + }, + { + "seriesName": "Emails Detected as Phish", + "label": "Emails with Phish", + "color": "redBright" + }, + { + "seriesName": "Emails Detected as Malware", + "label": "Emails with Malware", + "color": "red" + }, + { + "seriesName": "Total Intra-org Emails", + "label": "Intra-org Emails", + "color": "greenDark" + }, + { + "seriesName": "Emails Detected as Spam", + "label": "Emails with Spam", + "color": "gray" + }, + { + "seriesName": "Total Outbound Emails", + "label": "Outbound Emails", + "color": "greenDarkDark" + }, + { + "seriesName": "Total Emails Removed by ZAP", + "label": "Emails ZAP-d", + "color": "orangeDark" + }, + { + "seriesName": "Total Emails Reported by Users", + "label": "User Reported Emails", + "color": "lightBlue" + }, + { + "seriesName": "Total Emails Reported by Admins", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 1", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "bcbefa48-f553-4290-acff-2691caf898ea" + }, + { + "type": 1, + "content": { + "json": "## Bad traffic (%) - Inbound Emails - grouped by {Granularity}\r\n**This represents bad traffic (% of emails with threats) compared to total inbound emails, summarized per {Granularity} interval over time.**" + }, + "name": "text - 15", + "id": "30761bcc-b1a5-45e2-8c0a-22388fbbf16c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises bad traffic (% of emails with threats) compared to total inbound emails over time summarising the data daily.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalEmailCount = count(),\r\n BadEmailCount = countif(isnotempty(ThreatTypes)) by bin(Timestamp, {Granularity})\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(BadEmailCount / todouble(TotalEmailCount) * 100, 2))\r\n| project Timestamp, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 0, + "aggregation": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 4", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "508036a8-d969-44c2-b2d2-c62d99999197" + } + ] + }, + "customWidth": "100", + "name": "group - Exec Protection Details", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "e6edeeeb-dcde-41d0-88c7-97ef773403b1" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Collaboration Protection Posture\r\n
\r\n\r\nMicrosoft Defender for Office 365 protects Microsoft Teams and collaboration, not only email. This snapshot shows Teams threat activity for the period.

**Recommended action:** Review the dedicated **Teams & Collaboration** tab for impersonation, malicious URLs, risky senders and file threats in Teams." + }, + "name": "exec collab banner", + "id": "3d78a6aa-51d4-4cab-93d1-26dff86fd667" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Headline Microsoft Teams / collaboration protection metrics for the executive summary, with per-interval sparklines so the collaboration threat trend is visible at a glance. Messages and URLs are counted per distinct Teams message.\r\nlet gran = {Granularity};\r\nlet me = materialize(MessageEvents);\r\nlet cae = materialize(CloudAppEvents | where ActionType == \"TeamsImpersonationDetected\");\r\nlet mui = materialize(MessageUrlInfo);\r\nlet uce = materialize(UrlClickEvents | where Workload == \"Teams\" and ActionType in (\"ClickBlocked\",\"ClickBlockedByTenantPolicy\"));\r\nlet fmc = materialize(FileMaliciousContentInfo | where Workload == \"MicrosoftTeams\");\r\nunion\r\n(me | summarize Count = dcount(TeamsMessageId) | extend Details = \"Teams Messages Scanned\", Ord = 1, Trend = toscalar(me | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(me | where isnotempty(ThreatTypes) | summarize Count = count() | extend Details = \"Teams Threat Messages\", Ord = 2, Trend = toscalar(me | where isnotempty(ThreatTypes) | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(cae | summarize Count = count() | extend Details = \"Teams Impersonation Detections\", Ord = 3, Trend = toscalar(cae | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(mui | summarize Count = dcount(TeamsMessageId) | extend Details = \"URLs Shared in Teams\", Ord = 4, Trend = toscalar(mui | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(uce | summarize Count = count() | extend Details = \"Malicious Clicks Blocked\", Ord = 5, Trend = toscalar(uce | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(fmc | summarize Count = count() | extend Details = \"Teams Files Scanned\", Ord = 6, Trend = toscalar(fmc | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(fmc | where isnotempty(ThreatTypes) | summarize Count = count() | extend Details = \"Malicious Teams Files\", Ord = 7, Trend = toscalar(fmc | where isnotempty(ThreatTypes) | make-series S = count() default = 0 on Timestamp step gran | project S))\r\n| sort by Ord asc\r\n| project Details, Count, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21 + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "exec collab tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3175aee5-56d2-4cb1-b1c3-75be683e6ffb" + } + ] + }, + "customWidth": "100", + "name": "group - Exec Collaboration Posture", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "39b0921f-fcef-49f4-8d52-0dcd1f33045b" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Emerging Threats\r\n
\r\n\r\n

With more sophisticated adversaries and new threats emerging frequently and prevalently, it's critical to be able to quickly identify and react to these threats.

\r\n\r\n[

🛡️Activity Profile: Email threat landscape

](https://security.microsoft.com/threatanalytics3/f186e4b0-28df-499a-901e-c64768b6d0dc/overview?filters=tags%253DPhishing)\r\n[

🛡️Activity Profile: Automated business email impersonation campaign uses parallel aging report and payroll diversion lures

](https://security.microsoft.com/threatanalytics3/3eb53378-892d-4695-a497-25d0a54181ee)\r\n[

🛡️Tool Profile: StealC

](https://security.microsoft.com/threatanalytics3/4d837c12-1db4-49c8-8466-219198d40b9b)\r\n[

🛡️OSINT Profile: UNC1151/Ghostwriter phishing campaign targeting Gmail accounts

](https://security.microsoft.com/threatanalytics3/b1a7e5e7-4b43-4758-8805-f714a131161a)\r\n[

🛡️Activity Profile: Encrypted message campaign targets real estate/financial sectors

](https://security.microsoft.com/threatanalytics3/651d669a-4721-42ab-bb96-509e94b5bfd9)\r\n\r\n
\r\n\r\nView all\r\n \r\n\r\n" + }, + "name": "text - 10", + "styleSettings": { + "margin": "0", + "padding": "0" + }, + "id": "0c781e85-af9a-41a6-9cf7-b3bb9a09d5d0" + } + ] + }, + "customWidth": "100", + "name": "group - Exec Emerging Threats", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "4f8886d3-882a-4c14-ab7f-a37bd302e32f" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Microsoft 365 Secure Email Gateway Performance\r\n
\r\n\r\n

Using multiple vendor email security products can offer diverse detections. However, our comprehensive end-to-end approach—spanning prevention, detection, posture, investigation, response, and user training—delivers a unified and effective defense that matches or exceeds the efficacy of siloed Secure Email Gateway solutions.

\r\n\r\n[

Learn more

](https://www.microsoft.com/en-us/security/blog/2026/06/15/microsoft-defender-email-security-benchmarking-key-insights-from-one-year-of-data/) \r\n\r\n
\r\n

High-severity email threats missed per 1,000 users protected - February–April 2026 (Microsoft Defender email security benchmarking)

" + }, + "name": "text - 12", + "id": "94c804f9-2860-4768-be59-fb31a4ff22d7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "datatable(Index:int, Name:string, Value:int)\r\n[\r\n 1, \"Defender for Office 365\", 194,\r\n 2, \"Mimecast\", 478,\r\n 3, \"ProofPoint\", 483,\r\n 4, \"HornetSecurity\", 813,\r\n 5, \"TrendMicro\", 1151,\r\n 6, \"IronPort\", 1274,\r\n 7, \"Barracuda\", 1585,\r\n 8, \"FireEye\", 2107\r\n]\r\n| project [\"Email security solution\"] = Name, [\"High-severity threats missed / 1K users\"] = Value\r\n| order by [\"High-severity threats missed / 1K users\"] asc\r\n", + "size": 0, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Email security solution", + "formatter": 1, + "formatOptions": { + "customColumnWidthSetting": "40%" + } + }, + { + "columnMatch": "High-severity threats missed / 1K users", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "min": 0, + "max": 2107, + "customColumnWidthSetting": "60%" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "useGrouping": true + } + } + } + ], + "rowLimit": 10, + "sortBy": [ + { + "itemKey": "High-severity threats missed / 1K users", + "sortOrder": 1 + } + ] + } + }, + "name": "query - 11", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e54fd5bd-17e2-40dc-897d-8a3bb21116ff" + } + ] + }, + "customWidth": "100", + "name": "group - Exec SEG Performance", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "1f3a7e2b-0a1f-48ba-9da3-e7531d500938" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "id": "ab3756d3-3f60-4024-9376-0f1a7d47ac13", + "type": 1, + "name": "text - 18", + "content": { + "json": "\r\n\r\n\r\n\r\n
Stay Current\r\n
\r\n\r\n
\r\n\r\n- **Threat Analytics (Defender XDR)** — live, tenant-specific threat intelligence and recommended actions: aka.ms/threatanalytics\r\n- **Microsoft Security Blog** — campaign write-ups and threat research: microsoft.com/security/blog\r\n- **Microsoft Defender for Office 365 Tech Community blog** — product updates and reporting guidance: Tech Community\r\n- **Latest features in Microsoft Defender for Office 365** — What's new in Microsoft Defender for Office 365 \r\n- **Share reporting feedback**: aka.ms/mdoreportingfeedback\r\n" + } + } + ] + }, + "customWidth": "100", + "name": "group - Exec Stay Current", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "5e22c565-cd2e-41f3-8d5a-0735af67c93f" + } + ], + "exportParameters": true + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "1" + }, + "name": "Detection Overview", + "styleSettings": { + "margin": "0", + "padding": "0" + }, + "id": "3f2cc277-9eb3-486d-a1f8-9fa5374a3d80" + }, + { + "type": 1, + "content": { + "json": "# Malware detection insights\r\n\r\n---\r\n\r\nThis tab provides insights into email message **detections** by Microsoft Defender for Office 365 where the message contained a **malware threat** (such as viruses, spyware, or ransomware) within its **URLs** or **attachments**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "text - 13", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "81f28ffc-b69e-4960-a61c-cac17a012ed6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//KPI summary of inbound email malware detections for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet mal = EmailEvents | where EmailDirection == \"Inbound\" | where ThreatTypes has \"Malware\";\r\nlet inbox = mal | where DeliveryLocation has \"Inbox\";\r\nlet malTrend = toscalar(mal | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet inboxTrend = toscalar(inbox | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(mal | summarize count()), Details = \"Malware Emails\", Ord = 1, Trend = malTrend),\r\n(print Count = toscalar(mal | summarize dcount(RecipientEmailAddress)), Details = \"Users Targeted\", Ord = 2, Trend = malTrend),\r\n(print Count = toscalar(mal | summarize dcount(SenderFromDomain)), Details = \"Sender Domains\", Ord = 3, Trend = malTrend),\r\n(print Count = toscalar(inbox | summarize count()), Details = \"Delivered to Inbox\", Ord = 4, Trend = inboxTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "malware kpi strip", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "20c06dd3-5025-4b2b-960e-ff012f5d2343" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Malware Detection Trends, Threat Classes, and Malware Names\r\n
\r\n\r\nThis section consolidates key visuals that track and explain malware detections in inbound email as identified by Microsoft Defender for Office 365 focusing on per-{Granularity} trend, threat classes and Malware types. \r\n

**Recommended action:** If malware volume spikes, confirm Safe Attachments (Block mode) is enabled for all users and investigate the top malware families below." + }, + "name": "text - 14", + "id": "1f09c6ec-b2de-4aa9-bd8e-81d11c92ebd4" + }, + { + "type": 1, + "content": { + "json": "### Malware Detection Trend\r\n**This visual displays a per-{Granularity} trend of email malware detections identified by Microsoft Defender for Office 365. The area chart summarises the number of messages flagged for malware threats.**" + }, + "name": "text - Malware Trend header", + "id": "e90b714f-de84-4571-9a60-b3b2f3bd09dd" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents \r\n| where ThreatTypes has \"Malware\" \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize MalwareDetections = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, MalwareDetections = coalesce(MalwareDetections, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "MalwareDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 0", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "350d0aa3-c093-4105-a150-c20111ac2912" + }, + { + "type": 1, + "content": { + "json": "### Malware Detection Trend - Advanced Threats\r\n**Not all threats are going to be easily recognisable, that's why Microsoft Defender for Office 365 has advanced threat detection methods, that use virtual sandbox environments to detonate URLs and Files. These virtual sandbox technologies look for known patterns, such as a recognisable login page in a URL, or a file accessing command and control infrastructure. This visual displays a per-{Granularity} trend of Malware detections of these advanced threats**" + }, + "name": "text - Malware Advanced Threats header", + "id": "12e07248-ada4-41d9-99cc-824eb65cff79" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections over time summarizing the data daily by Malware detection technologies/controls used for detecting unknown-unique malware.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Malware'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand MalwareMethod = ParsedMethods.Malware\r\n| where MalwareMethod in ('File detonation','URL detonation')\r\n| summarize Count = count() by MalwareMethod = tostring(MalwareMethod), Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct MalwareMethod | extend d = 1) on d | project Timestamp, MalwareMethod\r\n| join kind=leftouter (agg) on Timestamp, MalwareMethod\r\n| project Timestamp, MalwareMethod, Count = coalesce(Count, 0)\r\n| sort by MalwareMethod asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "File detonation", + "color": "redDark" + }, + { + "seriesName": "URL detonation", + "color": "orangeDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 9", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "ebcb6f29-02be-4dd0-b792-cd99285c29d4" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by Threat Classification\r\n**Summary of email messages detected by Microsoft Defender for Office 365 as malware, grouped by type of malware (Adware, Downloader, HackTool, Ransomware, Remote access trojan, Spyware).**" + }, + "customWidth": "33", + "name": "text - 15", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5638fc51-0830-4675-87d4-82f03df17bbf" + }, + { + "type": 1, + "content": { + "json": "### Top Attacked Users by Malware Threat Classification\r\n**Displays the recipient most frequently targeted for each malware type (Adware, Downloader, HackTool, Ransomware, Remote access trojan, Spyware) in inbound email detections.**" + }, + "customWidth": "33", + "name": "text - 15 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d2e3903b-4984-40da-a437-3d6a2b121e23" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by Threat Name\r\n**Summarises email messages flagged by Microsoft Defender for Office 365, grouped by specific malware names detected in URLs or attachments.**" + }, + "customWidth": "33", + "name": "text - 15 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6c0bebcf-9838-4385-ab3a-30db6c994284" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by threat classification of the malware threat in the message.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where ThreatTypes has 'Malware' and ThreatClassification has_any(\"Adware\",\"Downloader\",\"HackTool\",\"Ransomware\",\"Remote access trojan\",\"Spyware\")\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Count = count(Key) by ThreatClassification\r\n| sort by Count desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "query - 11", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "acb98530-8e3a-4383-b42f-8fd74b1c3fbe" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Malware detections in emails summarizing by various Threat classes showing the top attacked user for each threat classification type.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where ThreatTypes has \"Malware\" and EmailDirection == \"Inbound\" and ThreatClassification has_any(\"Adware\",\"Downloader\",\"HackTool\",\"Ransomware\",\"Remote access trojan\",\"Spyware\")\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize EmailCount=count() by ThreatClassification, RecipientEmailAddress\r\n| summarize Count = arg_max(EmailCount, RecipientEmailAddress) by ThreatClassification\r\n| sort by Count desc\r\n| project ['Threat Classification'] = ThreatClassification, ['Top Recipient'] = RecipientEmailAddress, ['Emails'] = Count", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "TopEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "statSettings": { + "valueField": "RecipientEmailAddress", + "valueAggregation": "None", + "colorSettings": { + "type": "static", + "mode": "background", + "heatmapPalette": "greenRed", + "thresholdsGrid": [] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "tagText": "", + "valueFontStyle": "auto" + }, + "chartSettings": { + "xAxis": "RecipientEmailAddress" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 5 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d9b46c97-91ce-4d64-aca6-3126ac49c0ff" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by ThreatNames of the malware detected.\r\nEmailEvents \r\n| where isnotempty(ThreatNames) and ThreatTypes has \"Malware\" \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| mv-expand ThreatName = split(ThreatNames, \",\") to typeof(string)\r\n| where isnotempty(ThreatName)\r\n| distinct Key, ThreatName\r\n| summarize Count = count() by ThreatName\r\n| top 15 by Count\r\n| project ['Threat Name'] = ThreatName, Count", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Count", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "xAxis": "ThreatNames", + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 3", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b9a4b34f-f54f-4d6e-bb20-81925d0f5540" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "group - 3", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "82853a93-e11f-4e4a-80f4-733850a1d3ff" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Malware Detections by Delivery Location, Detection Technology and Sender Infrastructure Insights\r\n
\r\n\r\nThis section consolidates key visuals that track and explain malware detections delivery locations, detection technologies used for detections, sender infrastructure insights in inbound email identified by Microsoft Defender for Office 365 as Malware. \r\n

**Recommended action:** For sender IPs or countries you do not do business with, consider connection filtering or geo-based rules; verify the detection technologies catching these are enabled." + }, + "name": "banner - Malware Delivery Detection Sender", + "id": "cba6403d-e2b1-4fe8-af52-57e5c2aa8e54" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by delivery location\r\n**Visualizes counts (per {Granularity}) of malware detections of inbound emails by delivery location: Quarantine or Failed (rejected with or without NDR)**" + }, + "name": "text - Malware Delivery Location header", + "id": "95be7f48-40eb-4154-91d8-20f7033f2ff5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections over time summarizing the data daily by Delivery Location\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Malware' and EmailDirection == 'Inbound'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalMalwareDetections=count(), Quarantine=countif(DeliveryLocation == 'Quarantine'), Failed=countif(DeliveryLocation == 'Failed') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, TotalMalwareDetections=coalesce(TotalMalwareDetections,0), Quarantine=coalesce(Quarantine,0), Failed=coalesce(Failed,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "TotalMalwareDetections", + "color": "blue" + }, + { + "seriesName": "Quarantine", + "color": "orangeDark" + }, + { + "seriesName": "Failed", + "color": "redDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 10", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b2c19e58-2123-490b-9631-c0b238c582e6" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by Detection Technology\r\n**Visualizes counts (per {Granularity}) of Malware detections of inbound emails by various Microsoft Defender for Office 365 detection technologies.**" + }, + "name": "text - Malware Detection Technology header", + "id": "f3c2691e-4f32-4109-9524-8a11719e4425" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections over time summarizing the data daily by various Malware detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Malware'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand MalwareMethod = ParsedMethods.Malware\r\n| summarize Count = count() by MalwareMethod = tostring(MalwareMethod), Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct MalwareMethod | extend d = 1) on d | project Timestamp, MalwareMethod\r\n| join kind=leftouter (agg) on Timestamp, MalwareMethod\r\n| project Timestamp, MalwareMethod, Count = coalesce(Count, 0)\r\n| sort by MalwareMethod asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 8", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f00c1ce0-e55e-44c0-8bf0-4af662ccef89" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by various Malware detection technologies/controls in Microsoft Defender for Office 365.\r\nEmailEvents \r\n| where DetectionMethods has 'Malware'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand MalwareMethod = ParsedMethods.Malware\r\n| summarize Count = count() by MalwareMethod = tostring(MalwareMethod)\r\n| sort by Count desc\r\n| project ['Detection Technology'] = MalwareMethod, ['Detections'] = Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "34", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 2", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "590880a9-1cf7-44ae-b4de-2f65bc700b5d" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by SenderIPv4 Geo Location\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Malware, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" + }, + "name": "text - Malware Geo Location header", + "id": "19d78b48-af58-4bee-abfe-57efb1eba125" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by email sender IP address (SenderIPv4).\r\nEmailEvents \r\n| where ThreatTypes has 'Malware' and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_", + "size": 0, + "showAnalytics": true, + "title": "Malware Detections-Sender Heatmap (IPv4)", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "map", + "gridSettings": { + "sortBy": [ + { + "itemKey": "count_", + "sortOrder": 2 + } + ] + }, + "sortBy": [ + { + "itemKey": "count_", + "sortOrder": 2 + } + ], + "mapSettings": { + "locInfo": "LatLong", + "locInfoColumn": "GeoInfo", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "none" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 1", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8cb46ec0-ac2a-41d1-bf8a-0b8585d1fefc" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where ThreatTypes has 'Malware' and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Malware Emails'] = count_\r\n| sort by ['Malware Emails'] desc\r\n\r\n\r\n", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Malware Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "mapSettings": { + "locInfo": "LatLong", + "locInfoColumn": "GeoInfo", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "heatmap", + "heatmapPalette": "red" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 1 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b6a0355a-2b8f-48a5-8edc-58f4f7f8180a" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "Malware-Detectiontech-Deliverylocation-SendingInfra", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "2692cb5e-825c-45c1-bd3a-096b55e8d760" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Malware Detections Top attacked users and top senders\r\n
\r\n\r\nThis section consolidates key visuals that track and explain malware detections in inbound email as identified by Microsoft Defender for Office 365 focusing on top attacked users and top senders. \r\n

**Recommended action:** Apply the Strict preset security policy to the most-attacked users and consider adding persistent malicious sender domains to the Tenant Allow/Block List." + }, + "name": "banner - Malware Top Users Senders", + "id": "bc5b37a4-71e4-4a2f-b0ba-b3dd87333391" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections top attacked users\r\n**Displays the top 10 recipient email addresses that received inbound emails flagged as Malware. These users may be at higher risk and should be prioritised for targeted cybersecurity awareness training. Training should cover the specific threat types and techniques they are exposed to, and reinforce best practices for promptly reporting any suspicious messages that might bypass security controls and reach their inbox.**" + }, + "customWidth": "100", + "name": "text - Malware Top Users header", + "id": "cb87a026-ad03-45cc-887e-ab460490d9a5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails with Malware detections summarizing the data by the top 15 recipient email address (RecipientEmailAddress).\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),MalwareEmailCount = countif(ThreatTypes has \"Malware\") by RecipientEmailAddress\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(MalwareEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| where MalwareEmailCount !=0\r\n| top 15 by MalwareEmailCount\r\n| project ['Recipient'] = RecipientEmailAddress, ['Malware Emails'] = MalwareEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Malware Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - Malware Top Recipients", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e7ffef62-f85e-4188-8ab9-d90a5c666c30" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains with Malware Detections (Inbound)\r\n**Displays the top 10 sender domains sending inbound emails detected as Malware. Helps identify external sources most frequently associated with malicious content for prioritised threat monitoring and mitigation.**" + }, + "customWidth": "100", + "name": "text - Malware Top Senders header", + "id": "93390807-25b2-4bea-9648-98e821da8ec6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by the top 15 email sender P2 domain (SenderFromDomain). Adding additional insights for total inbound emails and bad traffic percentage for each sender domain.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount = count(), MalwareEmailCount = countif(ThreatTypes has \"Malware\") by SenderFromDomain\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(MalwareEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| where MalwareEmailCount !=0\r\n| top 15 by MalwareEmailCount\r\n| project ['Sender Domain'] = SenderFromDomain, ['Malware Emails'] = MalwareEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Malware Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal", + "useGrouping": false + } + } + }, + { + "columnMatch": "BadEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - Malware Top Sender Domains", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "eaa45734-2df2-4a5e-b35b-1295e00cb46f" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "MalwareTopAttackedUser-TopSenders", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "4e0900ab-e7e4-4cf1-93a4-7e86bca20782" + }, + { + "type": 1, + "content": { + "json": "# Phishing Detection Insights\r\n\r\n---\r\nThis tab provides insights into email message **detections** by Microsoft Defender for Office 365 where the message contained a **Phishing threat** within its **email content**, **URLs**, or **attachments**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "text - 24", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "fe82d665-fa9e-4fc2-9ba9-7e2eabb9a04b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//KPI summary of inbound email phishing detections for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet ph = EmailEvents | where EmailDirection == \"Inbound\" | where ThreatTypes has \"Phish\";\r\nlet inbox = ph | where DeliveryLocation has \"Inbox\";\r\nlet phTrend = toscalar(ph | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet inboxTrend = toscalar(inbox | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(ph | summarize count()), Details = \"Phish Emails\", Ord = 1, Trend = phTrend),\r\n(print Count = toscalar(ph | summarize dcount(RecipientEmailAddress)), Details = \"Users Targeted\", Ord = 2, Trend = phTrend),\r\n(print Count = toscalar(ph | summarize dcount(SenderFromDomain)), Details = \"Sender Domains\", Ord = 3, Trend = phTrend),\r\n(print Count = toscalar(inbox | summarize count()), Details = \"Delivered to Inbox\", Ord = 4, Trend = inboxTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "phish kpi strip", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5debf0b8-4384-485b-8a7f-71ead592718a" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Phishing Detection Trend, LLM Content Analysis, Advanced Threats, and Threat Classes\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Phish detections in inbound email as identified by Microsoft Defender for Office 365 focusing on per-{Granularity} trends, advanced threat detections, LLM-based content analysis, and threat classes.

**Recommended action:** Review the LLM-classified phishing themes; enable Safe Links and impersonation protection, and prioritise awareness training on the dominant lure types." + }, + "name": "text - Phish Section1 Banner", + "id": "ce5e489f-c83b-4bc8-9e63-b08dfb5ef31f" + }, + { + "type": 1, + "content": { + "json": "### Phish Detection Trend
\r\n\r\n**This visual displays a per-{Granularity} trend of email Phish detections identified by Microsoft Defender for Office 365. The area chart summarises the number of messages flagged for Phish threats.**" + }, + "name": "text - Phish Trend Header", + "id": "429ef4d2-61a9-40d0-940f-2212ddce22ce" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections over time summarizing the data daily.\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has \"Phish\"\r\n| summarize PhishDetections = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, PhishDetections = coalesce(PhishDetections, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "PhishDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b0d170ec-331c-4ad0-8ce6-258704cc5345" + }, + { + "type": 1, + "content": { + "json": "### Phish Detection Trend - Advanced Threats
\r\n\r\n**Not all threats are easily recognizable, which is why Microsoft Defender for Office 365 uses advanced detection methods, including virtual sandbox environments to detonate URLs and files. These virtual sandbox technologies look for known patterns, such as a recognisable login page in a URL, or a file accessing command and control infrastructure. This visual displays a per-{Granularity} trend of Phish detections of these advanced threats.**" + }, + "name": "text - Phish AdvThreats Header", + "id": "425476e0-066a-42ee-afb9-5dabc612a3c8" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections over time summarizing the data daily by Phish detection technologies/controls used for detecting unknown-unique phish.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| project Timestamp, RecipientEmailAddress, NetworkMessageId, DT=parse_json(DetectionMethods)\r\n| evaluate bag_unpack(DT)\r\n| summarize [\"File detonation\"]=countif(Phish has 'File detonation' and Phish !has 'File detonation reputation'), [\"URL detonation\"]=countif(Phish has 'URL detonation' and Phish !has 'URL detonation reputation') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, [\"File detonation\"]=coalesce([\"File detonation\"],0), [\"URL detonation\"]=coalesce([\"URL detonation\"],0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "URL detonation", + "color": "orangeDark" + }, + { + "seriesName": "File detonation", + "color": "redDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish AdvThreats Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6b62347a-b162-49e6-891c-07697af22dd9" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - LLM content analysis
\r\n\r\n**Microsoft Defender for Office 365 uses Language AI for Phish and Business Email Compromise (BEC) detection. These models are progressively learning from thousands of real-world phishing attempts and analyzing all messages classified as phish. Furthermore, it incorporates advanced Machine Learning and Natural Language Processing (NLP) techniques to read, process, and understand email content the way a human analyst might, yet in a fraction of the time and at a large scale. [Learn more](https://techcommunity.microsoft.com/blog/microsoftdefenderforoffice365blog/microsoft-defender-for-office-365s-language-ai-for-phish-enhancing-email-securit/4410446)**" + }, + "customWidth": "50", + "name": "text - Phish LLM Content Header", + "id": "c23460b1-e025-4f6c-b2d5-3f78c0c9afc6" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - LLM Threat Classifications
\r\n\r\n**Microsoft Defender for Office 365 uses purpose-built Large Language Models (LLM) at scale to provide AI-powered email and collaboration security. Our solution now parses language to understand and identify attacker intent and classifies threats at machine speed – keeping malicious emails out of your inbox and giving security operations (SOC) teams a new level of insight into adversary techniques. [Learn more](https://techcommunity.microsoft.com/blog/microsoftdefenderforoffice365blog/microsoft-ignite-redefining-email-security-with-llms-to-tackle-a-new-era-of-soci/4302421)**" + }, + "customWidth": "50", + "name": "text - Phish LLM ThreatClass Header", + "id": "1d723c26-501f-4385-9331-957ab7ae5019" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails detected as Phish by LLM content analysis detection technology in Microsoft Defender for Office 365. \r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has 'Phish' and DetectionMethods contains \"LLM content analysis\"\r\n| summarize count()\r\n| sort by count_ desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "statSettings": { + "valueAggregation": "None", + "colorSettings": { + "type": "thresholds", + "mode": "foreground", + "thresholdsGrid": [ + { + "operator": ">", + "thresholdValue": "0", + "representation": "red" + }, + { + "operator": "<=", + "thresholdValue": "0", + "representation": "red" + } + ] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "tagText": "", + "valueFontStyle": "auto", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish LLM Content Count", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "86a301c5-2bc0-436a-982c-861beee7c9ab" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by intent of the message.\r\n// Microsoft Defender for Office 365 LLM analysis is analyzing email messages to understand the intent of the messages. These threat classifications are then used in filtering decisions.\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has 'Phish' and ThreatClassification has_any(\"Business intelligence\",\"Contact establishment\",\"Gift card\",\"Invoice\",\"Payroll\",\"PII gathering\",\"Task\")\r\n| summarize count() by ThreatClassification\r\n| sort by count_ desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish LLM ThreatClass Pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d547b730-f174-4f78-8998-02f24453304e" + }, + { + "type": 1, + "content": { + "json": "### Top Attacked Users by LLM Threat classes (Phish)
\r\n\r\n**Displays recipients most frequently targeted by inbound phishing emails, grouped by threat classification (e.g., Gift Card, Invoice, Payroll). Helps identify users at higher risk for phishing attacks. These users may be at higher risk and should be prioritised for targeted cybersecurity awareness training. Training should cover the specific threat types and techniques they are exposed to, and reinforce best practices for promptly reporting any suspicious messages that might bypass security controls and reach their inbox.**" + }, + "customWidth": "100", + "name": "text - Phish LLM TopUsers Header", + "id": "4ba9d9eb-d88d-4e5d-ba58-a740559677f7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Phish detections in emails summarizing by various Threat classes showing the top attacked user for each threat classification type.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has \"Phish\" and EmailDirection == \"Inbound\" and ThreatClassification has_any(\"Business intelligence\",\"Contact establishment\",\"Gift card\",\"Invoice\",\"Payroll\",\"PII gathering\",\"Task\")\r\n| summarize EmailCount=count() by ThreatClassification, RecipientEmailAddress\r\n| summarize Emails = arg_max(EmailCount, RecipientEmailAddress) by ThreatClassification\r\n| sort by Emails desc\r\n| project ['Threat Classification'] = ThreatClassification, ['Top Recipient'] = RecipientEmailAddress, ['Emails'] = Emails", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "80px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish LLM TopUsers", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "51599ab2-db69-4195-b4e9-2828729ec35b" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "group - 5", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "25c47f6a-3525-435e-90cf-357f02fb2fed" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Phish Detections by Delivery location, Detection technology and Sender infrastructure insights\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Phish detections delivery locations, detection technologies used for detections, sender infrastructure insights in inbound email identified by Microsoft Defender for Office 365 as Phish.

**Recommended action:** Verify anti-phishing and Safe Links policies cover these delivery paths; consider blocking sender infrastructure from regions you do not operate in, where appropriate." + }, + "name": "text - Phish Section2 Banner", + "id": "6876063e-6a4f-48ea-829d-4486922783dd" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections by delivery location
\r\n\r\n**Visualizes counts (per {Granularity}) of Phish detections of inbound emails by various delivery locations: Quarantine, Junk folder or Failed (rejected with or without NDR)**" + }, + "name": "text - Phish DeliveryLoc Header", + "id": "b5045aab-1b4b-4d35-af41-a6315d36e864" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections over time summarizing the data daily by Delivery Location.\r\n//The comment in the query excludes deliveries to the SecOps Mailboxes and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\" and EmailDirection == \"Inbound\"\r\n| summarize TotalPhishDetections=count(), Quarantine=countif(DeliveryLocation == \"Quarantine\"), Junkfolder=countif(DeliveryLocation == \"Junk folder\"), Inbox=countif(DeliveryLocation == \"Inbox/folder\"), Failed=countif(DeliveryLocation == \"Failed\"), Dropped=countif(DeliveryLocation == \"Dropped\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, TotalPhishDetections=coalesce(TotalPhishDetections,0), Quarantine=coalesce(Quarantine,0), Junkfolder=coalesce(Junkfolder,0), Inbox=coalesce(Inbox,0), Failed=coalesce(Failed,0), Dropped=coalesce(Dropped,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Quarantine", + "color": "greenDark" + }, + { + "seriesName": "Failed", + "color": "green" + }, + { + "seriesName": "Dropped", + "color": "green" + }, + { + "seriesName": "Junk folder", + "color": "orangeDark" + }, + { + "seriesName": "Inbox", + "color": "redBright" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish DeliveryLoc Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e839848c-d176-4251-bbb4-1c2e1103ed2d" + }, + { + "type": 1, + "content": { + "json": "### Phish detections by Detection Technology
\r\n\r\n**Visualizes counts (per {Granularity}) of Phish detections of inbound emails by various Microsoft Defender for Office 365 detection technologies.**" + }, + "name": "text - Phish DetTech Header", + "id": "149bf1b3-80cc-4e82-ae5d-ddee0f6b0cd9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections over time summarizing the data daily by various Phish Detection technologies/controls in Microsoft Defender for Office 365.\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "createOtherGroup": 15 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish DetTech Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b0b16329-e1a6-4138-871e-76d57a60b978" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarized by individual Phish detection technology/control in Microsoft Defender for Office 365.\r\n//Each detection technology is counted individually via mv-expand over DetectionMethods.Phish (matching the sibling trend line chart), so a message flagged by multiple techniques counts once per technique.\r\n//The where clause excludes deliveries to the SecOps Mailbox and by the Phish Simulation system.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details\r\n| sort by Count desc\r\n| project ['Detection Technology'] = Details, ['Detections'] = Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish DetTech Pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5270ba04-599f-4940-805b-687f7475bc70" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections by SenderIPv4 Geo Location
\r\n\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Phish, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" + }, + "name": "text - Phish Geo Header", + "id": "ddd0c12f-1bb1-4d7d-afb4-f28bcfcd7c4b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by email sender IP address (SenderIPv4).\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has \"Phish\" and isnotempty(SenderIPv4)\r\n| summarize count() by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "map", + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "none" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish Geo Map", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "85ea7223-7d77-43f5-b0d9-e0de7c898758" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where ThreatTypes has 'Phish' and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Phish Emails'] = count_\r\n| sort by ['Phish Emails'] desc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Phish Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "heatmap", + "heatmapPalette": "red" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish Country Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f561209b-15a6-442e-af10-63e375088209" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "group - 25- Phish delivery locations-detecion tech-sender infra", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "10f3e3eb-b330-4955-952e-01eff69405e9" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Phish Detections Top attacked users and top senders\r\n
\r\n\r\nThis section consolidates key visuals that track and explain phish detections in inbound email as identified by Microsoft Defender for Office 365 focusing on top attacked users and top senders.

**Recommended action:** Enroll the most-targeted users in security awareness training and consider blocking persistent phishing sender domains." + }, + "name": "text - Phish Section3 Banner", + "id": "f46ed4a8-e2b5-4ccd-ae38-efc571bfc791" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections top attacked users\r\n**Displays the top 10 recipient email addresses that received inbound emails flagged as Phish. These users may be at higher risk and should be prioritised for targeted cybersecurity awareness training. Training should cover the specific threat types and techniques they are exposed to, and reinforce best practices for promptly reporting any suspicious messages that might bypass security controls and reach their inbox.**" + }, + "customWidth": "100", + "name": "text - Phish TopUsers Header", + "id": "96d9b543-070a-42d4-bbed-3f5cf79ca7ce" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails with Phish detections summarizing the data by the top 15 recipient email address (RecipientEmailAddress).\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),PhishEmailCount = countif(ThreatTypes has \"Phish\") by RecipientEmailAddress\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(PhishEmailCount / todouble(TotalEmailCount) * 100, 2))\r\n| where PhishEmailCount !=0\r\n| top 15 by PhishEmailCount\r\n| project ['Recipient'] = RecipientEmailAddress, ['Phish Emails'] = PhishEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Phish Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish TopRecipients Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "25100115-78d3-4144-b44e-613b44f02484" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains with Phish Detections (Inbound)\r\n**Displays the top 10 sender domains sending inbound emails detected as Phish. Helps identify external sources most frequently associated with malicious content for prioritised threat monitoring and mitigation.**" + }, + "customWidth": "100", + "name": "text - Phish TopSenders Header", + "id": "e7fcb7fe-4bca-4153-a9b0-8ded135b1c64" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by the top 15 email sender P2 domain (SenderFromDomain), now including the Phish confidence split (High/Normal) and the aggregated phish detection methods seen per domain. Adding additional insights for total inbound emails and bad traffic percentage for each sender domain.\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where EmailDirection == \"Inbound\"\r\n| extend PhishConf = tostring(parse_json(ConfidenceLevel).Phish)\r\n| extend PhishMethods = parse_json(DetectionMethods).Phish\r\n| summarize TotalEmailCount = count(),\r\n PhishEmailCount = countif(ThreatTypes has \"Phish\"),\r\n Phish_High = countif(ThreatTypes has \"Phish\" and PhishConf == \"High\"),\r\n Phish_Normal = countif(ThreatTypes has \"Phish\" and PhishConf == \"Normal\"),\r\n PhishMethodSet = make_set_if(PhishMethods, ThreatTypes has \"Phish\") by SenderFromDomain\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(PhishEmailCount / todouble(TotalEmailCount) * 100, 2))\r\n| where PhishEmailCount != 0\r\n| top 15 by PhishEmailCount\r\n| mv-apply S = PhishMethodSet on ( mv-expand m = S to typeof(string) | summarize Methods = make_set(m) )\r\n| project ['Sender Domain'] = SenderFromDomain, ['Phish Emails'] = PhishEmailCount, ['Phish (High)'] = Phish_High, ['Phish (Normal)'] = Phish_Normal, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound, ['Detection Methods'] = strcat_array(Methods, \", \")", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Phish Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish (High)", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish (Normal)", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "BadEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish TopSenders Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "717bfce8-b5d4-4900-99db-4ba0c503591d" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "group - 26-PhishDetectionsTopattackedusers-topsenders", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "553afca2-caa1-45b1-bec0-dca426b5be46" + }, + { + "type": 1, + "content": { + "json": "# Spam Detection Insights\r\n\r\n---\r\nThis tab provides insights into email message **detections** by Microsoft Defender for Office 365 where the message contained a **Spam threat** within its **email content**, **URLs**, or **attachments**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "4" + }, + "name": "text - Spam Tab Intro", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a693a05a-a772-4ac4-9863-07ad0d1b7092" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//KPI summary of inbound email spam detections for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet sp = EmailEvents | where EmailDirection == \"Inbound\" | where ThreatTypes has \"Spam\";\r\nlet junk = sp | where DeliveryLocation has \"Junk\";\r\nlet spTrend = toscalar(sp | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet junkTrend = toscalar(junk | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(sp | summarize count()), Details = \"Spam Emails\", Ord = 1, Trend = spTrend),\r\n(print Count = toscalar(sp | summarize dcount(RecipientEmailAddress)), Details = \"Users Targeted\", Ord = 2, Trend = spTrend),\r\n(print Count = toscalar(sp | summarize dcount(SenderFromDomain)), Details = \"Sender Domains\", Ord = 3, Trend = spTrend),\r\n(print Count = toscalar(junk | summarize count()), Details = \"Sent to Junk\", Ord = 4, Trend = junkTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "4" + }, + "name": "spam kpi strip", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "cadd5331-1db8-4ac8-bc99-42cd5227ee51" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Spam Detection Effectiveness and Trends\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Spam detections in inbound email as identified by Microsoft Defender for Office 365 focusing on Effectiveness and per-{Granularity} trend. For effectiveness, we consider messages reported by your admins and decisions made post-delivery.

**Recommended action:** If legitimate mail is marked as spam, review the Spam and Bulk thresholds; if spam is leaking through, tighten them." + }, + "name": "text - Spam Section1 Banner", + "id": "1093f3b6-cea7-4f54-9029-f9aadd79ca9f" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query calculates the effectiveness of spam detections without edge data.\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\n// baseQuery _FN_Admin_Submissions_SPM\r\nlet _FN_Admin_Submissions_SPM = toscalar(\r\nCloudAppEvents\r\n| where Timestamp between (minTime .. maxTime)\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType)\r\n| extend NetworkMessageId = tostring((parse_json(RawEventData)).ObjectId)\r\n| where SubmissionType in (\"0\")\r\n| summarize count()\r\n);\r\n// baseQuery _FN_ZAP_Successful_Spam\r\nlet _FN_ZAP_Successful_Spam = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and ActionType == \"Spam ZAP\" and ActionResult == \"Success\" and Timestamp between (minTime .. maxTime)\r\n| summarize count()\r\n //Take all our Spam ZAP, and count how many messages we missed and successfully cleaned up.\r\n);\r\n// baseQuery _FN_ZAP_Unsuccessful_Spam\r\nlet _FN_ZAP_Unsuccessful_Spam = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and ActionType == \"Spam ZAP\" and ActionResult != \"Success\" and Timestamp between (minTime .. maxTime)\r\n| summarize count()\r\n//Take all our Spam ZAP, and count how many messages we failed to clean up due to error or users/admins/API vendors getting to the message first.\r\n);\r\n// baseQuery _SPAM_ZAP_FP\r\nlet _SPAM_ZAP_FP = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and Action has_any (\"Redelivery\",\"Reprocessed\") and Timestamp between (minTime .. maxTime)\r\n| join kind=leftsemi (\r\n EmailEvents\r\n | where Timestamp between (minTime ..maxTime )\r\n | where ThreatTypes contains \"Spam\"\r\n | project NetworkMessageId, ThreatTypes)\r\n on NetworkMessageId\r\n| summarize count()\r\n// count all the FPs which were originally Spam, and when we TT'd them were not so we can subtract that from our mailfow catch, and therefore the total true bad.\r\n);\r\n// baseQuery _Spam_Mailflow\r\nlet _Spam_Mailflow = toscalar(\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and ThreatTypes == \"Spam\" and Timestamp between (minTime .. maxTime)\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count()\r\n// Get all the mailflow detected as SPM, then count all the NMIDs (not distinct)\r\n);\r\nprint\r\nEffectiveness_PostDelivery = abs(round(((toreal(toscalar(_FN_Admin_Submissions_SPM))+toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)))/(toreal(toscalar(_Spam_Mailflow))+toreal(toscalar(_FN_ZAP_Successful_Spam))+toreal(toscalar(_FN_ZAP_Unsuccessful_Spam))+toreal(toscalar(_FN_Admin_Submissions_SPM))-toreal(toscalar(_SPAM_ZAP_FP)))*100-100),2))", + "size": 1, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "statSettings": { + "valueAggregation": "None", + "colorSettings": { + "type": "thresholds", + "mode": "foreground", + "heatmapPalette": "greenRed", + "thresholdsGrid": [ + { + "operator": ">", + "thresholdValue": "95", + "representation": "green" + }, + { + "operator": "<=", + "thresholdValue": "95", + "representation": "orange" + }, + { + "operator": "<=", + "thresholdValue": "90", + "representation": "red" + } + ] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "numberFormatSettings": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "tagText": "Spam Effectiveness (without Edge data)", + "valueFontStyle": "superLarge", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Effectiveness Stat", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "036851c1-489e-4fda-8059-850c161578b3" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\n// baseQuery _FN_Admin_Submissions_SPM\r\nlet _FN_Admin_Submissions_SPM = toscalar(\r\nCloudAppEvents\r\n| where Timestamp between (minTime .. maxTime)\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType)\r\n| extend NetworkMessageId = tostring((parse_json(RawEventData)).ObjectId)\r\n| where SubmissionType in (\"0\")\r\n| summarize count()\r\n);\r\n// baseQuery _FN_ZAP_Successful_Spam\r\nlet _FN_ZAP_Successful_Spam = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and ActionType == \"Spam ZAP\" and ActionResult == \"Success\" and Timestamp between (minTime .. maxTime)\r\n| summarize count()\r\n //Take all our Spam ZAP, and count how many messages we missed and successfully cleaned up.\r\n);\r\n// baseQuery _FN_ZAP_Unsuccessful_Spam\r\nlet _FN_ZAP_Unsuccessful_Spam = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and ActionType == \"Spam ZAP\" and ActionResult != \"Success\" and Timestamp between (minTime .. maxTime)\r\n| summarize count()\r\n//Take all our Spam ZAP, and count how many messages we failed to clean up due to error or users/admins/API vendors getting to the message first.\r\n);\r\n// baseQuery _SPAM_ZAP_FP\r\nlet _SPAM_ZAP_FP = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and Action has_any (\"Redelivery\",\"Reprocessed\") and Timestamp between (minTime .. maxTime)\r\n| join kind=leftsemi (\r\n EmailEvents\r\n | where Timestamp between (minTime ..maxTime )\r\n | where ThreatTypes contains \"Spam\"\r\n | project NetworkMessageId, ThreatTypes)\r\n on NetworkMessageId\r\n| summarize count()\r\n// count all the FPs which were originally Spam, and when we TT'd them were not so we can subtract that from our mailfow catch, and therefore the total true bad.\r\n);\r\n// baseQuery _Spam_Mailflow\r\nlet _Spam_Mailflow = toscalar(\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and ThreatTypes == \"Spam\" and Timestamp between (minTime .. maxTime)\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count()\r\n// Get all the mailflow detected as SPM, then count all the NMIDs (not distinct)\r\n);\r\nprint StatisticName=\"Spam Mailflow Minus FPs\", Value=toreal((toscalar(_Spam_Mailflow)) - toreal(toscalar(_SPAM_ZAP_FP)))\r\n| union (print StatisticName=\"Spam Admin FNs Submitted\", Value=toreal(toscalar(_FN_Admin_Submissions_SPM)))\r\n| union (print StatisticName=\"Spam FPs Reverse Zapped\", Value=toreal(toscalar(_SPAM_ZAP_FP)))\r\n| union (print StatisticName=\"Spam Zapped Successfully\", Value=toreal(toscalar(_FN_ZAP_Successful_Spam)))\r\n| union (print StatisticName=\"Spam NotZapped\", Value=toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)))\r\n| union (print StatisticName=\"Spam Effectiveness Post Delivery %\", Value=abs(round(((toreal(toscalar(_FN_Admin_Submissions_SPM)) + toreal(toscalar(_FN_ZAP_Unsuccessful_Spam))) / (toreal(toscalar(_Spam_Mailflow)) + toreal(toscalar(_FN_ZAP_Successful_Spam)) + toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)) + toreal(toscalar(_FN_Admin_Submissions_SPM)) - toreal(toscalar(_SPAM_ZAP_FP)))) * 100 - 100, 2)))\r\n| union (print StatisticName=\"Spam Effectiveness Pre-Delivery %\", Value=abs(round(((toreal(toscalar(_FN_Admin_Submissions_SPM)) + toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)) + (toscalar(_FN_ZAP_Successful_Spam))) / (toreal(toscalar(_Spam_Mailflow)) + toreal(toscalar(_FN_ZAP_Successful_Spam)) + toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)) + toreal(toscalar(_FN_Admin_Submissions_SPM)) - toreal(toscalar(_SPAM_ZAP_FP)))) * 100 - 100, 2 )))\r\n| project ['Statistic'] = StatisticName, Value", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "tileSettings": { + "showBorder": false, + "titleContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Value", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Value", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 2 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Effectiveness Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8d456ea2-f04a-4d71-95c6-fbaad8c2d2f2" + } + ] + }, + "customWidth": "100", + "name": "Spam Effectiveness", + "id": "82812b88-e7f7-4be0-9d13-8e7a7d8c0c4e" + }, + { + "type": 1, + "content": { + "json": "### Spam Detection Trend
\r\n\r\n**This visual displays a per-{Granularity} trend of email Spam detections identified by Microsoft Defender for Office 365. The area chart summarises the number of messages flagged for Spam threats.**" + }, + "name": "text - Spam Trend Header", + "id": "b5574a88-430b-4cca-a76e-9a0b07e9da2e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where ThreatTypes has \"Spam\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, SpamDetections = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "SpamDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "09b7d330-1683-45c4-ac0e-8141580d13b5" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "4" + }, + "name": "group - 6-Spam-detections-trend", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "25273f47-8201-4565-8815-1d059ee8abb6" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Spam Detections by Delivery location, Detection technology, Sender infrastructure and Bulk insights\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Spam detections delivery locations, detection technologies used for detections, sender infrastructure and Bulk insights in inbound email identified by Microsoft Defender for Office 365 as Spam.

**Recommended action:** Raise the Bulk Complaint Level (BCL) threshold for noisy sender domains and consider blocking high-volume, low-value bulk senders where appropriate." + }, + "name": "text - Spam Section2 Banner", + "id": "b82f442b-a3a0-44f7-82df-2fd4a9594992" + }, + { + "type": 1, + "content": { + "json": "### Spam Detections by delivery location
\r\n\r\n**Visualizes counts (per {Granularity}) of Spam detections of inbound emails by various delivery locations Quarantine, Junk folder or Failed (rejected with or without NDR)**" + }, + "name": "text - Spam DeliveryLoc Header", + "id": "a6326d97-56cc-45fb-8019-e0c3346968f2" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections over time summarizing the data daily by Delivery Location.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Spam\" and EmailDirection == \"Inbound\"\r\n| summarize TotalSpamDetections=count(), Quarantine=countif(DeliveryLocation == \"Quarantine\"), Junkfolder=countif(DeliveryLocation == \"Junk folder\"), Inbox=countif(DeliveryLocation == \"Inbox/folder\"), Failed=countif(DeliveryLocation == \"Failed\"), Dropped=countif(DeliveryLocation == \"Dropped\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, TotalSpamDetections=coalesce(TotalSpamDetections,0), Quarantine=coalesce(Quarantine,0), Junkfolder=coalesce(Junkfolder,0), Inbox=coalesce(Inbox,0), Failed=coalesce(Failed,0), Dropped=coalesce(Dropped,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "TotalSpamDetections", + "color": "blue" + }, + { + "seriesName": "Quarantine", + "color": "greenDark" + }, + { + "seriesName": "Junkfolder", + "color": "orangeDark" + }, + { + "seriesName": "Inbox", + "color": "redBright" + }, + { + "seriesName": "Failed", + "color": "red" + }, + { + "seriesName": "Dropped", + "color": "redDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam DeliveryLoc Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "97f89032-34e3-40ff-bb88-42d195aea095" + }, + { + "type": 1, + "content": { + "json": "### Spam Detections Detection Technology
\r\n\r\n**Visualizes counts (per {Granularity}) of Spam detections of inbound emails by various Microsoft Defender for Office 365 detection technologies.**" + }, + "name": "text - Spam DetTech Header", + "id": "935ea90d-8430-49d5-b942-3a7b319a603e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections over time summarizing the data daily by various Spam Detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where DetectionMethods has \"Spam\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| mv-expand Details = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam DetTech Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f31ec0d1-04e1-4b2b-9b98-27289ca34b84" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections summarized by individual Spam detection technology/control in Microsoft Defender for Office 365.\r\n//Each technique is counted individually via mv-expand over DetectionMethods.Spam (matching the sibling trend line chart), so a message flagged by multiple techniques counts once per technique.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Spam\"\r\n| mv-expand Details = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details\r\n| sort by Count desc\r\n| project ['Detection Technology'] = Details, ['Detections'] = Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam DetTech Pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "95e40479-f0bc-41ff-8191-634b606d3632" + }, + { + "type": 1, + "content": { + "json": "### Spam Detections by SenderIPv4 Geo Location
\r\n\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Spam, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" + }, + "name": "text - Spam Geo Header", + "id": "614d1c3f-df6a-4659-b170-7b466c66d66f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections summarizing the data by email sender IP address (SenderIPv4).\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where ThreatTypes has \"Spam\" and isnotempty(SenderIPv4)\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_ ", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "map", + "mapSettings": { + "locInfo": "LatLong", + "locInfoColumn": "SenderIPv4", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "none" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Geo Map", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5519d715-dc79-45f8-8ed5-a63a253c45e3" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where ThreatTypes has 'Spam' and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Spam Emails'] = count_\r\n| sort by ['Spam Emails'] desc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spam Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "mapSettings": { + "locInfo": "LatLong", + "locInfoColumn": "SenderIPv4", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "heatmap", + "heatmapPalette": "red" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Country Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5078dc24-e8be-4943-98fc-6527968e1e3d" + }, + { + "type": 1, + "content": { + "json": "### Spam Detections Bulk Insights
\r\n\r\n**Displays the distribution of inbound emails across different Bulk Complaint Levels together with Top 10 domains sending Bulk email (grey mail). Helps identify patterns in bulk email complaints and assess potential spam or unwanted message trends.**" + }, + "name": "text - Spam Bulk Header", + "id": "cd7b3cbe-a6c1-422c-ab37-4afc26002d5d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails which has any Bulk complaint level. It is summarizing the data by the various Bulk Complaint levels to understand how many messages are detected with each Bulk Complaint level.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\" and isnotnull(BulkComplaintLevel)\r\n| summarize count() by BulkComplaintLevel\r\n| sort by BulkComplaintLevel desc\r\n| project ['Bulk Complaint Level'] = BulkComplaintLevel, Emails=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "blueDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Bulk By Level", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "021c022b-aa67-427d-9e1a-688af7aed5d4" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails which has any Bulk complaint level. It is summarizing the data by the various Bulk Complaint levels and SenderFromDomain of the email sender. It provides insights how many messages are detected with each Bulk Complaint level for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\" and isnotnull(BulkComplaintLevel)\r\n| summarize count() by BulkComplaintLevel, SenderFromDomain\r\n| top 10 by count_ desc\r\n| project ['Sender Domain'] = SenderFromDomain, ['Bulk Complaint Level'] = BulkComplaintLevel, Emails=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Bulk By Domain", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b1835e0f-f9ad-44c3-bba4-cf9a9546d09a" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "4" + }, + "name": "group - 28-Spam-Delivery location-Detection technology-Sender infrastructure insights", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "307d3d03-93ae-4c8f-b68b-f833ee7d38e8" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n\r\n
Spam Detections Top attacked users and top senders\r\n
\r\n\r\nThis section consolidates key visuals that track and explain spam detections in inbound email as identified by Microsoft Defender for Office 365 focusing on top attacked users and top senders.

**Recommended action:** Review the most-affected users and the top spam sender domains as possible block-list candidates." + }, + "name": "text - Spam Section3 Banner", + "id": "4c34ed7b-86da-4ee1-8a69-f96c213a4340" + }, + { + "type": 1, + "content": { + "json": "### Spam Detections top attacked users
\r\n\r\n**Displays the top 10 recipient email addresses that received inbound emails flagged as Spam. These users may be at higher risk and should be prioritised for targeted cybersecurity awareness training. Training should cover the specific threat types and techniques they are exposed to, and reinforce best practices for promptly reporting any suspicious messages that might bypass security controls and reach their inbox.**" + }, + "customWidth": "100", + "name": "text - Spam TopUsers Header", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "be708ad5-51fd-4a54-b1bc-f912e12b4a01" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails with Spam detections summarizing the data by the top 15 recipient email address (RecipientEmailAddress).\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where EmailDirection ==\"Inbound\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),SpamEmailCount = countif(ThreatTypes has \"Spam\") by RecipientEmailAddress\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(SpamEmailCount / todouble(TotalEmailCount)* 100, 2))\r\n| where SpamEmailCount !=0\r\n| top 15 by SpamEmailCount\r\n| project ['Recipient'] = RecipientEmailAddress, ['Spam Emails'] = SpamEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spam Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "40ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal", + "useGrouping": false + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam TopRecipients Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6e7b357d-6792-41c5-83fc-efae31afe2ee" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains with Spam Detections (Inbound)
\r\n\r\n**Displays the top 10 sender domains sending inbound emails detected as Spam. Helps identify external sources most frequently associated with spam content for prioritised monitoring and mitigation.**" + }, + "customWidth": "100", + "name": "text - Spam TopSenders Header", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1d1bdb8d-9619-488b-935a-3791ad73f096" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails with Spam detections summarizing the data by the top 15 email sender P2 domain (SenderFromDomain). Adding additional insights for total inbound emails and bad traffic percentage for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where EmailDirection == \"Inbound\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount = count(),\r\n SpamEmailCount = countif(ThreatTypes has \"Spam\") by SenderFromDomain\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(SpamEmailCount / todouble(TotalEmailCount) * 100, 2))\r\n| where SpamEmailCount !=0\r\n| top 15 by SpamEmailCount\r\n| project ['Sender Domain'] = SenderFromDomain, ['Spam Emails'] = SpamEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spam Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "40ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam TopSenders Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "253efada-ca89-49c5-b1e3-e42ac005b938" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "4" + }, + "name": "group - 29-Spam Detections Top attacked users and top senders", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "d4cc057f-c9b7-40b9-85d3-52f90767d1f5" + }, + { + "type": 1, + "content": { + "json": "# Email Impersonation & BEC Insights\r\n\r\n---\r\nThis tab focuses on the highest-value email threat class: **impersonation and Business Email Compromise (BEC)**. It brings together impersonation and spoof detections, sender authentication (DMARC, DKIM, SPF, CompAuth), supply-chain and partner-compromise correlation, and first-contact / new-vendor senders - the signals that precede targeted financial and credential attacks. It is the email-side companion to the impersonation insights on the **Teams & Collaboration** tab." + }, + "name": "text - impersonation bec description", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "id": "fda8ccd5-fafc-457a-a6a2-05b504be1023" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//KPI summary of inbound email impersonation and spoof (BEC) detections for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet bec = EmailEvents | where EmailDirection == \"Inbound\" | where DetectionMethods has \"Impersonation\" or DetectionMethods has \"Spoof\";\r\nlet inbox = bec | where DeliveryLocation has \"Inbox\";\r\nlet becTrend = toscalar(bec | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet inboxTrend = toscalar(inbox | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(bec | summarize count()), Details = \"Impersonation / Spoof Emails\", Ord = 1, Trend = becTrend),\r\n(print Count = toscalar(bec | summarize dcount(RecipientEmailAddress)), Details = \"Users Targeted\", Ord = 2, Trend = becTrend),\r\n(print Count = toscalar(bec | summarize dcount(SenderFromDomain)), Details = \"Spoofed Sender Domains\", Ord = 3, Trend = becTrend),\r\n(print Count = toscalar(inbox | summarize count()), Details = \"Delivered to Inbox\", Ord = 4, Trend = inboxTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "name": "bec kpi strip", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "91fdd28f-31c4-4f94-b60a-12cd97d44ddf" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Phish Detections Business Email Compromise (BEC) detections\r\n
\r\n\r\nThis section consolidates key visuals that track and explain phish detections in inbound email as identified by Microsoft Defender for Office 365 focusing on Business Email Compromise (BEC) detections Impersonation and Spoof.

**Recommended action:** Enable mailbox intelligence and impersonation protection for frequently-impersonated users and domains; consider adding confirmed look-alike domains to the Tenant Block List." + }, + "name": "text - Phish BEC Banner", + "id": "e3b2232c-8056-4913-a652-64f70e228750" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Impersonation detections Trend\r\n**Displays counts (per {Granularity}) of inbound emails flagged for Business Email Compromise (BEC) using Impersonation detection methods by Microsoft Defender for Office 365. Helps track impersonation attack patterns over time.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Imp Trend Header", + "id": "e95667df-3bcd-4023-9e8f-99ed05bc4bf0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Impersonation detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has 'Impersonation'\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ImpersonationDetections = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "ImpersonationDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Imp Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "61fa166d-f300-42a6-a324-de18b3fdf4c1" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Impersonation detections by Detection Technology\r\n**Visualizes counts (per {Granularity}) of Phish detections of inbound emails by various Microsoft Defender for Office 365 detection technologies used for detecting Impersonations.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Imp Tech Header", + "id": "09e1a866-f344-4a92-a3bd-8c3c3c5d598d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Impersonation detections over time summarizing the data daily by various Impersonation Detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where Details has \"Impersonation\"\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Imp Tech Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6cd5662f-13b4-4a9b-afe7-0a6343e3ab5c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish - Business Email Compromise (BEC) - Impersonation detections summarized by individual detection technology/control in Microsoft Defender for Office 365.\r\n//Each technique is counted individually via mv-expand over DetectionMethods.Phish (matching the sibling trend line chart), so a message flagged by multiple techniques counts once per technique.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where Details has \"Impersonation\"\r\n| summarize Count = count() by Details\r\n| sort by Count desc\r\n| project ['Detection Technology'] = Details, ['Detections'] = Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "graphSettings": { + "type": 0 + }, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Imp Tech Pie", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "73499618-e842-440e-a555-cd8849093884" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Impersonation detections by SenderIPv4 Geo Location\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Phish - Impersonation, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Imp Geo Header", + "id": "189a1ac1-f275-4697-880b-7ffae1e5d263" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Impersonation detections summarizing the data by email sender IP address (SenderIPv4).\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Impersonation\" and isnotempty(SenderIPv4)\r\n//| project Timestamp, EmailDirection, SenderFromAddress, AdditionalFields, SenderIPv4 \r\n| summarize count()by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_ ", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "map", + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "none" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish BEC Imp Geo Map", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "574b61ad-ec2d-4517-93c5-d0e9bd14f2e9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where DetectionMethods has \"Impersonation\" and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Impersonation Emails'] = count_\r\n| sort by ['Impersonation Emails'] desc", + "size": 0, + "showAnalytics": true, + "title": "Impersonation Detections-Sender Heatmap (IPv4)", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Impersonation Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "heatmap", + "heatmapPalette": "red" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish BEC Imp Country", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e53b7dbc-4683-4309-b879-c7be68599159" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Spoof detections Trend\r\n**Displays counts (per {Granularity}) of inbound emails flagged for Business Email Compromise (BEC) using Spoof detection methods by Microsoft Defender for Office 365. Helps track Spoofing based attack patterns over time.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Spoof Trend Header", + "id": "8db0f1b0-49bf-43a2-9f9f-164eb9530629" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Spoof detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has 'Spoof'\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, SpoofDetections = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "SpoofDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Spoof Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "9a308cd9-bf05-4287-b0d5-54636d081a82" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Spoof detections Trend by Detection Technology\r\n**Visualizes counts (per {Granularity}) of Phish detections of inbound emails by various Microsoft Defender for Office 365 detection technologies used for detecting Spoofing.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Spoof Tech Header", + "id": "28c9c15d-d22f-4412-9efc-868b95082668" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Spoof detections over time summarizing the data daily by various Spoof Detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where Details has \"Spoof\"\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "yAxis": [ + "Count" + ], + "seriesLabelSettings": [ + { + "seriesName": "[\"Spoof external domain\"]", + "color": "redDark" + }, + { + "seriesName": "[\"Spoof intra-org\"]", + "color": "orangeDark" + }, + { + "seriesName": "[\"Spoof DMARC\"]", + "color": "yellowDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Spoof Tech Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1a1328fc-5404-4dff-99ed-3a30082a4cbe" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish - Business Email Compromise (BEC) - Spoof detections summarized by individual detection technology/control in Microsoft Defender for Office 365.\r\n//Each technique is counted individually via mv-expand over DetectionMethods.Phish (matching the sibling trend line chart), so a message flagged by multiple techniques counts once per technique.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where Details has \"Spoof\"\r\n| summarize Count = count() by Details\r\n| sort by Count desc\r\n| project ['Detection Technology'] = Details, ['Detections'] = Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Spoof Tech Pie", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "f7df9892-85b4-49c3-8739-873b745183a3" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Spoof detections by SenderIPv4 Geo Location\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Phish - Spoofing, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Spoof Geo Header", + "id": "3c83e7f0-5391-4b1a-bb5b-de0d17488efd" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Spoof detections summarizing the data by email sender IP address (SenderIPv4).\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Spoof\" and isnotempty(SenderIPv4)\r\n//| project Timestamp, EmailDirection, SenderFromAddress, AdditionalFields, SenderIPv4 \r\n| summarize count()by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_ ", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "map", + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "none" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish BEC Spoof Geo Map", + "styleSettings": { + "margin": "15px", + "padding": "15px" + }, + "id": "122d860c-ab0d-475e-b29e-2955020680c7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where DetectionMethods has \"Spoof\" and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Spoof Emails'] = count_\r\n| sort by ['Spoof Emails'] desc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spoof Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "heatmap", + "heatmapPalette": "red" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish BEC Spoof Country", + "styleSettings": { + "margin": "15px", + "padding": "15px" + }, + "id": "9d0111bc-8d01-4a99-9009-645dc02c3bed" + }, + { + "type": 1, + "content": { + "json": "### Supply-Chain & Partner Risk (Possible Partner Compromise)\r\n**Correlates the external domains your organization emails most with inbound emails from those same domains that carried threats. A trusted partner or supplier domain suddenly sending threats is a strong signal that the partner may be compromised - a common supply-chain and business email compromise (BEC) vector.**

**Recommended action:** Verify any flagged partner through a trusted channel before acting on their recent messages, alert them to a possible compromise, and consider tightening inbound policy for that domain until confirmed clean." + }, + "customWidth": "100", + "name": "text - Phish Partner Compromise Header", + "id": "2c62c576-3b05-4663-ae2e-4f961d7409c6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises top outbound recipient domains by outbound email volume and shows total number of inbound emails with Threats from the same domains (as inbound senders) \r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Outbound\"\r\n| project RecipientDomain = tostring(split(RecipientEmailAddress, \"@\")[1])\r\n| summarize count() by RecipientDomain\r\n| project OutboundCount=count_, RecipientDomain, SenderFromDomain=RecipientDomain\r\n| join (EmailEvents | where EmailDirection == \"Inbound\" and isempty(ThreatTypes)==false) on SenderFromDomain\r\n| summarize max(OutboundCount),count() by SenderFromDomain\r\n| project SenderFromDomain, OutboundEmails=max_OutboundCount, IncomingEmailsWithThreats=count_\r\n| extend Bad_Traffic_Percentage = todouble(round(IncomingEmailsWithThreats / todouble(OutboundEmails) * 100, 2))\r\n| top 15 by OutboundEmails\r\n| project ['Sender Domain'] = SenderFromDomain, ['Outbound Emails'] = OutboundEmails, ['Inbound w/ Threats'] = IncomingEmailsWithThreats, ['Bad Traffic %'] = Bad_Traffic_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Outbound Emails", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Inbound w/ Threats", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "60ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish Partner Compromise", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1aaa047c-1108-4288-833e-61ca35b5495a" + }, + { + "type": 1, + "content": { + "json": "### Top Recipients Targeted by Impersonation / BEC\r\n**Lists the recipients most frequently targeted by impersonation and Business Email Compromise (BEC) attempts, showing the number of impersonation emails, how many distinct senders were involved, the top spoofed sender domains, and how many of those messages were delivered to the inbox. Helps identify high-risk users (often executives or finance staff) who may need extra protection or awareness.**" + }, + "customWidth": "100", + "name": "text - impersonation targets", + "id": "b1e7c2a4-9f3d-4a6b-8c12-7d5e9f0a1b23" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top recipients targeted by impersonation / BEC, with distinct senders, spoofed domains and how many landed in the inbox.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| where OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")\r\n| where DetectionMethods has \"Impersonation\"\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize ImpersonationEmails = count(),\r\n DistinctSenders = dcount(SenderFromAddress),\r\n TopSpoofedDomains = make_set(SenderFromDomain, 5),\r\n DeliveredToInbox = countif(DeliveryLocation has \"Inbox\")\r\n by RecipientEmailAddress\r\n| top 20 by ImpersonationEmails\r\n| project ['Recipient'] = RecipientEmailAddress, ['Impersonation Emails'] = ImpersonationEmails, ['Distinct Senders'] = DistinctSenders, ['Top Spoofed Domains'] = strcat_array(TopSpoofedDomains, \", \"), ['Delivered to Inbox'] = DeliveredToInbox", + "size": 0, + "title": "Top Recipients Targeted by Impersonation / BEC", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "showAnalytics": true, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Impersonation Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "name": "newviz - impersonation targets", + "id": "afe28369-af82-47ae-846d-179bd86b660e" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "name": "group - 7 - Phish-BEC-Insights", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "b7971cd9-d086-47c7-8f66-50956b9c56c3" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Phish Detections Sender Authentication details (DMARC, DKIM, SPF, CompAuth)\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Sender Authentication checks details in inbound email by Microsoft Defender for Office 365 focusing on the various Sender Authentication standards: DMARC, DKIM, SPF, CompAuth.

**Recommended action:** For domains failing DMARC/DKIM/SPF, verify your own outbound authentication is published and enforced (p=reject), and treat persistent external spoofers as possible block candidates." + }, + "name": "text - Phish Section5 Banner", + "id": "90d7a338-d943-4398-b788-bfd4f93007d4" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections Sender Authentication Trend (DMARC, DKIM, SPF, CompAuth)\r\n**Shows counts (per {Granularity}) of sender authentication check outcomes (DMARC, DKIM, SPF, CompAuth) performed by Microsoft Defender for Office 365 on inbound emails. Useful for monitoring authentication success and failure patterns over time to identify anomalies or potential phishing risks.**" + }, + "customWidth": "100", + "name": "text - Phish SenderAuth Trend Header", + "id": "4a0ab90e-55dd-4fa6-82c3-0edc57ce0966" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spoof- DMARC fails summarizing the data daily.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend DMARCFail = (tostring(parse_json(AuthenticationDetails).DMARC) == \"fail\") \r\n| summarize DMARCFail = sum(DMARCFail) by bin (Timestamp,{Granularity})", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "DMARCFail", + "color": "orangeDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish Auth DMARC Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "79920d30-01d4-4412-b994-853e50c9d7d8" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spoof- DKIM fails summarizing the data daily.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend DKIMFail = (tostring(parse_json(AuthenticationDetails).DKIM) == \"fail\") \r\n| summarize DKIMFail = sum(DKIMFail) by bin (Timestamp,{Granularity})", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "DKIMFail", + "color": "yellowDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish Auth DKIM Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "bf09ffd4-eee0-42f7-a507-1cf54d9c365a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spoof- SPF fails summarizing the data daily.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend SPFFail = (tostring(parse_json(AuthenticationDetails).SPF) == \"fail\") \r\n| summarize SPFFail = sum(SPFFail) by bin (Timestamp,{Granularity})", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "SPFFail", + "color": "purpleDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish Auth SPF Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "4d66fe13-9904-45cf-8783-f3ee984f3a66" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spoof- Composite Authentication fails summarizing the data daily.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend CompAuthFail = (tostring(parse_json(AuthenticationDetails).CompAuth) == \"fail\") \r\n| summarize CompAuthFail = sum(CompAuthFail) by bin (Timestamp,{Granularity})", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "CompAuthFail", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish Auth CompAuth Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "0968b828-23fe-4fa2-a5ea-8ab39362457f" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections Top Sender Domains with DMARC Failures (Inbound)\r\n**Displays the top 10 sender domains (P1 and P2) for inbound emails where Spoof-DMARC detection triggered. Includes total inbound email volume and calculates DMARC fail traffic percentage per domain to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "text - Phish Auth DMARC Domains Header", + "id": "24d4689a-eb6d-49f5-85a8-fcadca409f7a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spoof-DMARC fails detections summarizing the data by the top 10 email sender P2 domain (SenderFromDomain) and sender P1 domain (SenderMailFromDomain). Adding additional insights for total inbound emails and DMARC fail traffic percentage for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalEmailCount = count(),\r\n DMARCFailCount = countif(set_has_element(parse_json(DetectionMethods).Phish, \"Spoof DMARC\")) by P1Sender=SenderMailFromDomain, P2Sender=SenderFromDomain\r\n| extend DMARCFail_Traffic_Percentage = todouble(round(DMARCFailCount / todouble(TotalEmailCount) * 100, 2))\r\n| where DMARCFailCount !=0\r\n| top 10 by DMARCFailCount\r\n| project ['P1 Sender'] = P1Sender, ['P2 Sender'] = P2Sender, ['DMARC Failures'] = DMARCFailCount, ['Total Inbound'] = TotalEmailCount, ['DMARC Fail %'] = DMARCFail_Traffic_Percentage", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "DMARCFail", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "DMARC Fail %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "40ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish Auth DMARC Domains", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "642814ad-9d24-4be9-ae10-3578e89da05b" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections Top Sender Domains with Spoof External Domain Detections (Inbound)\r\n**Displays the top 10 sender domains (P1 and P2) for inbound emails flagged for Spoof External Domain detection. Includes total inbound email volume and calculates spoof traffic percentage per domain to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "text - Phish Auth SpoofExt Domains Header", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "993fdc34-354b-412e-be39-facbde4f4f0e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish-Spoof-external domain detections summarizing the data by the top 10 email sender P2 domain (SenderFromDomain) and sender P1 domain (SenderMailFromDomain). Adding additional insights for total inbound emails and Spoof external domain detection traffic percentage for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalEmailCount = count(),\r\n SpoofExternalCount = countif(set_has_element(parse_json(DetectionMethods).Phish, \"Spoof external domain\")) by P1Sender=SenderMailFromDomain, P2Sender=SenderFromDomain\r\n| extend SpoofExternal_Traffic_Percentage = todouble(round(SpoofExternalCount / todouble(TotalEmailCount) * 100, 2))\r\n| where SpoofExternalCount !=0\r\n| top 10 by SpoofExternalCount\r\n| project ['P1 Sender'] = P1Sender, ['P2 Sender'] = P2Sender, ['Spoof External'] = SpoofExternalCount, ['Total Inbound'] = TotalEmailCount, ['Spoof External %'] = SpoofExternal_Traffic_Percentage", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spoof External", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spoof External %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "40ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "SpoofExternalFail", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true, + "sortBy": [ + { + "itemKey": "Spoof External %", + "sortOrder": 2 + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish Auth SpoofExt Domains", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "69ca3799-d2d5-4896-b3a5-1eeba46f0b46" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections Top Sender Domains with Spoof Internal Domain Detections (Inbound)\r\n**Displays the top 10 sender domains (P1 and P2) for inbound emails flagged for Spoof Internal Domain detection. Includes total inbound email volume and calculates spoof traffic percentage per domain to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "text - Phish Auth SpoofInt Domains Header", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3fa33c5d-0eba-471f-b47f-0c12c1f770d6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish-Spoof-internal domain detections summarizing the data by the top 10 email sender P2 domain (SenderFromDomain) and sender P1 domain (SenderMailFromDomain). Adding additional insights for total inbound emails and Spoof internal domain detection traffic percentage for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalEmailCount = count(),\r\n SpoofInternalCount = countif(set_has_element(parse_json(DetectionMethods).Phish, \"Spoof intra-org\")) by P1Sender=SenderMailFromDomain, P2Sender=SenderFromDomain\r\n| extend SpoofInternal_Traffic_Percentage = todouble(round(SpoofInternalCount / todouble(TotalEmailCount) * 100, 2))\r\n| where SpoofInternalCount !=0\r\n| top 10 by SpoofInternalCount\r\n| project ['P1 Sender'] = P1Sender, ['P2 Sender'] = P2Sender, ['Spoof Internal'] = SpoofInternalCount, ['Total Inbound'] = TotalEmailCount, ['Spoof Internal %'] = SpoofInternal_Traffic_Percentage", + "size": 3, + "showAnalytics": true, + "title": "Top 10 Spoof intra-org detections by Sender domain (P1/P2)", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spoof Internal", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spoof Internal %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "40ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "SpoofIntraorgFail", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish Auth SpoofInt Domains", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "ae0c65c7-68ea-4d50-b177-1effeaf1c045" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "name": "group - 8-Phish-SenderAuth", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "8077779a-4da8-46be-8032-626bd8c36dbd" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
First-Contact & New-Vendor Senders\r\n
\r\n\r\nExternal email senders and domains seen for the first time in the selected period. New/first-contact relationships - especially ones already carrying threats - are a common precursor to phishing, business email compromise (BEC), and supply-chain attacks.

**Recommended action:** Treat brand-new domains sending threats as high-priority review; verify any that claim to be a known brand or partner before trusting their messages." + }, + "name": "phish fc banner", + "id": "05b83435-c7ed-48a3-919e-388b2e599726" + }, + { + "type": 1, + "content": { + "json": "### First-contact external senders
\r\n\r\n**External email senders ordered by when they were first seen in the period (most recent first). In tenants with longer history this highlights genuinely new senders.**" + }, + "customWidth": "100", + "name": "phish fc senders header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "c57dffb4-dfdb-4a1e-93be-16fa9e856a0d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists external email senders seen for the first time in the selected period (most recent first), surfacing new/first-contact senders. In tenants with longer history this highlights genuinely new relationships - a common precursor to BEC and supply-chain attacks.\r\n// TIP: to hide your own accepted domains, uncomment the ExcludeDomains line and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"fabrikam.com\"]);\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| extend SenderDomain = tostring(split(SenderFromAddress, \"@\")[1])\r\n| where isnotempty(SenderFromAddress)\r\n//| where SenderDomain !in~ (ExcludeDomains)\r\n| summarize FirstSeen=min(Timestamp), Messages=count(), ThreatMessages=countif(isnotempty(ThreatTypes)) by SenderFromAddress, SenderDomain\r\n| top 20 by FirstSeen desc\r\n| project ['Sender']=SenderFromAddress, ['Sender Domain']=SenderDomain, ['First Seen']=FirstSeen, Messages, ['Threat Messages']=ThreatMessages", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "phish fc senders table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d1ceb0ac-2dad-49af-b416-a3376a7b8513" + }, + { + "type": 1, + "content": { + "json": "### New sender domains carrying threats
\r\n\r\n**External sender domains seen for the first time in the period that already carried threats, most-recent first. A brand-new domain sending threats to your users is a strong early-warning signal.**" + }, + "customWidth": "100", + "name": "phish fc domains header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "bd29bbe4-cde2-499c-a1d0-e2cc51f7733d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists external sender domains seen for the first time in the selected period that already carried threats, ranked by most-recently first seen. A brand-new domain sending threats to your users is a strong early-warning signal for phishing and BEC.\r\n// TIP: to hide your own accepted domains, uncomment the ExcludeDomains line and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"fabrikam.com\"]);\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| extend SenderDomain = tostring(split(SenderFromAddress, \"@\")[1])\r\n| where isnotempty(SenderDomain)\r\n//| where SenderDomain !in~ (ExcludeDomains)\r\n| summarize FirstSeen=min(Timestamp), LastSeen=max(Timestamp), Messages=count(), Senders=dcount(SenderFromAddress), Recipients=dcount(RecipientEmailAddress), ThreatMessages=countif(isnotempty(ThreatTypes)) by SenderDomain\r\n| where ThreatMessages > 0\r\n| top 20 by FirstSeen desc\r\n| project ['Sender Domain']=SenderDomain, ['First Seen']=FirstSeen, Messages, Senders, Recipients, ['Threat Messages']=ThreatMessages, ['Last Seen']=LastSeen", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Senders", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Recipients", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "phish fc domains table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "7da952d5-5ae2-4b2e-a5cf-c78b11bda4f8" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "customWidth": "100", + "name": "group - Phish First Contact", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "90e5248a-2c35-48f3-869c-c45c631c6fbf" + }, + { + "type": 1, + "content": { + "json": "# URL Detections and URL Click Insights\r\n\r\n---\r\nThis tab provides insights into **URL-based detections** in email messages and details about URL clicks performed by end users on URLs identified as **malicious**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "5" + }, + "name": "text - 24 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "2156430d-fec6-48bb-a9a8-3166182f6993" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//KPI summary of URL threat protection (Safe Links clicks and URLs seen in email) for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet clicks = UrlClickEvents;\r\nlet blocked = clicks | where ActionType in (\"ClickBlocked\",\"ClickBlockedByTenantPolicy\");\r\nlet allowed = clicks | where ActionType == \"ClickAllowed\";\r\nlet blockedTrend = toscalar(blocked | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet allowedTrend = toscalar(allowed | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet usersTrend = toscalar(clicks | make-series Trend = dcount(AccountUpn) default = 0 on Timestamp step gran | project Trend);\r\nlet urlsTrend = toscalar(EmailUrlInfo | make-series Trend = dcount(Url) default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(blocked | summarize count()), Details = \"Malicious Clicks Blocked\", Ord = 1, Trend = blockedTrend),\r\n(print Count = toscalar(allowed | summarize count()), Details = \"Clicks Allowed Through\", Ord = 2, Trend = allowedTrend),\r\n(print Count = toscalar(clicks | summarize dcount(AccountUpn)), Details = \"Users Clicking Links\", Ord = 3, Trend = usersTrend),\r\n(print Count = toscalar(EmailUrlInfo | summarize dcount(Url)), Details = \"Distinct URLs in Email\", Ord = 4, Trend = urlsTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "5" + }, + "name": "url kpi strip", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d5e2326a-a5dd-4217-bb75-0e337d75d306" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Insights on URL-Based Threat Detections\r\n
\r\n\r\nThis section consolidates key visuals that track and explain URL based threat detections in inbound email as identified by Microsoft Defender for Office 365 focusing on per-{Granularity} trends of URL-based threat detections, QR code detections, and URL scans activity by locations.

**Recommended action:** Confirm Safe Links is enabled for email and Teams; investigate QR-code and URL detection spikes for emerging campaigns." + }, + "name": "text - 13 - Copy", + "id": "ed3468e7-1936-45fd-9168-93010a662302" + }, + { + "type": 1, + "content": { + "json": "### Trend of URL-Based Malware Threat Detections
\r\n\r\n**This visual displays a per-{Granularity} trend of emails with URL based Malware threat detections identified by Microsoft Defender for Office 365. The line chart summarises the number of messages flagged for malware threats.**" + }, + "name": "text - 13 - Copy - Copy", + "id": "77e7bbac-d752-478b-bce9-06bb1bd12bfe" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections over time summarizing the data daily by various Malware URL threat based detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Malware'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand MalwareMethod = ParsedMethods.Malware\r\n| where MalwareMethod contains \"URL\"\r\n| summarize Count = count() by MalwareMethod = tostring(MalwareMethod), Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct MalwareMethod | extend d = 1) on d | project Timestamp, MalwareMethod\r\n| join kind=leftouter (agg) on Timestamp, MalwareMethod\r\n| project Timestamp, MalwareMethod, Count = coalesce(Count, 0)\r\n| sort by MalwareMethod asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 8 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "79ef5e7b-57a6-4519-9899-18fd8cae5e68" + }, + { + "type": 1, + "content": { + "json": "### Trend of URL-Based Phish Threat Detections
\r\n\r\n**This visual displays a per-{Granularity} trend of emails with URL based Phish threat detections identified by Microsoft Defender for Office 365. The line chart summarises the number of messages flagged for Phish threats.**" + }, + "name": "text - 13 - Copy - Copy - Copy", + "id": "48923812-5440-4f47-8881-273f14cbfb8e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phishing detections over time summarizing the data daily by various Phishing URL threat based detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Phish'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand PhishMethod = ParsedMethods.Phish\r\n| where PhishMethod contains \"URL\"\r\n| summarize Count = count() by PhishMethod = tostring(PhishMethod), Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct PhishMethod | extend d = 1) on d | project Timestamp, PhishMethod\r\n| join kind=leftouter (agg) on Timestamp, PhishMethod\r\n| project Timestamp, PhishMethod, Count = coalesce(Count, 0)\r\n| sort by PhishMethod asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 8 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b983b361-6c2e-47d5-b2c5-edd9caa6a55d" + }, + { + "type": 1, + "content": { + "json": "### Trend (per {Granularity}) of QR Code-Based Threat Detections
\r\n\r\n**Displays counts (per {Granularity}) of inbound emails containing QR codes flagged for Phish, Malware, or Spam via URL-based detection methods. Helps track QR code abuse patterns over time.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3d8b75e1-6e1d-44eb-b1fc-78d3db7feb71" + }, + { + "type": 1, + "content": { + "json": "### URL Scan activity by Location (per {Granularity})
\r\n\r\n**Displays counts (per {Granularity}) of URLs scanned from various locations within emails (e.g., body, attachments, QR codes). Helps identify where malicious URLs are most commonly embedded.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b275b28c-e441-4c19-9055-256d5d45c69c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where EmailDirection == \"Inbound\" \r\n| where DetectionMethods has \"Url\"\r\n| join EmailUrlInfo on NetworkMessageId\r\n| where UrlLocation == \"QRCode\"\r\n| summarize [\"Phish QR Detection\"]=countif(parse_json(DetectionMethods).Phish has \"URL\"), [\"Malware QR Detection\"]=countif(parse_json(DetectionMethods).Malware has \"URL\"), [\"Spam QR Detection\"]=countif(parse_json(DetectionMethods).Spam has \"URL\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, [\"Phish QR Detection\"]=coalesce([\"Phish QR Detection\"],0), [\"Malware QR Detection\"]=coalesce([\"Malware QR Detection\"],0), [\"Spam QR Detection\"]=coalesce([\"Spam QR Detection\"],0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "graphSettings": { + "type": 0 + }, + "chartSettings": { + "xAxis": "Timestamp", + "xSettings": { + "dateFormatSettings": { + "formatName": "shortDatePattern", + "showUtcTime": false + } + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 6", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6c2a7724-d3c2-42b2-b8da-7acbcd0666c6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises where URL's have been scanned identified from various locations in emails\r\nEmailUrlInfo\r\n| summarize count() by UrlLocation", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 5", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5640dbd5-4085-4f2a-8fb9-e4112233e99e" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "5" + }, + "name": "group - 9-URL detections", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "b572d79b-17a0-48ac-9a43-4f20324cf998" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Insights on URL Click-Based Threat Detections\r\n
\r\n\r\nThis section consolidates key visuals that track and explain URL click based threat detections in emails as identified by Microsoft Defender for Office 365 focusing on per-{Granularity} trend of blocked URL clicks, time-of-click URL scans by workload, malicious clicks allowed, top clicks on malicious URLs, and more.

**Recommended action:** For blocked-click spikes, verify Safe Links is set to not allow click-through; investigate workloads with high click-through activity." + }, + "name": "text - 13 - Copy - Copy", + "id": "6d37617e-911e-4ce6-a10d-4749486738ea" + }, + { + "type": 1, + "content": { + "json": "### Trend (per {Granularity}) of Blocked URL Click Events
\r\n\r\n**Shows the count (per {Granularity}) of blocked URL click attempts and click attempts on URLs with detections, grouped by threat types (e.g., Phish, Malware, Spam). Helps track user interaction with malicious links over time across various threat types.**" + }, + "name": "text - 13 - Copy - Copy - Copy", + "id": "9e477950-bedc-4cc0-9863-df07d124806c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// Generates a time-series analysis for blocked URL click events from the 'UrlClickEvents' table\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(UrlClickEvents\r\n| where isnotempty(ActionType)\r\n| where ActionType has_any(\"ClickBlocked\")\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, BlockedClicks = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "BlockedClicks", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "query - 4", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "366e80d9-f6ed-43af-91e5-3d04cdcf692d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of click attempts on URL's with detections split by the different threat types identified\r\nUrlClickEvents\r\n| where isnotempty(ThreatTypes)\r\n| summarize count() by ThreatTypes", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "query - 4", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a356eac3-62c2-4fc9-a4d9-3b05b13848df" + }, + { + "type": 1, + "content": { + "json": "### Trend (per {Granularity}) of URL Click Actions by Type
\r\n\r\n**Displays counts (per {Granularity}) of URL click events categorised by action type: Blocked, Allowed, Pending Verdict, Error Page, and Clicked Through. Helps identify risky user behaviour and policy gaps.**" + }, + "customWidth": "66", + "name": "text - 13 - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a91fe7a6-f507-48f7-bbcc-61dc4f998ba6" + }, + { + "type": 1, + "content": { + "json": "### URL Clicks by Workload
\r\n\r\n**Displays counts (per {Granularity}) of URL click events grouped by Workload (e.g., Outlook, Teams, Copilot, Office Apps: Word, Excel, PowerPoint) Helps identify which applications are most frequently used for URL interactions and potential risk exposure.**" + }, + "customWidth": "33", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "ce05fa08-6e68-4c02-a0bf-2be6cdfae935" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises different URL click event types by action (e.g., blocked, allowed, pending verdict, error pages, and clicked through), summarizing the data daily\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(UrlClickEvents\r\n| where isnotempty(ActionType)\r\n| summarize ClickBlocked=countif(ActionType has_any(\"ClickBlocked\")), ClickAllowed=countif(ActionType has_any(\"ClickAllowed\")), PendingVerdict=countif(ActionType has_any(\"UrlScanInProgress\")), ErrorPage=countif(ActionType has_any(\"UrlErrorPage\")), ClickedThrough=countif(IsClickedThrough == true) by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ClickBlocked=coalesce(ClickBlocked,0), ClickAllowed=coalesce(ClickAllowed,0), PendingVerdict=coalesce(PendingVerdict,0), ErrorPage=coalesce(ErrorPage,0), ClickedThrough=coalesce(ClickedThrough,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "query - 1", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a12b4c78-7d18-4adc-86e0-54395d6a996a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises where URL clicks scanned by the Workload the click happened from\r\nUrlClickEvents\r\n| summarize count() by Workload", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "query - 5 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3237cd55-1d5c-41a9-a8f2-1d46c61a709e" + }, + { + "type": 1, + "content": { + "json": "### Blocked URL Clicks by Workload (per {Granularity})
\r\n\r\n**Displays counts (per {Granularity}) of blocked URL click attempts grouped by Workload (Email, Teams, Office, Microsoft 365 Copilot). Helps identify which platforms are most exposed to malicious link interactions and where user awareness or policy enforcement should be strengthened.**" + }, + "customWidth": "66", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1f209a83-3d50-4bb8-9a79-a365a50a4142" + }, + { + "type": 1, + "content": { + "json": "### Click-Through Activity on Detected URLs by Workload
\r\n\r\n**Displays counts of click‑through actions on URLs already identified with detections, grouped by Workload where the click happened. Helps identify clients/platforms where users are most likely to proceed to risky URLs and prioritise awareness training or policy tuning for those workloads**" + }, + "customWidth": "33", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "33592db8-0ff5-4d8e-bd8f-0201b81a4584" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises blocked URL click event types by Workload (e.g., Email, Teams, Office, Microsoft 365 Copilot), summarizing the data daily\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(UrlClickEvents\r\n| where ActionType ==\"ClickBlocked\"\r\n| summarize Teams=countif(Workload==\"Teams\"), Office=countif(Workload==\"Office\"), Email=countif(Workload==\"Email\"), Copilot=countif(Workload==\"Copilot\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, Teams=coalesce(Teams,0), Office=coalesce(Office,0), Email=coalesce(Email,0), Copilot=coalesce(Copilot,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "query - 3", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "80241767-0f69-4e2e-9889-3bf1f48e4f02" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of click-through activities on URL's with detections split by the source client\r\nUrlClickEvents \r\n| where IsClickedThrough !=\"0\"\r\n| where isnotempty(ThreatTypes) \r\n| summarize count() by Workload", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "query - 2", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "fde29b46-2896-4bfc-bb61-09436696d738" + }, + { + "type": 1, + "content": { + "json": "### Top clicks on Malicious URLs
\r\n\r\n**Displays the top 20 URLs associated with detections that registered the highest number of clicks. Includes ThreatTypes, ActionType, and Workload to provide context on the nature of the threat and where user interaction occurred.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "22bda63a-626c-47de-9a76-ad665ef87862" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows the top 20 URL's that have a detection associated with the most ammount of clicks registered \r\nUrlClickEvents\r\n| where ThreatTypes !=\"\"\r\n| summarize count() by Url, ThreatTypes, ActionType, Workload\r\n| top 20 by count_\r\n| project ['URL']=Url, ['Threat Types']=ThreatTypes, ['Action Type']=ActionType, Workload, ['Click Count']=count_", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Click Count", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 10 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a044fd4e-7be6-4a11-974c-b54e417c2a81" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "5" + }, + "name": "group - 31-URL clicks", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "75e543f6-08c0-42ed-9869-ecd61b721d34" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Top Risky Users Clicking on URLs with Threats\r\n
\r\n\r\nThis section consolidates key visuals that track and identify users who have clicked on malicious URLs detected by Microsoft Defender for Office 365.

**Recommended action:** Enroll these users in security awareness training and verify Safe Links policy coverage for their mailboxes." + }, + "name": "text - 13 - Copy - Copy - Copy", + "id": "19487811-a94b-4537-877e-61ac7e287c21" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Users Clicking on URLs with Malware Threat
\r\n\r\n**Displays the top 10 user accounts with the highest number of click attempts on URLs flagged as Malware. Helps identify individuals at greater risk and prioritise targeted security awareness training.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "78e10621-0e98-44c4-8399-810c19f138c2" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top 10 users with click attempts on URL's with malware detections\r\nUrlClickEvents\r\n| summarize TotalClickCount=count(),MalwareClickCount = countif(ThreatTypes has \"Malware\") by AccountUpn\r\n| extend Bad_Click_Percentage = todouble(round(MalwareClickCount / todouble(TotalClickCount) *100, 2))\r\n| where MalwareClickCount !=0\r\n| sort by MalwareClickCount desc\r\n| top 15 by MalwareClickCount\r\n| project ['User']=AccountUpn, ['Malware Clicks']=MalwareClickCount, ['Total Clicks']=TotalClickCount, ['Bad Click %']=Bad_Click_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Malware Clicks", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "25ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Clicks", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Click %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "25ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "MalwareEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "TotalEmailCount", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad_Traffic_Percentage_Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 18 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a7ae8a75-ca7f-49be-8cad-d1451a3bd396" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Users Clicking on URLs with Phish Threat
\r\n\r\n**Displays the top 10 user accounts with the highest number of click attempts on URLs flagged as Phish. Helps identify individuals at greater risk and prioritise targeted security awareness training.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "90d9a0c3-970a-4998-be62-3b3b84bb0f37" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top 10 users with click attempts on URL's with Phish detections\r\nUrlClickEvents\r\n| summarize TotalClickCount=count(),PhishClickCount = countif(ThreatTypes has \"Phish\") by AccountUpn\r\n| extend Bad_Click_Percentage = todouble(round(PhishClickCount / todouble(TotalClickCount) *100, 2))\r\n| where PhishClickCount !=0\r\n| sort by PhishClickCount desc\r\n| top 15 by PhishClickCount\r\n| project ['User']=AccountUpn, ['Phish Clicks']=PhishClickCount, ['Total Clicks']=TotalClickCount, ['Bad Click %']=Bad_Click_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Phish Clicks", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "25ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Clicks", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Click %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "25ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "MalwareClickCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "MalwareEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "TotalEmailCount", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad_Traffic_Percentage_Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 18 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d46877d9-03af-463a-b406-bb4c601dffeb" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Users Clicking on URLs with Spam Threat
\r\n\r\n**Displays the top 10 user accounts with the highest number of click attempts on URLs flagged as Spam. Helps identify individuals at greater risk and prioritise targeted security awareness training.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "dc66e020-0932-4346-8e20-6a2dc78de7a9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top 10 users with click attempts on URL's with Spam detections\r\nUrlClickEvents\r\n| summarize TotalClickCount=count(),SpamClickCount = countif(ThreatTypes has \"Spam\") by AccountUpn\r\n| extend Bad_Click_Percentage = todouble(round(SpamClickCount / todouble(TotalClickCount) *100, 2))\r\n| where SpamClickCount !=0\r\n| sort by SpamClickCount desc\r\n| top 15 by SpamClickCount\r\n| project ['User']=AccountUpn, ['Spam Clicks']=SpamClickCount, ['Total Clicks']=TotalClickCount, ['Bad Click %']=Bad_Click_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spam Clicks", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "25ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Clicks", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Click %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "25ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "PhishClickCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "MalwareClickCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "MalwareEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "TotalEmailCount", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad_Traffic_Percentage_Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 18 - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "734ee45e-4dff-4ca1-b17d-02389086b17b" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "5" + }, + "name": "group - 32-Top clickers", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "ee6c3413-28be-49a1-a89d-bf5fce7acfa4" + }, + { + "type": 1, + "content": { + "json": "# Microsoft Teams Collaboration Protection\r\n\r\n---\r\nAs email defenses mature, attackers are shifting into **Microsoft Teams**, where messages bypass secure email gateways and carry the implicit trust of a colleague chat. Microsoft Threat Intelligence reports Teams-based phishing and voice phishing (vishing) rising steadily through 2026, most often as **IT help desk or technical-support impersonation** from external or newly-created tenants, used to steer users toward remote-access tools and credential theft.\r\n\r\nThis tab shows **Microsoft Defender for Office 365** protection for Microsoft Teams: threat detections and impersonation, suspicious external senders, malicious URLs and clicks, malicious files, post-delivery ZAP removals, and user and admin submissions across chats and channels.\r\n\r\n**Recommended action:** Treat unsolicited external help desk or IT support contact as suspicious. Restrict inbound chat from unmanaged and consumer tenants, allowlist trusted external domains, remove or restrict remote-support tools such as Quick Assist where they are not required, and enforce phishing-resistant MFA for all users (Conditional Access with authentication strength), prioritizing privileged and administrator accounts first.\r\n\r\n[

Disrupting threats targeting Microsoft Teams

](https://www.microsoft.com/en-us/security/blog/2025/10/07/disrupting-threats-targeting-microsoft-teams/)[

Cross-tenant helpdesk impersonation to data exfiltration: a human-operated intrusion playbook

](https://www.microsoft.com/en-us/security/blog/2026/04/18/crosstenant-helpdesk-impersonation-data-exfiltration-human-operated-intrusion-playbook/)[

Help on the line: how a Microsoft Teams support call led to compromise

](https://www.microsoft.com/en-us/security/blog/2026/03/16/help-on-the-line-how-a-microsoft-teams-support-call-led-to-compromise/)[

Email threat landscape: Q2 2026 trends and insights

](https://www.microsoft.com/en-us/security/blog/2026/07/23/email-threat-landscape-q2-2026-trends-and-insights/)" + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "text - teams description", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5c0f0100-0a11-4b22-9c33-000000000100" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Headline Microsoft Teams protection metrics for the selected period, with per-interval sparklines. Messages are de-duplicated to the latest record per Teams message.\r\nlet gran = {Granularity};\r\nlet msgs = materialize(MessageEvents | summarize arg_max(Timestamp, *) by TeamsMessageId);\r\nlet zap = materialize(MessagePostDeliveryEvents);\r\nunion\r\n(msgs | summarize Count = count() | extend Details = \"Teams Messages Scanned\", Ord = 1, Trend = toscalar(msgs | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where isnotempty(ThreatTypes) | summarize Count = count() | extend Details = \"Messages with Threats\", Ord = 2, Trend = toscalar(msgs | where isnotempty(ThreatTypes) | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where ThreatTypes has \"Phish\" | summarize Count = count() | extend Details = \"Phish Detections\", Ord = 3, Trend = toscalar(msgs | where ThreatTypes has \"Phish\" | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where ThreatTypes has \"Malware\" | summarize Count = count() | extend Details = \"Malware Detections\", Ord = 4, Trend = toscalar(msgs | where ThreatTypes has \"Malware\" | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where ThreatTypes has \"Spam\" | summarize Count = count() | extend Details = \"Spam Detections\", Ord = 5, Trend = toscalar(msgs | where ThreatTypes has \"Spam\" | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where SafetyTip == \"URLMessageWarning\" | summarize Count = count() | extend Details = \"Messages with URL Warning\", Ord = 6, Trend = toscalar(msgs | where SafetyTip == \"URLMessageWarning\" | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(zap | summarize Count = count() | extend Details = \"Post-Delivery ZAP Actions\", Ord = 7, Trend = toscalar(zap | make-series S = count() default = 0 on Timestamp step gran | project S))\r\n| sort by Ord asc\r\n| project Details, Count, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21 + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams kpi tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b2c476ca-4141-43b4-9d4e-98470aa432fc", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + } + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Microsoft Teams - Collaboration Protection Overview\r\n
\r\n\r\nMicrosoft Defender for Office 365 extends its protection to **Microsoft Teams**, detecting malicious messages, URLs, and files shared through chats and channels. This tab summarizes Teams message detections, link-safety warnings, post-delivery ZAP, file scanning, and user/admin submissions.

*Scope note: the Teams message tables surface metadata for external-conversation messages plus internal messages that contain URLs, so counts reflect that scope rather than the full volume of Teams messages.*" + }, + "name": "teams overview banner", + "id": "2f71360f-1673-480f-8361-5afc83aee67d" + }, + { + "type": 1, + "content": { + "json": "### Teams threat detections over time
\r\n\r\n**Volume (per selected interval) of Microsoft Teams messages detected with a threat by Microsoft Defender for Office 365. Spikes may indicate a targeted Teams-based campaign.**" + }, + "customWidth": "100", + "name": "teams trend header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "0ac71d4e-8ecb-4d17-9fd3-10754007ec07" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the number of Microsoft Teams messages detected with a threat over time, de-duplicated to the latest record per message and summarized per selected interval.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(MessageEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(MessageEvents | summarize max(Timestamp));\r\nlet agg = materialize(MessageEvents | where isnotempty(ThreatTypes) | summarize arg_max(Timestamp, *) by TeamsMessageId | summarize ThreatDetections = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ThreatDetections = coalesce(ThreatDetections, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "xAxis": "Timestamp", + "seriesLabelSettings": [ + { + "seriesName": "ThreatDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams detection trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "937f3bc6-21f5-4f4c-ab72-78f08f32c5bd" + }, + { + "type": 1, + "content": { + "json": "### Threat type breakdown
\r\n\r\n**Split of Microsoft Teams threat detections across Phish, Malware, and Spam.**" + }, + "customWidth": "50", + "name": "teams threat pie header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "645a39ae-843a-47db-8016-6082ef37744d" + }, + { + "type": 1, + "content": { + "json": "### Thread exposure
\r\n\r\n**De-duplicated Microsoft Teams messages split by whether the conversation includes external participants.**" + }, + "customWidth": "50", + "name": "teams thread header", + "id": "a1a48f9a-8593-4ab5-8824-5998c643e844" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query breaks down Microsoft Teams threat detections by threat type for the selected period, de-duplicated to the latest record per message. A message flagged for more than one threat type is counted under each, so the split can exceed the distinct message count.\r\nlet msgs = MessageEvents | where isnotempty(ThreatTypes) | summarize arg_max(Timestamp, *) by TeamsMessageId;\r\nunion\r\n(msgs | where ThreatTypes has \"Phish\" | summarize Count = count() | extend ThreatType = \"Phish\"),\r\n(msgs | where ThreatTypes has \"Malware\" | summarize Count = count() | extend ThreatType = \"Malware\"),\r\n(msgs | where ThreatTypes has \"Spam\" | summarize Count = count() | extend ThreatType = \"Spam\")\r\n| project ThreatType, Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams threat type pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "029b4ecc-cd95-4385-a251-8ab194add8f4" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows de-duplicated Microsoft Teams messages split by whether the thread includes external participants.\r\nMessageEvents\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| extend Thread = iif(IsExternalThread == true, \"External Thread\", \"Internal Thread\")\r\n| summarize Count = count() by Thread", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams thread pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1581f447-9b3e-4857-84b8-e78b5df65ac5" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Overview", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "283f36b2-5c54-4afe-9a87-33d4796bd5b7" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Teams Calls and Vishing (Voice Phishing)\r\n
\r\n\r\n**Voice phishing (vishing) over Microsoft Teams is the fastest-growing collaboration threat of 2026. Attackers impersonate IT help desk or support and call users directly, often after a chat lure, to talk them into granting remote access or entering credentials. Because a target must be online to answer, malicious calls cluster in working hours. This section surfaces Teams call activity, when calls happen, and callers using support or brand-impersonation identities.**

*Interim data source: Teams call activity is currently read from Microsoft Defender for Cloud Apps call telemetry (CloudAppEvents). The existing V4 logic retains this source while the dedicated CallActivityEvents implementation is evaluated separately.*

**Recommended action:** Treat unsolicited help desk or support calls as suspicious. Confirm any request through a known internal channel, and never grant remote access such as Quick Assist on the strength of an inbound Teams call. Restrict inbound calls and chat from unmanaged and consumer tenants." + }, + "customWidth": "100", + "name": "teams calls banner", + "id": "9815bdc9-9e10-4e84-9164-783092b4ccb0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Teams call and vishing headline metrics for the selected period, with per-interval sparklines. Interim source: Defender for Cloud Apps call telemetry (CloudAppEvents / CallParticipantDetail).\r\nlet gran = {Granularity};\r\nlet calls = materialize(CloudAppEvents | where ActionType == \"CallParticipantDetail\" | extend R = parse_json(RawEventData) | extend CallId = tostring(R.CallId), UId = tolower(tostring(R.UserId)));\r\nlet susp = calls | extend Local = tostring(split(UId, \"@\")[0]), Dom = tostring(split(UId, \"@\")[1]) | where Local matches regex @\"(?i)help ?desk|helpdesk|it ?support|service ?desk|sys ?admin|administrator|security|microsoft|google|apple|amazon|paypal|support|update|verif|account|password|mfa|maintenance\" or Dom endswith \".onmicrosoft.com\";\r\nlet reported = CloudAppEvents | where ActionType == \"CallReported\";\r\nunion\r\n(calls | summarize Count = dcount(CallId) | extend Details = \"Teams Calls\", Ord = 1, Trend = toscalar(calls | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(susp | summarize Count = dcount(UId) | extend Details = \"Impersonation-style Callers\", Ord = 2, Trend = toscalar(susp | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(reported | summarize Count = count() | extend Details = \"Reported Suspicious Calls\", Ord = 3, Trend = toscalar(reported | make-series S = count() default = 0 on Timestamp step gran | project S))\r\n| sort by Ord asc\r\n| project Details, Count, Trend", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21 + }, + "showBorder": true, + "size": "auto" + }, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams calls kpi", + "id": "be8946d9-1eae-405c-b8df-cee2242cb44d" + }, + { + "type": 1, + "content": { + "json": "### Teams call activity over time
\r\n**Distinct Microsoft Teams calls per selected interval. A sudden rise, or calls outside normal working hours, can indicate a vishing campaign in progress.**" + }, + "customWidth": "100", + "name": "teams calls trend header", + "id": "1b49c98f-e5d9-457c-b058-a195e89eac0e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Distinct Teams calls per interval (interim source: CloudAppEvents / CallParticipantDetail).\r\nCloudAppEvents\r\n| where ActionType == \"CallParticipantDetail\"\r\n| extend R = parse_json(RawEventData)\r\n| extend CallId = tostring(R.CallId)\r\n| summarize ['Teams Calls'] = dcount(CallId) by Timestamp = bin(Timestamp, {Granularity})\r\n| sort by Timestamp asc", + "size": 0, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "xAxis": "Timestamp", + "seriesLabelSettings": [ + { + "seriesName": "Teams Calls", + "color": "blueDark" + } + ] + }, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams calls trend", + "id": "7538b3ca-b96d-421a-9cdc-69b8aef4b185" + }, + { + "type": 1, + "content": { + "json": "### When calls happen (hour of day, UTC)
\r\n**Microsoft Teams calls by the hour of day they started (UTC), listed 00:00 through 23:00. The bar length is the number of calls that started in that hour across the selected period. Vishing calls cluster in working hours because the target must be online to answer, with the heaviest malicious-call activity between 14:00 and 20:00 UTC, Monday to Friday, according to Microsoft Threat Intelligence. Use this to baseline normal call timing and spot unusual off-hours spikes.**" + }, + "customWidth": "100", + "name": "teams calls hour header", + "id": "6bc095e9-fe0d-4f6f-81bd-f3374d758229" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Teams calls by start hour of day (UTC), all 24 hours 00:00..23:00 in order (interim source: CloudAppEvents / CallParticipantDetail).\r\nlet data = CloudAppEvents\r\n| where ActionType == \"CallParticipantDetail\"\r\n| extend R = parse_json(RawEventData)\r\n| extend JoinTime = todatetime(R.JoinTime), CallId = tostring(R.CallId)\r\n| where isnotempty(JoinTime) and isnotempty(CallId)\r\n| summarize CallStart = min(JoinTime) by CallId\r\n| extend HourUTC = hourofday(CallStart)\r\n| summarize Calls = count() by HourUTC;\r\nrange HourUTC from 0 to 23 step 1\r\n| join kind=leftouter (data) on HourUTC\r\n| extend Calls = coalesce(Calls, 0)\r\n| extend HourLabel = strcat(iif(HourUTC < 10, strcat(\"0\", tostring(HourUTC)), tostring(HourUTC)), \":00\")\r\n| order by HourUTC asc\r\n| project ['Hour of Day (UTC)'] = HourLabel, ['Teams Calls'] = Calls", + "size": 0, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Teams Calls", + "formatter": 3, + "formatOptions": { + "palette": "blueDark", + "customColumnWidthSetting": "360px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams calls hour", + "id": "c36a9909-5570-4fe7-8efc-1b9b4745713a" + }, + { + "type": 1, + "content": { + "json": "### Suspicious callers (support and helpdesk impersonation)
\r\n**Teams call participants whose display name or address looks like IT support, help desk, or a well-known brand (for example \"Microsoft IT support\", \"Help Desk\", \"Office 365 Support\"), or who dial in from a throwaway `.onmicrosoft.com` tenant. Origin shows whether the caller is external, an external throwaway tenant, or inside your own tenant. External and throwaway-tenant callers are the primary vishing risk; own-tenant matches are frequently a legitimate internal help desk and should be confirmed rather than assumed malicious.**

**Recommended action:** Prioritise External and `.onmicrosoft` callers, confirm none are legitimate, and warn the users they called. Genuine IT support does not cold-call staff over Teams to request remote access." + }, + "customWidth": "100", + "name": "teams calls susp header", + "id": "aa420b5f-efd2-4da5-ab41-192031f62ed1" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Suspicious Teams callers by impersonation-style DISPLAY NAME or address (Attendees[].DisplayName / UPN), with Origin from the org's own accepted (EmailEvents inbound) domains - no tenant-id anchor. Interim source: CloudAppEvents / CallParticipantDetail.\r\nlet suspRegex = @\"(?i)help ?desk|helpdesk|it ?support|service ?desk|sys ?admin|administrator|security|microsoft|google|apple|amazon|paypal|support|update|verif|account|password|mfa|maintenance\";\r\nlet ownDomains = toscalar(EmailEvents | where EmailDirection == \"Inbound\" | extend RD = tolower(tostring(split(RecipientEmailAddress, \"@\")[1])) | where isnotempty(RD) | summarize make_set(RD, 200));\r\nlet calls = CloudAppEvents\r\n| where ActionType == \"CallParticipantDetail\"\r\n| extend R = parse_json(RawEventData)\r\n| extend CallId = tostring(R.CallId), JoinTime = todatetime(R.JoinTime), Attendees = R.Attendees\r\n| where isnotempty(CallId);\r\nlet callAtt = calls | summarize Attendees = take_any(Attendees), JoinTime = min(JoinTime) by CallId;\r\ncallAtt\r\n| mv-expand Att = Attendees\r\n| extend Caller = tolower(tostring(Att.UPN)), CallerName = tostring(Att.DisplayName)\r\n| extend CallerDom = tostring(split(Caller, \"@\")[1])\r\n| where isnotempty(Caller)\r\n| extend SuspName = CallerName matches regex suspRegex or Caller matches regex suspRegex\r\n| where SuspName or CallerDom endswith \".onmicrosoft.com\"\r\n| extend Origin = case(CallerDom endswith \".onmicrosoft.com\", \"External (.onmicrosoft throwaway)\", set_has_element(ownDomains, CallerDom), \"Own tenant\", \"External\")\r\n| summarize CallsPlaced = dcount(CallId), FirstSeen = min(JoinTime), LastSeen = max(JoinTime) by CallerName, Caller, Origin\r\n| extend OriginRank = case(Origin == \"External (.onmicrosoft throwaway)\", 0, Origin == \"External\", 1, 2)\r\n| sort by OriginRank asc, CallsPlaced desc\r\n| take 10\r\n| project ['Caller Display Name'] = CallerName, ['Caller Address'] = Caller, ['Origin'] = Origin, ['Calls Placed'] = CallsPlaced, ['First Seen'] = FirstSeen, ['Last Seen'] = LastSeen", + "size": 0, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Calls Placed", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams calls susp table", + "id": "d1c4df7b-db07-4c4c-bc71-dfd8623cd704" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Calls and Vishing", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "1d133411-9b5c-4ede-8502-68b3b02262e4" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Teams Impersonation & Identity Deception\r\n
\r\n\r\nMicrosoft Defender for Office 365 flags Teams messages where a sender impersonates a brand, a specific person, or a trusted domain. Impersonation is the entry point for most Teams social-engineering: attackers pose as IT, executives, or Microsoft to build trust before delivering a malicious link or request. These visuals expose who is being impersonated, who is being targeted, and the infrastructure (display names, look-alike domains, and URLs) behind the campaigns so you can hunt IOCs and coach at-risk users.

**Recommended action:** Treat the impersonated display names and look-alike domains below as IOCs to hunt, and prioritize the Microsoft Defender alert *Microsoft Teams chat initiated by a suspicious external user*. Teach users that a Teams display name is not proof of identity: verify the real sender domain, and confirm any help desk, executive, or Microsoft support request through a known internal channel before acting." + }, + "name": "teams imp banner", + "id": "7ff04ff3-9f2d-4a49-8383-2b542d78fe9b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nunion\r\n(imp | summarize Count=count() | extend Details=\"Impersonation Detections\", Ord=1),\r\n(imp | summarize Count=dcount(FakeSenderAddress) | extend Details=\"Distinct Fake Senders\", Ord=2),\r\n(imp | summarize Count=dcount(TargetUser) | extend Details=\"Targeted Users\", Ord=3),\r\n(imp | summarize Count=dcount(ImpersonationType) | extend Details=\"Impersonation Types\", Ord=4)\r\n| sort by Ord asc | project Count, Details", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e37f94d5-9bcc-432e-aa66-25831603c228" + }, + { + "type": 1, + "content": { + "json": "### Impersonation over time, by type
\r\n\r\n**Trend of Brand, User, and Domain impersonation detections. A spike in a single type often marks the start of a targeted campaign.**" + }, + "customWidth": "100", + "name": "teams imp trend header", + "id": "09907f5b-5c20-4a7e-86d3-c89153c4df98" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp | summarize Count=count() by ImpersonationType, Timestamp=bin(Timestamp, {Granularity}) | sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp trend", + "id": "757204b1-e900-4217-a2ff-2224a033fdcc" + }, + { + "type": 1, + "content": { + "json": "### Suspicious external senders (impersonation and throwaway tenants)
\r\n**External Microsoft Teams senders flagged as likely impersonation: throwaway `.onmicrosoft.com` tenants and/or help desk, IT support, security, admin, or account/update-themed display names. Attackers rotate through many such identities (for example numbered `ithelpdesk@...` addresses) from newly-created or consumer tenants to pose as internal support, frequently before the Defender impersonation detector assigns a verdict. This heuristic complements that detector.**

**Recommended action:** Review high threat-rate senders, block the sending domains, and remind users that genuine IT support does not cold-contact them from an external tenant; verify any such request through a known internal channel." + }, + "customWidth": "100", + "name": "teams susp senders header", + "id": "5df4af86-49e9-4fc7-b6ad-76d3ef3f7da6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//External Teams senders flagged as likely impersonation: throwaway .onmicrosoft.com tenants and/or help desk / IT / admin / update-themed display names, ranked by messages carrying a threat.\r\nMessageEvents\r\n| where IsExternalThread == true\r\n| extend SenderDomain = tolower(tostring(split(SenderEmailAddress, \"@\")[1]))\r\n| extend IsOnMicrosoft = SenderDomain endswith \".onmicrosoft.com\"\r\n| extend SuspName = SenderDisplayName matches regex @\"(?i)help ?desk|helpdesk|it ?support|service ?desk|it team|administrator|sys ?admin|security|microsoft|maintenance|support|update|verif|account|password|mfa\"\r\n| where IsOnMicrosoft or SuspName\r\n| summarize TeamsMessages = count(), ThreatMessages = countif(isnotempty(ThreatTypes)), FirstSeen = min(Timestamp), LastSeen = max(Timestamp) by SenderDisplayName, SenderEmailAddress, SenderDomain, IsOnMicrosoft, SuspName\r\n| extend WhyFlagged = case(IsOnMicrosoft and SuspName, \"Throwaway .onmicrosoft tenant + helpdesk-style name\", IsOnMicrosoft, \"Throwaway .onmicrosoft tenant\", \"Helpdesk / IT-style display name\")\r\n| extend ThreatPct = round(todouble(ThreatMessages) * 100 / TeamsMessages, 1)\r\n| project ['Sender Display Name']=SenderDisplayName, ['Sender Address']=SenderEmailAddress, ['Why Flagged']=WhyFlagged, ['Teams Messages']=TeamsMessages, ['Threat Messages']=ThreatMessages, ['Threat %']=ThreatPct, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen\r\n| sort by ['Threat Messages'] desc, ['Teams Messages'] desc\r\n| take 10", + "size": 0, + "title": "", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Teams Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Threat %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 100 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams susp senders table", + "id": "dd1d79d8-f591-4aae-bd44-6ad23a3e0ae4" + }, + { + "type": 1, + "content": { + "json": "### Who is being targeted
\r\n\r\n**Internal users receiving the most impersonation attempts. Concentrated targeting of a few users is a strong signal of a deliberate campaign - prioritize these users for security awareness training.**" + }, + "customWidth": "100", + "name": "teams imp targets header", + "id": "43112ad1-ebc9-42fb-9ebd-0dbaa862ed45" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp | summarize Detections=count(), ['Distinct Fake Senders']=dcount(FakeSenderAddress), Types=make_set(ImpersonationType,3), ['Last Seen']=max(Timestamp) by ['Targeted User']=TargetUser | top 10 by Detections", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp targets", + "id": "cc4b3f98-bfcb-4741-9abb-9ff099eb946f" + }, + { + "type": 1, + "content": { + "json": "### Impersonating senders
\r\n\r\n**The identities behind the impersonation, grouped by fake display name, sender domain, and type. Attackers rotate through many sending addresses under a single display name - Distinct Sender Addresses exposes that rotation, and a high count is itself a strong bulk-campaign signal. Use First/Last Seen to scope the campaign window.**" + }, + "customWidth": "100", + "name": "teams imp senders header", + "id": "99859796-7b69-42e7-a27a-541e0ba86cb2" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the identities behind Teams impersonation, grouped by the fake display name, sender domain, and impersonation type. Attackers rotate through many sending addresses under one display name, so Distinct Sender Addresses reveals bulk campaigns that per-address ranking would hide.\r\nlet imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp\r\n| summarize Detections=count(), SenderAddresses=dcount(FakeSenderAddress), Targets=dcount(TargetUser), FirstSeen=min(Timestamp), LastSeen=max(Timestamp) by FakeDisplayName, FakeSenderDomain, ImpersonationType\r\n| top 10 by Detections\r\n| project ['Fake Display Name']=FakeDisplayName, ['Sender Domain']=FakeSenderDomain, ['Impersonation Type']=ImpersonationType, ['Distinct Sender Addresses']=SenderAddresses, Detections, ['Targeted Users']=Targets, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Distinct Sender Addresses", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp senders", + "id": "209439a0-5be3-4e41-abe9-695552730dc8" + }, + { + "type": 1, + "content": { + "json": "### Display names abused
\r\n\r\n**The identities attackers pretend to be (for example \"IT HelpDesk\", \"Microsoft Support\"). These are the trust anchors of the social-engineering lure.**" + }, + "customWidth": "100", + "name": "teams imp names header", + "id": "e645578b-7a52-4d38-9d83-f5c500bbfe1a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp | summarize Detections=count(), ['Targeted Users']=dcount(TargetUser), ['Distinct Senders']=dcount(FakeSenderAddress) by ['Fake Display Name']=FakeDisplayName | top 10 by Detections", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Distinct Senders", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp names", + "id": "d723d72b-4e7c-431b-ae7b-980879c8bd75" + }, + { + "type": 1, + "content": { + "json": "### Look-alike sender domains
\r\n\r\n**Sending domains used for impersonation - watch for typosquats (for example rnicrosoft.com for m→rn). Add confirmed domains to your Tenant Allow/Block List.**" + }, + "customWidth": "100", + "name": "teams imp domains header", + "id": "98040a5a-bbd5-4c95-b976-5630ce48b282" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp | summarize Detections=count(), ['Targeted Users']=dcount(TargetUser), ['Display Names Used']=dcount(FakeDisplayName) by ['Sender Domain']=FakeSenderDomain | top 10 by Detections", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Display Names Used", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp domains", + "id": "94b9fa45-c889-46a7-8b80-92e5d280ad3b" + }, + { + "type": 1, + "content": { + "json": "### URL IOCs from impersonation messages
\r\n\r\n**URL domains that appeared in messages sent by impersonating senders. Threat actors deliberately mix legitimate domains (for example microsoft.com or google.com) with their malicious ones to make the lure look trustworthy, so treat this as a review list - not a blocklist. Investigate the unfamiliar or look-alike domains and block only those you confirm malicious; never block a well-known legitimate domain from this list.**" + }, + "customWidth": "100", + "name": "teams imp ioc header", + "id": "d5f4886c-7c7e-4c6f-94ca-569cabda5ede" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists URL domains that appeared in messages sent by impersonating senders, with a breakdown of how many carried Malware, Phish, or Spam verdicts. Threat actors mix legitimate and malicious domains in a single lure, so review the unfamiliar or look-alike domains and block only confirmed-malicious ones.\r\nlet imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ChatThreadId = tostring(RD.ChatThreadId);\r\nlet impThreads = imp | distinct ChatThreadId;\r\nlet impMsgs = MessageEvents\r\n | where ThreadId in (impThreads)\r\n | summarize arg_max(Timestamp, *) by TeamsMessageId\r\n | project TeamsMessageId, ThreatTypes;\r\nMessageUrlInfo\r\n| where isnotempty(UrlDomain)\r\n| join kind=inner (impMsgs) on TeamsMessageId\r\n| summarize ['URL Count']=count(), Messages=dcount(TeamsMessageId), Malware=countif(ThreatTypes has \"Malware\"), Phish=countif(ThreatTypes has \"Phish\"), Spam=countif(ThreatTypes has \"Spam\") by ['URL Domain']=UrlDomain\r\n| top 10 by ['URL Count']", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "URL Count", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Malware", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Phish", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Spam", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp ioc", + "id": "958ac65c-d56d-4a80-ba83-2ab33e8b1e2e" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Impersonation", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "c49582db-6318-423f-b806-91cbeb625ea2" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Malicious URLs and Link Warnings in Teams\r\n
\r\n\r\nTracks URLs shared through Microsoft Teams, messages that triggered a Microsoft Defender for Office 365 URL safety-tip warning, and the outcome of Teams URL clicks (allowed versus blocked) captured in UrlClickEvents.

**Recommended action:** Enable Safe Links for Microsoft Teams so links are checked at click time, and prioritize *User clicked a malicious link in Teams chat* alerts for investigation. Treat a blocked click as an attempted compromise: check whether the user went on to share credentials or run a file, and reset credentials where warranted." + }, + "name": "teams url banner", + "id": "e3ec4d65-8d1f-4303-bd8f-eb1ae521da41" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query surfaces Microsoft Teams URL-sharing and link-warning metrics for the selected period. URL-warning messages carry the Microsoft Defender for Office 365 URL safety tip.\r\nlet msgs = materialize(MessageEvents | summarize arg_max(Timestamp, *) by TeamsMessageId);\r\nunion\r\n(msgs | where SafetyTip == \"URLMessageWarning\" | summarize Count = count() | extend Details = \"Messages with URL Warning\", Ord = 1),\r\n(MessageUrlInfo | summarize Count = count() | extend Details = \"URLs Shared in Messages\", Ord = 2),\r\n(MessageUrlInfo | summarize Count = dcount(TeamsMessageId) | extend Details = \"Messages Containing URLs\", Ord = 3),\r\n(MessageUrlInfo | summarize Count = dcount(UrlDomain) | extend Details = \"Distinct URL Domains\", Ord = 4)\r\n| sort by Ord asc\r\n| project Count, Details", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams url tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b71382c7-c0f7-4f9d-9d21-e0a8bf9504ff" + }, + { + "type": 1, + "content": { + "json": "### Teams URL click outcomes over time
\r\n\r\n**Allowed versus blocked Microsoft Teams URL clicks (per selected interval) from UrlClickEvents where the click happened in the Teams workload.**" + }, + "customWidth": "66", + "name": "teams click trend header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "30818e0d-6c4b-4868-896a-ac48cb3cef86" + }, + { + "type": 1, + "content": { + "json": "### Click outcomes
\r\n\r\n**Distribution of Microsoft Teams URL click actions by type.**" + }, + "customWidth": "33", + "name": "teams click pie header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "5a882138-2241-4527-80b8-9983c5807050" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Microsoft Teams URL click outcomes over time (allowed vs blocked) using the UrlClickEvents workload filter, summarizing the data per selected interval.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(UrlClickEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(UrlClickEvents | summarize max(Timestamp));\r\nlet agg = materialize(UrlClickEvents\r\n| where Workload == \"Teams\"\r\n| summarize ClickAllowed = countif(ActionType has \"ClickAllowed\"), ClickBlocked = countif(ActionType has \"ClickBlocked\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ClickAllowed = coalesce(ClickAllowed, 0), ClickBlocked = coalesce(ClickBlocked, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "teams click trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "7a2f5559-1e3e-412a-addf-c3bf6be98502" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows Microsoft Teams URL click outcomes by action type for the selected period.\r\nUrlClickEvents\r\n| where Workload == \"Teams\"\r\n| where isnotempty(ActionType)\r\n| summarize Count = count() by ActionType", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "teams click pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "889c6bb3-438b-4575-84f2-084c1b5fd1f4" + }, + { + "type": 1, + "content": { + "json": "### Top domains shared in Teams messages
\r\n\r\n**The 10 most-shared URL domains in Microsoft Teams messages, with the number of messages each appeared in.**" + }, + "customWidth": "100", + "name": "teams top domains header", + "id": "dcb8c87c-087e-4d69-b7b7-0329296293ff" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 URL domains shared in Microsoft Teams messages by volume for the selected period.\r\nMessageUrlInfo\r\n| where isnotempty(UrlDomain)\r\n| summarize UrlCount = count(), Messages = dcount(TeamsMessageId) by UrlDomain\r\n| top 10 by UrlCount\r\n| project ['URL Domain']=UrlDomain, ['URLs Shared']=UrlCount, ['Messages']=Messages", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "URLs Shared", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams top domains table", + "id": "7561adb0-1fbe-41ce-a924-a27bcd4c5c12" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Malicious URLs", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "6d47c309-be9e-4b21-940e-7c7b282e5dc2" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Targeted Users & Risky Senders\r\n
\r\n\r\nIdentifies who is most targeted in Microsoft Teams, and profiles the external senders and domains behind risky messages - URL safety-tip warnings, first-contact senders, threat-carrying domains, and low-reputation link infrastructure - so you can spot anomalous senders before they succeed.

**Recommended action:** Prioritize the most-targeted users for phishing-resistant MFA and awareness coaching, and treat first-contact external senders and low-reputation domains as IOCs. Restrict inbound chat from unmanaged and consumer tenants, and allowlist only trusted external domains so unsolicited outsiders cannot start a conversation." + }, + "name": "teams risky banner", + "id": "0aa13d73-2e13-487c-a7c4-d90464a554d4" + }, + { + "type": 1, + "content": { + "json": "### Top targeted users (messages with threats)
\r\n\r\n**The 10 users receiving the most Microsoft Teams messages that contained a threat, expanded from each message recipient list.**" + }, + "customWidth": "100", + "name": "teams targeted header", + "id": "827dc0f6-2bb2-49b9-acf8-d7b400238594" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 users receiving Microsoft Teams messages that contained a threat, expanded from the message recipient list, with each user's total Teams messages received and the share that carried a threat. Messages are de-duplicated to the latest record per message.\r\nlet expanded = MessageEvents\r\n | summarize arg_max(Timestamp, *) by TeamsMessageId\r\n | mv-expand rd = parse_json(RecipientDetails)\r\n | extend Recipient = tostring(rd.RecipientSmtpAddress)\r\n | where isnotempty(Recipient);\r\nlet totals = expanded | summarize TotalMessages = count() by Recipient;\r\nexpanded\r\n| where isnotempty(ThreatTypes)\r\n| summarize ThreatMessages = count() by Recipient\r\n| join kind=leftouter (totals) on Recipient\r\n| extend ThreatPct = round(100.0 * ThreatMessages / TotalMessages, 1)\r\n| top 10 by ThreatMessages\r\n| project ['Recipient']=Recipient, ['Threat Messages']=ThreatMessages, ['Total Messages']=TotalMessages, ['Threat %']=ThreatPct", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams targeted users table", + "id": "79481d1b-617e-46df-b555-9f7240932dd0" + }, + { + "type": 1, + "content": { + "json": "### Top senders of URL-warning messages
\r\n\r\n**Senders whose Microsoft Teams messages most often triggered a URL safety-tip warning.**" + }, + "customWidth": "50", + "name": "teams warn senders header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "ef71d7dd-4442-4992-977d-d550aad4533c" + }, + { + "type": 1, + "content": { + "json": "### Top domains in URL-warning messages
\r\n\r\n**URL domains most frequently present in Microsoft Teams messages that triggered a URL safety-tip warning.**" + }, + "customWidth": "50", + "name": "teams warn domains header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "6f41a4ba-f832-4947-ad27-cd6b8015bd63" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 senders whose Microsoft Teams messages triggered a URL safety-tip warning for the selected period, with each sender's total Teams messages and the share that carried a warning. Messages are de-duplicated to the latest record per message.\r\nlet dedup = MessageEvents | summarize arg_max(Timestamp, *) by TeamsMessageId;\r\nlet totals = dedup | summarize TotalMessages = count() by SenderEmailAddress;\r\ndedup\r\n| where SafetyTip == \"URLMessageWarning\"\r\n| summarize WarningMessages = count() by SenderEmailAddress\r\n| join kind=leftouter (totals) on SenderEmailAddress\r\n| extend WarningPct = round(100.0 * WarningMessages / TotalMessages, 1)\r\n| top 10 by WarningMessages\r\n| project ['Sender']=SenderEmailAddress, ['Warning Messages']=WarningMessages, ['Total Messages']=TotalMessages, ['Warning %']=WarningPct", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Warning Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams warn senders table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3fa023af-79e3-407f-ac20-b0aa6e3ba511" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 URL domains appearing in Microsoft Teams messages that triggered a URL safety-tip warning, with the domain's total message appearances and the share that carried a warning.\r\nlet warned = MessageEvents | where SafetyTip == \"URLMessageWarning\" | distinct TeamsMessageId;\r\nlet totals = MessageUrlInfo | where isnotempty(UrlDomain) | summarize TotalMessages = dcount(TeamsMessageId) by UrlDomain;\r\nMessageUrlInfo\r\n| where TeamsMessageId in (warned)\r\n| summarize WarningMessages = dcount(TeamsMessageId) by UrlDomain\r\n| join kind=leftouter (totals) on UrlDomain\r\n| extend WarningPct = round(100.0 * WarningMessages / TotalMessages, 1)\r\n| top 10 by WarningMessages\r\n| project ['URL Domain']=UrlDomain, ['Warning Messages']=WarningMessages, ['Total Messages']=TotalMessages, ['Warning %']=WarningPct", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Warning Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams warn domains table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "68811015-1383-48ad-86da-4f8f9d39e4c4" + }, + { + "type": 1, + "content": { + "json": "### First-contact external senders
\r\n\r\n**External Microsoft Teams senders ordered by when they were first seen in the period (most recent first). Note: some flows tag internal-domain senders as external - to hide your own tenant domains, edit the query and uncomment the ExcludeDomains filter.**" + }, + "customWidth": "100", + "name": "teams fc senders header", + "id": "0f131ff3-d6b2-4187-b86c-ca3493594b54" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists external Microsoft Teams senders by the date they were first seen in the selected period, surfacing recent first-contact senders. Messages are de-duplicated to the latest record per message. In tenants with longer history this highlights genuinely new senders.\r\n// TIP: IsExternalThread may still surface senders from your own accepted domains. To hide them,\r\n// uncomment the ExcludeDomains line below (add your tenant domains) and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"contoso.com\"]);\r\nMessageEvents\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| where IsExternalThread == true\r\n//| where tostring(split(SenderEmailAddress, \"@\")[1]) !in~ (ExcludeDomains)\r\n| summarize FirstSeen = min(Timestamp), Messages = count(), ThreatMessages = countif(isnotempty(ThreatTypes)) by SenderEmailAddress\r\n| top 10 by FirstSeen desc\r\n| project ['Sender']=SenderEmailAddress, ['First Seen']=FirstSeen, ['Messages']=Messages, ['Threat Messages']=ThreatMessages", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true, + "sortBy": [ + { + "itemKey": "Threat Messages", + "sortOrder": 2 + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams fc senders table", + "id": "4e10a78d-8858-4dbb-9db0-e7b7d7e7636c" + }, + { + "type": 1, + "content": { + "json": "### External sender-domain risk
\r\n\r\n**External sending domains ranked by threat volume, with the mix of conversation types (1:1 chat, group chat, channel), threat breakdown, threat rate, count of messages carrying low-reputation URLs (domains on commonly-abused TLDs such as .xyz, .top, .click, .shop, .zip), and first/last-seen. A domain that is new in the period, skews toward 1:1 chats, or shows a high threat rate is anomalous and warrants review. Note: to exclude your own tenant domains, edit the query and uncomment the ExcludeDomains filter.**" + }, + "customWidth": "100", + "name": "teams anomaly header", + "id": "a91295db-8192-4828-93c5-408436e4b0e1" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query ranks external sender domains in Microsoft Teams by threat volume for the selected period, split by conversation type (1:1 chat, group chat, channel), with threat-type breakdown, threat rate, and a count of messages carrying low-reputation URL TLDs. Messages are de-duplicated to the latest record per message. New, 1:1-skewed, or high-threat-rate domains are the anomalies to review.\r\n// TIP: IsExternalThread may still surface your own accepted domains. To hide them, uncomment the\r\n// ExcludeDomains line below (add your tenant domains) and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"contoso.com\"]);\r\nlet suspTlds = dynamic([\"top\",\"xyz\",\"click\",\"link\",\"shop\",\"online\",\"site\",\"live\",\"icu\",\"cyou\",\"sbs\",\"rest\",\"quest\",\"cfd\",\"bond\",\"buzz\",\"fun\",\"space\",\"monster\",\"work\",\"tk\",\"ml\",\"ga\",\"cf\",\"gq\",\"dev\",\"app\",\"zip\",\"mov\",\"info\",\"win\",\"loan\",\"men\",\"stream\",\"country\"]);\r\nlet suspUrlMsgs = MessageUrlInfo\r\n | where isnotempty(UrlDomain)\r\n | extend Tld = tostring(split(UrlDomain, \".\")[-1])\r\n | where Tld in (suspTlds)\r\n | distinct TeamsMessageId;\r\nMessageEvents\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| where IsExternalThread == true\r\n| extend SenderDomain = tostring(split(SenderEmailAddress, \"@\")[1])\r\n| where isnotempty(SenderDomain)\r\n//| where SenderDomain !in~ (ExcludeDomains)\r\n| extend ConvType = case(isnotempty(GroupId), \"Channel\", array_length(todynamic(RecipientDetails)) > 1, \"Group chat\", \"1:1 chat\")\r\n| extend HasSuspUrl = TeamsMessageId in (suspUrlMsgs)\r\n| summarize Messages=count(), Senders=dcount(SenderEmailAddress), OneToOne=countif(ConvType==\"1:1 chat\"), GroupChat=countif(ConvType==\"Group chat\"), ChannelMsgs=countif(ConvType==\"Channel\"), ThreatMessages=countif(isnotempty(ThreatTypes)), Malware=countif(ThreatTypes has \"Malware\"), Phish=countif(ThreatTypes has \"Phish\"), Spam=countif(ThreatTypes has \"Spam\"), SuspUrlMsgs=countif(HasSuspUrl), FirstSeen=min(Timestamp), LastSeen=max(Timestamp) by SenderDomain\r\n| where ThreatMessages > 0\r\n| extend ThreatRatePct = round(100.0 * ThreatMessages / Messages, 1)\r\n| top 10 by ThreatMessages desc\r\n| project ['Sender Domain']=SenderDomain, Messages, Senders, ['1:1']=OneToOne, ['Group']=GroupChat, ['Channel']=ChannelMsgs, ['Threat Msgs']=ThreatMessages, Malware, Phish, Spam, ['Threat Rate %']=ThreatRatePct, ['Low-Rep URL Msgs']=SuspUrlMsgs, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams anomaly table", + "id": "bcd6746d-8298-495d-9d6c-2fadc6cba569" + }, + { + "type": 1, + "content": { + "json": "### Suspicious new senders (no threat verdict yet)
\r\n\r\n**External sending domains with no threat verdict yet, but that are either sending low-reputation-URL messages or showing unusual volume. These slip past threat filters - watch for new domains skewing toward 1:1 chats, an early social-engineering signal. Note: to exclude your own tenant domains, edit the query and uncomment the ExcludeDomains filter.**" + }, + "customWidth": "100", + "name": "teams newdom header", + "id": "9e3844f4-befc-4b76-a8cd-ca53fdf51d41" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query surfaces external sender domains in Microsoft Teams that have NO threat verdict yet but are sending messages with low-reputation URL TLDs or unusual volume, split by conversation type. These are early-warning senders that have not tripped a detection. Messages are de-duplicated to the latest record per message.\r\n// TIP: IsExternalThread may still surface your own accepted domains. To hide them, uncomment the\r\n// ExcludeDomains line below (add your tenant domains) and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"contoso.com\"]);\r\nlet suspTlds = dynamic([\"top\",\"xyz\",\"click\",\"link\",\"shop\",\"online\",\"site\",\"live\",\"icu\",\"cyou\",\"sbs\",\"rest\",\"quest\",\"cfd\",\"bond\",\"buzz\",\"fun\",\"space\",\"monster\",\"work\",\"tk\",\"ml\",\"ga\",\"cf\",\"gq\",\"dev\",\"app\",\"zip\",\"mov\",\"info\",\"win\",\"loan\",\"men\",\"stream\",\"country\"]);\r\nlet suspUrlMsgs = MessageUrlInfo\r\n | where isnotempty(UrlDomain)\r\n | extend Tld = tostring(split(UrlDomain, \".\")[-1])\r\n | where Tld in (suspTlds)\r\n | distinct TeamsMessageId;\r\nMessageEvents\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| where IsExternalThread == true\r\n| extend SenderDomain = tostring(split(SenderEmailAddress, \"@\")[1])\r\n| where isnotempty(SenderDomain)\r\n//| where SenderDomain !in~ (ExcludeDomains)\r\n| extend ConvType = case(isnotempty(GroupId), \"Channel\", array_length(todynamic(RecipientDetails)) > 1, \"Group chat\", \"1:1 chat\")\r\n| extend HasSuspUrl = TeamsMessageId in (suspUrlMsgs)\r\n| summarize Messages=count(), Senders=dcount(SenderEmailAddress), OneToOne=countif(ConvType==\"1:1 chat\"), GroupChat=countif(ConvType==\"Group chat\"), ChannelMsgs=countif(ConvType==\"Channel\"), ThreatMessages=countif(isnotempty(ThreatTypes)), SuspUrlMsgs=countif(HasSuspUrl), FirstSeen=min(Timestamp), LastSeen=max(Timestamp) by SenderDomain\r\n| where ThreatMessages == 0\r\n| where SuspUrlMsgs > 0 or Messages >= 5\r\n| order by SuspUrlMsgs desc, Messages desc\r\n| take 10\r\n| project ['Sender Domain']=SenderDomain, Messages, Senders, ['1:1']=OneToOne, ['Group']=GroupChat, ['Channel']=ChannelMsgs, ['Low-Rep URL Msgs']=SuspUrlMsgs, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams newdom table", + "id": "8036a5b7-b5b3-4af4-912f-bb092bb01b89" + }, + { + "type": 1, + "content": { + "json": "### Low-reputation link domains in Teams (IOC radar)
\r\n\r\n**URL domains shared in Teams that use TLDs commonly abused for phishing and malware (for example .xyz, .top, .click, .zip, .shop). Ranked by message reach, with first/last-seen. Review these domains as potential indicators - .zip and .mov are especially deceptive because links read like file names.**" + }, + "customWidth": "100", + "name": "teams tld header", + "id": "d48921f4-233c-4e0f-a97b-83e1bcaed399" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists URL domains shared in Microsoft Teams that use low-reputation TLDs commonly abused for phishing and malware, ranked by the number of Teams messages they appeared in, with first- and last-seen. Treat high-reach or newly-seen domains as candidate indicators of compromise.\r\nlet suspTlds = dynamic([\"top\",\"xyz\",\"click\",\"link\",\"shop\",\"online\",\"site\",\"live\",\"icu\",\"cyou\",\"sbs\",\"rest\",\"quest\",\"cfd\",\"bond\",\"buzz\",\"fun\",\"space\",\"monster\",\"work\",\"tk\",\"ml\",\"ga\",\"cf\",\"gq\",\"dev\",\"app\",\"zip\",\"mov\",\"info\",\"win\",\"loan\",\"men\",\"stream\",\"country\"]);\r\nMessageUrlInfo\r\n| where isnotempty(UrlDomain)\r\n| extend Tld = tostring(split(UrlDomain, \".\")[-1])\r\n| where Tld in (suspTlds)\r\n| summarize Messages=dcount(TeamsMessageId), FirstSeen=min(Timestamp), LastSeen=max(Timestamp) by ['URL Domain']=UrlDomain, ['TLD']=Tld\r\n| top 10 by Messages desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams tld table", + "id": "30d5588e-010c-474a-9c53-74b73dcc9676" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Targeted Users & Risky Senders", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "6fef737b-cb4e-4a51-9ced-bf11754a6b33" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Teams File Protection\r\n
\r\n\r\nMicrosoft Defender for Office 365 scans files shared in Microsoft Teams. These visuals show files scanned versus malware detected, and list the malicious files found.

**Recommended action:** Investigate each malicious file below and confirm it was quarantined and removed from the SharePoint or OneDrive location backing the chat. Enable Safe Attachments for SharePoint, OneDrive, and Microsoft Teams, and use attack surface reduction rules to block executable content delivered through collaboration." + }, + "name": "teams file banner", + "id": "2f01c905-dd65-4a13-9f67-c70402b2c175" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query summarizes Microsoft Teams file protection by Microsoft Defender for Office 365 - files scanned, files with malware detected, and files scanned with no detection - for the selected period.\r\nlet base = FileMaliciousContentInfo | where Workload == \"MicrosoftTeams\";\r\nunion\r\n(base | summarize Count = count() | extend Details = \"Teams Files Scanned\", Ord = 1),\r\n(base | where isnotempty(ThreatTypes) | summarize Count = count() | extend Details = \"Files with Malware Detected\", Ord = 2),\r\n(base | where isempty(ThreatTypes) | summarize Count = count() | extend Details = \"Files Scanned - No Detection\", Ord = 3)\r\n| sort by Ord asc\r\n| project Count, Details", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams file tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "9f555c51-1680-47ef-94d4-b1f8cf9dce3b" + }, + { + "type": 1, + "content": { + "json": "### Malicious files shared in Teams
\r\n\r\n**Files shared in Microsoft Teams that were detected with malware, with owner and file details.**" + }, + "customWidth": "100", + "name": "teams file table header", + "id": "4cd3274e-0c61-4722-83b7-1fccf8a94a57" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists Microsoft Teams files detected with malware by Microsoft Defender for Office 365 for the selected period.\r\nFileMaliciousContentInfo\r\n| where Workload == \"MicrosoftTeams\"\r\n| where isnotempty(ThreatTypes)\r\n| top 10 by Timestamp desc\r\n| project ['Time']=Timestamp, ['File Name']=FileName, ['Threat Type']=tostring(ThreatTypes), ['Threat Names']=ThreatNames, ['File Location']=FolderPath, ['File Owner']=FileOwnerUpn, SHA256", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams file table", + "id": "135e0e7d-7110-40ee-a377-1a5992b2ef9d" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams File Protection", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "8ecc1bae-4a06-4b1c-8952-59fb434b7cbc" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Post-Delivery ZAP Insights (Teams)\r\n
\r\n\r\nZero-hour auto purge (ZAP) removes malicious Microsoft Teams messages after delivery. These visuals summarize ZAP volume, type, result, and the senders whose messages were most often removed.

**Recommended action:** Confirm zero-hour auto purge is enabled for Microsoft Teams so newly-weaponized messages are pulled after delivery. Investigate senders with repeated ZAP removals as likely compromised or malicious accounts and block or restrict them. A rising ZAP trend can signal an active campaign that slipped past delivery-time filtering." + }, + "name": "teams zap banner", + "id": "136cfb4e-d2a5-4db0-9771-6b6380011ba0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query summarizes Microsoft Teams post-delivery ZAP (zero-hour auto purge) activity by Microsoft Defender for Office 365 for the selected period.\r\nlet zap = materialize(MessagePostDeliveryEvents);\r\nunion\r\n(zap | summarize Count = count() | extend Details = \"Total ZAP Actions\", Ord = 1),\r\n(zap | where ActionType == \"Malware ZAP\" | summarize Count = count() | extend Details = \"Malware ZAP\", Ord = 2),\r\n(zap | where ActionType == \"Phish ZAP\" | summarize Count = count() | extend Details = \"Phish ZAP\", Ord = 3),\r\n(zap | where ActionResult == \"Success\" | summarize Count = count() | extend Details = \"Successful Actions\", Ord = 4),\r\n(zap | where ActionResult == \"Failed\" | summarize Count = count() | extend Details = \"Failed Actions\", Ord = 5),\r\n(zap | where Action == \"Moved to quarantine\" | summarize Count = count() | extend Details = \"Moved to Quarantine\", Ord = 6)\r\n| sort by Ord asc\r\n| project Count, Details", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams zap tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "06980411-5e6b-4aa4-a746-351cd2b12dae" + }, + { + "type": 1, + "content": { + "json": "### ZAP actions over time
\r\n\r\n**Microsoft Teams post-delivery ZAP actions (per selected interval) split by Malware ZAP and Phish ZAP.**" + }, + "customWidth": "66", + "name": "teams zap trend header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "7fc1cfcd-3a9f-45b1-9f39-3820fce23c03" + }, + { + "type": 1, + "content": { + "json": "### ZAP by action type
\r\n\r\n**Distribution of Microsoft Teams post-delivery ZAP actions by type.**" + }, + "customWidth": "33", + "name": "teams zap pie header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "9bc0d0a3-876a-49d7-9046-31764511ca38" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Microsoft Teams post-delivery ZAP actions over time by ZAP type, summarizing the data per selected interval.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(MessagePostDeliveryEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(MessagePostDeliveryEvents | summarize max(Timestamp));\r\nlet agg = materialize(MessagePostDeliveryEvents\r\n| summarize MalwareZAP = countif(ActionType == \"Malware ZAP\"), PhishZAP = countif(ActionType == \"Phish ZAP\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, MalwareZAP = coalesce(MalwareZAP, 0), PhishZAP = coalesce(PhishZAP, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "teams zap trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "c78a509e-324f-4a8c-b2e7-bce3e0d20667" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows Microsoft Teams post-delivery ZAP actions by type for the selected period.\r\nMessagePostDeliveryEvents\r\n| summarize Count = count() by ActionType", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "teams zap pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "cfc94695-fb02-4b6c-a223-f79f7b947379" + }, + { + "type": 1, + "content": { + "json": "### Top senders whose messages were removed by ZAP
\r\n\r\n**Senders whose Microsoft Teams messages were most often removed by post-delivery ZAP.**" + }, + "customWidth": "100", + "name": "teams zap senders header", + "id": "f8677ffe-007a-41ca-81de-1ae5dd19d06a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 senders whose Microsoft Teams messages were removed by post-delivery ZAP for the selected period.\r\nMessagePostDeliveryEvents\r\n| where isnotempty(SenderEmailAddress)\r\n| summarize ZapActions = count(), MalwareZAP = countif(ActionType == \"Malware ZAP\"), PhishZAP = countif(ActionType == \"Phish ZAP\") by SenderEmailAddress\r\n| top 10 by ZapActions\r\n| project ['Sender']=SenderEmailAddress, ['ZAP Actions']=ZapActions, ['Malware ZAP']=MalwareZAP, ['Phish ZAP']=PhishZAP", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "ZAP Actions", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams zap senders table", + "id": "50c9a883-6442-40dc-b84f-57adfbb46a38" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams ZAP", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "f5cc2425-e5ae-4520-9a97-2e4c2c447dcd" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Teams Message and Call Submissions\r\n
\r\n\r\nMicrosoft Teams messages and calls reported by users, and messages submitted by admins, for review by Microsoft. Sourced from the submission records in CloudAppEvents.

**Recommended action:** Encourage users to report suspicious Teams messages and calls so Microsoft can tune protection, and triage admin submissions promptly. A cluster of reports naming the same sender, display name, or call identity is an early signal of a targeted campaign: pivot those identities into the impersonation and risky-sender views above to scope it." + }, + "name": "teams sub banner", + "id": "54cbfb29-2626-4b65-8cb5-a42ff4b41e63" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query summarizes Microsoft Teams message and call submissions reported to Microsoft for the selected period, split by user and admin reports. Only completed submissions are counted (submission triage/timeout lifecycle records are excluded).\r\nlet sub = materialize(CloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType in (\"ChatMessage\", \"TeamsCall\"));\r\nunion\r\n(sub | where SubmissionContentType == \"ChatMessage\" and ActionType == \"UserSubmission\" | summarize Count = count() | extend Details = \"Messages Reported by Users\", Ord = 1),\r\n(sub | where SubmissionContentType == \"TeamsCall\" and ActionType == \"UserSubmission\" | summarize Count = count() | extend Details = \"Calls Reported by Users\", Ord = 2),\r\n(sub | where SubmissionContentType == \"ChatMessage\" and ActionType == \"AdminSubmission\" | summarize Count = count() | extend Details = \"Messages Submitted by Admins\", Ord = 3)\r\n| sort by Ord asc\r\n| project Count, Details", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams sub tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "419ed645-ebc1-4df1-b9f0-c744403ab494" + }, + { + "type": 1, + "content": { + "json": "### Submissions over time
\r\n\r\n**Microsoft Teams user and admin submissions (per selected interval).**" + }, + "customWidth": "66", + "name": "teams sub trend header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "6a795b0a-82e2-427a-8ac0-abfb5bb5e447" + }, + { + "type": 1, + "content": { + "json": "### Submission mix
\r\n\r\n**Microsoft Teams submissions split by content type (message or call) and reporter (user or admin).**" + }, + "customWidth": "33", + "name": "teams sub pie header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "1f4c55f8-7290-4b6f-b02a-e3134568b9ff" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Microsoft Teams message and call submissions over time, summarizing the data per selected interval. Only completed submissions are counted (submission triage/timeout lifecycle records are excluded).\r\nlet gran = {Granularity};\r\nlet sub = materialize(CloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType in (\"ChatMessage\", \"TeamsCall\"));\r\nlet minTime = toscalar(sub | summarize min(Timestamp));\r\nlet maxTime = toscalar(sub | summarize max(Timestamp));\r\nlet agg = materialize(sub\r\n| summarize UserReports = countif(ActionType == \"UserSubmission\"), AdminReports = countif(ActionType == \"AdminSubmission\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, UserReports = coalesce(UserReports, 0), AdminReports = coalesce(AdminReports, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "teams sub trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "7dcb03da-de96-4388-90a4-0a3f3ca98dc6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows the mix of Microsoft Teams submissions by content type and reporter for the selected period. Only completed user submissions (chat and call) and admin submissions (chat) are counted; submission triage/timeout lifecycle records are excluded.\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\"\r\n| where (SubmissionContentType == \"ChatMessage\" and ActionType == \"UserSubmission\")\r\n or (SubmissionContentType == \"TeamsCall\" and ActionType == \"UserSubmission\")\r\n or (SubmissionContentType == \"ChatMessage\" and ActionType == \"AdminSubmission\")\r\n| extend Reporter = iif(ActionType == \"AdminSubmission\", \"Admin\", \"User\")\r\n| summarize Count = count() by SubmissionType = strcat(SubmissionContentType, \" (\", Reporter, \")\")", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "teams sub pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "84a0141e-51de-4423-acb0-3c4342a49bf2" + }, + { + "type": 1, + "content": { + "json": "### False Negative (FN) User Submissions by submission State
\r\n\r\n**Microsoft Teams messages reported by users as missed detections, broken down by submission state (for example Rescaned, Graded). Tracks the processing status of user reports.**" + }, + "customWidth": "50", + "name": "teams sub state header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "1b2bdffd-69b0-41b0-bdda-b242b7faaec0" + }, + { + "type": 1, + "content": { + "json": "### False Negative (FN) User Submissions by Triage Verdict
\r\n\r\n**Microsoft Teams user submissions grouped by the verdict assigned during grading (for example Phishing, NotSpam, Spam). Shows how reported messages were graded and highlights detection gaps.**" + }, + "customWidth": "50", + "name": "teams sub verdict header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "bdb97e09-44d2-41ad-a99f-931e4a8169cc" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows Microsoft Teams user (false negative) message submissions by submission state (for example Rescaned, Graded), to track processing status.\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend SubmissionState = tostring(RD.SubmissionState)\r\n| summarize Count = count() by tostring(SubmissionState)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub state pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "139ce840-5fc2-44d1-9872-91b37a74f0e7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows Microsoft Teams user (false negative) message submissions by the triage verdict assigned during grading (for example Phishing, NotSpam, Spam).\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend TriageVerdict = tostring(parse_json(tostring(RD.GradingResult)).TriageVerdict)\r\n| where isnotempty(TriageVerdict)\r\n| summarize Count = count() by TriageVerdict", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub verdict pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "538ce4a3-a1ff-4b8d-a466-2173edbb2cd7" + }, + { + "type": 1, + "content": { + "json": "### Top 10 P2 sender domains in FN User Submissions
\r\n\r\n**The sender domains most often reported by users as missed Microsoft Teams threats. High-volume domains are candidate sources of malicious messaging.**" + }, + "customWidth": "50", + "name": "teams sub domains header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "9b8db0c7-2bf2-4077-ae20-60146001bf23" + }, + { + "type": 1, + "content": { + "json": "### Top 10 individual P2 senders in FN User Submissions
\r\n\r\n**The individual senders most often reported by users as missed Microsoft Teams threats.**" + }, + "customWidth": "50", + "name": "teams sub senders header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "ffbe90ab-129c-47fa-9dac-50cab528ad55" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 P2 (envelope) sender domains of Microsoft Teams messages reported by users as false negatives (missed detections).\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend P2SenderDomain = tostring(RD.P2SenderDomain)\r\n| where isnotempty(P2SenderDomain)\r\n| summarize Submissions = count() by ['P2 Sender Domain']=P2SenderDomain\r\n| top 10 by Submissions", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub domains table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b18192fb-26a8-4bd1-9b07-7aeab496eae3" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 individual P2 (envelope) senders of Microsoft Teams messages reported by users as false negatives (missed detections).\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend P2Sender = tostring(RD.P2Sender)\r\n| where isnotempty(P2Sender)\r\n| summarize Submissions = count() by ['P2 Sender']=P2Sender\r\n| top 10 by Submissions", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub senders table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "7ead0a01-2b56-4225-b625-554b09350013" + }, + { + "type": 1, + "content": { + "json": "### Top 10 users performing the most FN User Submissions
\r\n\r\n**The users who report the most Microsoft Teams messages as missed detections - useful for recognising engaged reporters and spotting over-reporting.**" + }, + "customWidth": "50", + "name": "teams sub topusers header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "fb893cdd-d6d3-431a-a1d2-87652571a10d" + }, + { + "type": 1, + "content": { + "json": "### Top 10 admins performing the most FN Admin Submissions
\r\n\r\n**The admins who submit the most Microsoft Teams messages as missed detections.**" + }, + "customWidth": "50", + "name": "teams sub topadmins header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "14fca69b-e152-4a5d-bd2c-020c34c2226a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 users who reported the most Microsoft Teams messages as false negatives (missed detections), with each submitter's email (from the submission record) to disambiguate users with similar names.\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend Submitter = tostring(RD.SubmitterDisplayName), SubmitterEmail = tostring(RD.UserId)\r\n| where isnotempty(Submitter) and SubmitterEmail has \"@\"\r\n| summarize Submissions = count() by ['Submitter']=Submitter, ['Email']=SubmitterEmail\r\n| top 10 by Submissions", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub topusers table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a171a35b-35b0-46ce-a916-052a54101126" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 admins who submitted the most Microsoft Teams messages as false negatives (missed detections). The admin's own email is not present in the submission record (that would require the Identity table), so the Submitter ID (object GUID) is shown to disambiguate admins with similar names.\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"AdminSubmission\"\r\n| extend Submitter = tostring(RD.SubmitterDisplayName), SubmitterId = tostring(RD.SubmitterId)\r\n| where isnotempty(Submitter)\r\n| summarize Submissions = count() by ['Admin']=Submitter, ['Submitter ID']=SubmitterId\r\n| top 10 by Submissions", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub topadmins table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8bf37c2b-067a-4341-a192-2aa45699c3f7" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Submissions", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "eeea53a4-69d9-426e-bf9f-1789cd73bfed" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Recent Threat Detail\r\n
\r\n\r\nThe most recent Microsoft Teams phishing and malware messages, de-duplicated to the latest record per message, for investigation." + }, + "name": "teams detail banner", + "id": "4bdd917c-721f-450b-b455-45cbd5f59cc5" + }, + { + "type": 1, + "content": { + "json": "### Last 10 Teams phishing messages
\r\n\r\n**Most recent Microsoft Teams messages detected as phishing, with sender, delivery action, safety tip, team/group, and subject. TeamsMessageId is included to pivot to Advanced Hunting.**" + }, + "customWidth": "100", + "name": "teams detail phish header", + "id": "9bcf96c1-a958-4515-b171-10ec2f3ba660" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the 10 most recent Microsoft Teams messages detected as phishing by Microsoft Defender for Office 365, de-duplicated to the latest record per message. TeamsMessageId is included so analysts can pivot to Advanced Hunting.\r\nMessageEvents\r\n| where ThreatTypes has \"Phish\"\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| top 10 by Timestamp desc\r\n| project ['Time']=Timestamp, ['Sender']=SenderEmailAddress, ['Threat Types']=ThreatTypes, ['Delivery Action']=DeliveryAction, ['Safety Tip']=SafetyTip, ['Team / Group']=GroupName, ['External Thread']=IsExternalThread, ['Subject']=MessageSubject, TeamsMessageId", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams detail phish table", + "id": "3675d08f-1165-4f47-a633-e432cf96e3d5" + }, + { + "type": 1, + "content": { + "json": "### Last 10 Teams malware messages
\r\n\r\n**Most recent Microsoft Teams messages detected as malware, with sender, delivery action, safety tip, team/group, and subject. TeamsMessageId is included to pivot to Advanced Hunting.**" + }, + "customWidth": "100", + "name": "teams detail mal header", + "id": "6b9d66d2-8d89-47b0-a72a-5ee8623082dc" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the 10 most recent Microsoft Teams messages detected as malware by Microsoft Defender for Office 365, de-duplicated to the latest record per message. TeamsMessageId is included so analysts can pivot to Advanced Hunting.\r\nMessageEvents\r\n| where ThreatTypes has \"Malware\"\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| top 10 by Timestamp desc\r\n| project ['Time']=Timestamp, ['Sender']=SenderEmailAddress, ['Threat Types']=ThreatTypes, ['Delivery Action']=DeliveryAction, ['Safety Tip']=SafetyTip, ['Team / Group']=GroupName, ['External Thread']=IsExternalThread, ['Subject']=MessageSubject, TeamsMessageId", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams detail mal table", + "id": "d6e76d0a-7eee-4c05-8e92-10f9622b5ab3" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Detail", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "1e9c879b-d6be-4d36-9068-b5438abf7dd2" + }, + { + "type": 1, + "content": { + "json": "# Top Attacked Users, Top Senders, and Automatic External Email Forwarding\r\n\r\n---\r\nThis tab provides insights into **Top attacked users, Top Senders** in inbound email messages and details about **automatic external email forwarding**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "6" + }, + "name": "text - 24 - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f1a60054-44b1-432e-be7a-9d7d114ff5c7" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Top Attacked Users and Top Senders Insights\r\n
\r\n\r\nThis section provides key visuals that highlight top attacked users – individuals most frequently targeted by inbound email threats as detected by Microsoft Defender for Office 365. Offers insights into top email senders and sender domains across inbound email traffic, helping identify patterns and potential risk sources.

**Recommended action:** Apply the Strict preset to the most-attacked users and review the top sender domains as possible block-list candidates." + }, + "name": "text - 13 - Copy - Copy", + "id": "ff220902-30b8-4aef-9b79-14c913a1b2d2" + }, + { + "type": 1, + "content": { + "json": "### Top Attacked Users
\r\n\r\n**Displays the top 10 recipient email addresses that received inbound emails flagged as Spam, Phishing, or Malware. Helps identify high-risk users for targeted security awareness and policy enforcement.**" + }, + "name": "text - 13 - Copy - Copy - Copy", + "id": "58f34b9f-824d-4fcf-b2aa-d7d380aa08d5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 users that are receiving Spam, Phishing or Malware emails\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\" and EmailDirection ==\"Inbound\"\r\n| extend MDO_detection = parse_json(DetectionMethods) \r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),MalwareEmailCount = countif(FirstDetection == \"Malware\"),PhishEmailCount = countif(FirstDetection == \"Phish\"),SpamEmailCount = countif(FirstDetection == \"Spam\") by RecipientEmailAddress\r\n| extend ThreatEmailCount=(MalwareEmailCount+PhishEmailCount+SpamEmailCount)\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(ThreatEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| top 15 by ThreatEmailCount\r\n| project ['Recipient']=RecipientEmailAddress, ['Total Emails']=TotalEmailCount, ['Threat Emails']=ThreatEmailCount, ['Malware']=MalwareEmailCount, ['Phish']=PhishEmailCount, ['Spam']=SpamEmailCount, ['Bad Traffic %']=Bad_Traffic_Percentage_Inbound", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Threat Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Malware", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spam", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + } + } + ], + "filter": true, + "sortBy": [ + { + "itemKey": "$gen_bar_Threat Emails_2", + "sortOrder": 2 + } + ] + }, + "sortBy": [ + { + "itemKey": "$gen_bar_Threat Emails_2", + "sortOrder": 2 + } + ], + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 28", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e9459e78-6b43-4ef2-9596-32169d95c610" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Senders of Inbound Emails
\r\n\r\n**Displays the top 10 sender email addresses from external sources delivering inbound emails. Helps identify high-volume external senders for monitoring and policy enforcement.**" + }, + "name": "text - 13 - Copy - Copy - Copy - Copy", + "id": "eb4590a7-57c7-4728-af62-3d798afe6f2d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 senders by inbound email sending volume\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\" and EmailDirection ==\"Inbound\"\r\n| extend MDO_detection = parse_json(DetectionMethods) \r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),MalwareEmailCount = countif(FirstDetection == \"Malware\"),PhishEmailCount = countif(FirstDetection == \"Phish\"),SpamEmailCount = countif(FirstDetection == \"Spam\") by SenderFromAddress\r\n| extend ThreatEmailCount=(MalwareEmailCount+PhishEmailCount+SpamEmailCount)\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(ThreatEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| top 15 by TotalEmailCount\r\n| project ['Sender']=SenderFromAddress, ['Total Emails']=TotalEmailCount, ['Threat Emails']=ThreatEmailCount, ['Malware']=MalwareEmailCount, ['Phish']=PhishEmailCount, ['Spam']=SpamEmailCount, ['Bad Traffic %']=Bad_Traffic_Percentage_Inbound", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Threat Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Malware", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spam", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + } + } + ], + "filter": true + }, + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 28 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e4272979-1073-4c1e-9b1b-b971bc3efc33" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains of Inbound Emails
\r\n\r\n**Displays the top 10 sender domains from external sources delivering inbound emails. Helps identify high-volume external sender domains for monitoring and policy enforcement.**" + }, + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "id": "7ab63415-17ce-47f1-a614-e5e6edbe472e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 senders by inbound email sending volume\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\" and EmailDirection ==\"Inbound\"\r\n| extend MDO_detection = parse_json(DetectionMethods) \r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),MalwareEmailCount = countif(FirstDetection == \"Malware\"),PhishEmailCount = countif(FirstDetection == \"Phish\"),SpamEmailCount = countif(FirstDetection == \"Spam\") by SenderFromDomain\r\n| extend ThreatEmailCount=(MalwareEmailCount+PhishEmailCount+SpamEmailCount)\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(ThreatEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| top 15 by TotalEmailCount\r\n| project ['Sender Domain']=SenderFromDomain, ['Total Emails']=TotalEmailCount, ['Threat Emails']=ThreatEmailCount, ['Malware']=MalwareEmailCount, ['Phish']=PhishEmailCount, ['Spam']=SpamEmailCount, ['Bad Traffic %']=Bad_Traffic_Percentage_Inbound", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Threat Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Malware", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spam", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + } + } + ], + "filter": true + }, + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 28 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b593da94-b735-4fe3-a82d-18c90156e506" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "6" + }, + "name": "group - 10-Top attacked users and top senders", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "3e41cc1a-166e-4094-bc66-7e26a918b2e9" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Automatic External Email Forwarding Insights\r\n
\r\n\r\n**Email forwarding can be useful, but can also pose a security risk due to the potential disclosure of information.**\r\n
\r\n\r\nUsers can configure [Inbox rules](https://support.microsoft.com/en-US/Outlook/mail/use-rules-to-automatically-forward-messages) in Outlook or set up [SMTP forwarding](https://support.microsoft.com/en-us/office/turn-on-automatic-forwarding-in-outlook-7f2670a1-7fff-4475-8a3c-5822d63b0c8e) to automatically forward messages to external recipients. You can control automatic external email forwarding from cloud mailboxes using [Outbound spam policies](https://learn.microsoft.com/en-us/defender-office-365/outbound-spam-policies-external-email-forwarding) in Microsoft Defender for Office 365. \r\n**Attackers might exploit this capability to compromise your organization or its partners.**

**Recommended action:** Investigate external auto-forwarding - it is a common data-exfiltration path. Consider disabling auto-forwarding via the outbound spam policy unless a business case is documented." + }, + "name": "text - 8", + "id": "b04d1590-98e3-4650-9172-33e75561e1e5" + }, + { + "type": 1, + "content": { + "json": "### Automatic Email Forwarding by Type
\r\n\r\n**Displays counts of outbound emails automatically forwarded to external addresses, grouped by forwarding type (e.g., SMTP forwarding, inbox rules). Helps identify forwarding behaviors that may pose data exfiltration risks.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "c7cb7917-eaf4-4a1e-989a-75f4b6182851" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Internal Users Forwarding Emails Externally
\r\n\r\n**Displays the top 10 internal user accounts that have automatically forwarded emails to external addresses (regardless of the forwarding type used). Helps identify potential data exfiltration risks and enforce forwarding policies.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5a5d5a8c-c195-45db-a878-e6ac908cc919" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises automatic email forwarding to external email addresses by forwarding type\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| summarize count() by ForwardingType\r\n| sort by count_ desc \r\n", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "15094d98-add2-4b50-a0df-ee91fd34c6fb" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 internal senders who are automatically forwarding emails to external email addresses\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| summarize TotalForwardedMessages = count() by ForwardingUser\r\n| sort by TotalForwardedMessages desc \r\n| top 10 by TotalForwardedMessages\r\n| project ['Forwarding User']=ForwardingUser, ['Forwarded Messages']=TotalForwardedMessages\r\n\r\n", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "TotalForwardedMessages" + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "73d66038-2ea0-449d-9aeb-a1bd4b207d7f" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Internal Users Forwarding Emails Using Mailbox Rules
\r\n\r\n**Displays the top 10 internal user accounts that have automatically forwarded outbound emails to external addresses using Mailbox Rules. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "9a7b5fc3-da23-4e95-87df-542a5e3f6320" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 internal senders who are automatically forwarding emails to external email addresses using Mailbox Rules\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| where ForwardingType ==\"MbxRule\"\r\n| summarize TotalForwardedMessages = count() by ForwardingUser\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Forwarding User']=ForwardingUser, ['Forwarded Messages']=TotalForwardedMessages", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "TotalForwardedMessages" + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 30 - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f8d7b85d-944a-493f-a143-7e18277846c9" + }, + { + "type": 1, + "content": { + "json": "### Top 10 External domains Receiving Auto-Forwarded Emails (Mailbox Rules)
\r\n\r\n**Displays the top 10 external recipient email domains that received automatically forwarded emails from internal users via Mailbox Rules. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "cda99a50-b7c4-4d95-ac61-7231080a3f5d" + }, + { + "type": 1, + "content": { + "json": "### Top 10 External Recipients Receiving Auto-Forwarded Emails (Mailbox Rules)
\r\n\r\n**Displays the top 10 external recipient email addresses that received automatically forwarded emails from internal users via Mailbox Rules. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "72b01575-c33e-457c-98db-ea755c003bf0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 external domains who are recieving automatically forwarded emails using Mailbox Rules\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser),RecipientDomain = tostring(split(RecipientEmailAddress, \"@\")[1])\r\n| where ForwardingType ==\"MbxRule\"\r\n| summarize TotalForwardedMessages = count() by RecipientDomain\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Recipient Domain']=RecipientDomain, ['Forwarded Messages']=TotalForwardedMessages", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "823dec28-48b5-4be3-8e68-04301a952a62" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 external recipients who are recieving automatically forwarded emails using Mailbox Rules\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| where ForwardingType ==\"MbxRule\"\r\n| summarize TotalForwardedMessages = count() by RecipientEmailAddress\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Recipient']=RecipientEmailAddress, ['Forwarded Messages']=TotalForwardedMessages", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "14804990-bfc9-43b7-8c8d-95c2cf32ee56" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Internal Users Forwarding Emails via SMTP Forwarding
\r\n\r\n**Displays the top 10 internal user accounts that have automatically forwarded outbound emails to external addresses using SMTP Forwarding. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "fa04b313-5756-4ff7-9ee8-ec61e6b382cc" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 internal senders who are automatically forwarding emails to external email addresses using SmtpForwarding\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| where ForwardingType ==\"SmtpForwarding\"\r\n| summarize count() by ForwardingUser\r\n| top 10 by count_ desc\r\n| project ['Forwarding User']=ForwardingUser, ['Forwarded Messages']=count_", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 30 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "bed8e717-4ea7-4f71-aaa7-b70a31f4dc88" + }, + { + "type": 1, + "content": { + "json": "### Top 10 External domains receiving Auto-Forwarded Emails (SMTP Forwarding)
\r\n\r\n**Displays the top 10 external recipient email domains that received automatically forwarded emails from internal users using SMTP Forwarding. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f76bc717-3cf8-4d8d-92fa-3f2024065f8f" + }, + { + "type": 1, + "content": { + "json": "### Top 10 External Recipients Receiving Auto-Forwarded Emails (SMTP Forwarding)
\r\n\r\n**Displays the top 10 external recipient email addresses that received automatically forwarded emails from internal users using SMTP Forwarding. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "2190c799-ab4f-4bd8-87e1-f9c5c224cca4" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 external recipients who are recieving automatically forwarded emails using SmtpForwarding\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser),RecipientDomain = tostring(split(RecipientEmailAddress, \"@\")[1])\r\n| where ForwardingType ==\"SmtpForwarding\"\r\n| summarize TotalForwardedMessages = count() by RecipientDomain\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Recipient Domain']=RecipientDomain, ['Forwarded Messages']=TotalForwardedMessages", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "c3be87b3-8ce8-40f2-ad92-0651bed71117" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 external recipients who are recieving automatically forwarded emails using SmtpForwarding\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| where ForwardingType ==\"SmtpForwarding\"\r\n| summarize TotalForwardedMessages = count() by RecipientEmailAddress\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Recipient']=RecipientEmailAddress, ['Forwarded Messages']=TotalForwardedMessages", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "fb6b0113-f5bb-46a7-994b-92ebc3c7881d" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "6" + }, + "name": "group - 34 - Automatic email forwarding", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "02c91ebb-4f92-4843-a73b-6dea7a6ac2bd" + }, + { + "type": 1, + "content": { + "json": "# Email detection action overrides\r\n\r\n---\r\n\r\nThis tab provides insights into admin or end-user configured **detection overrides** where the message was detected as a threat by Microsoft Defender for Office 365, however an admin-configured policy or end-user setting overrode the detection action.[

Learn more

](https://learn.microsoft.com/en-us/defender-office-365/step-by-step-guides/understand-overrides-in-email-entity) " + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "text - 13 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "ae594968-00b9-40b8-b5dd-052a27440afb" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Admin configured Detection Overrides (Allow)\r\n
\r\n\r\nThis section consolidates key visuals that track emails subject to administrator policies (e.g., Transport Rules, Tenant Allow/Block List) with an \"Allow\" action, overriding Microsoft Defender for Office 365 detections (excluding SecOps Mailbox overrides).

**Recommended action:** Review Allow overrides that later carried threats and remove stale or overly broad allow entries - they weaken protection." + }, + "name": "text - AdminOverridesAllowHeader", + "id": "3d70a304-c590-4156-a6d4-da147fe106ab" + }, + { + "type": 1, + "content": { + "json": "### Admin Overrides (Allow) Trend\r\n**Displays the count (per {Granularity}) of emails where an administrator policy with an \"Allow\" action overrode detections (excluding SecOps Mailbox). Helps track the frequency of admin overrides over time.**" + }, + "name": "text - AdminOverridesAllowTrend", + "id": "a4ee104a-a0a1-4725-a60f-deedcc91af70" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to an admin policy with action of allow independent of action taken, summarizing the data daily\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where isnotempty(OrgLevelPolicy) and OrgLevelPolicy!=\"SecOps Mailbox\" and OrgLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalAdminOverrides = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Admin Overrides'] = coalesce(TotalAdminOverrides, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Admin Overrides", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 3", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "79928e9e-48ed-4d08-8ff7-c21fe027550e" + }, + { + "type": 1, + "content": { + "json": "### Total Emails by Admin Override type (Allow)\r\n**Summarizes the total count of emails subject to administrator policies with an \"Allow\" action, grouped by the type of override. Helps identify which policies are most frequently allowing emails.**" + }, + "customWidth": "50", + "name": "text - AdminOverridesAllowByType", + "id": "855fce09-2000-4d16-8521-8b4eeddfae00" + }, + { + "type": 1, + "content": { + "json": "### Admin Overrides (Allow) by Override Type and Threat Type\r\n**Details the count of emails allowed by administrator policies, categorized by the override type and the detected threat type. Helps assess the risk associated with allowed emails.**" + }, + "customWidth": "50", + "name": "text - AdminOverridesAllowByTypeAndThreat", + "id": "a2613078-b427-4b23-aca0-21989b1944db" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails subject to an admin policy with action of allow, independent of action taken, summarizing the data by type of override\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelPolicy!=\"SecOps Mailbox\" and OrgLevelAction == \"Allow\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by OrgLevelPolicy", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 16", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b21a0329-8f52-45c2-81f2-6df65c134673" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to an admin policy with action of allow, independent of action taken, summarizing the data by type of override and threats type found\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelPolicy!=\"SecOps Mailbox\" and OrgLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by OrgLevelAction,OrgLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=OrgLevelAction, ['Override Policy']=OrgLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 2", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "0bf4cbe6-7c84-49d4-801c-d955762b5699" + }, + { + "type": 1, + "content": { + "json": "### SecOps Mailbox Overrides (Allow)\r\nThis section focuses on emails allowed specifically due to the SecOps Mailbox override policy, typically used for investigation and analysis.[

Learn more

](https://learn.microsoft.com/en-us/defender-office-365/advanced-delivery-policy-configure) " + }, + "name": "text - SecOpsOverridesHeader", + "id": "f582dc86-4c40-4cdd-ba0b-ec6ef8820a27" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails subject to the \r\nEmailEvents \r\n| where OrgLevelPolicy==\"SecOps Mailbox\" and OrgLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by OrgLevelPolicy", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "statSettings": { + "valueAggregation": "None", + "colorSettings": { + "type": "static", + "mode": "background", + "heatmapPalette": "greenRed", + "thresholdsGrid": [] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "tagText": "", + "valueFontStyle": "auto", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 1", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8ad2fea4-dcd0-454e-a4d4-b5275c86fd9b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails delivered to the SecOps Mailbox by threat type\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelPolicy==\"SecOps Mailbox\" and OrgLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by OrgLevelAction,OrgLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=OrgLevelAction, ['Override Policy']=OrgLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", + "size": 1, + "showAnalytics": true, + "title": " ", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 4", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "52c04df2-69b5-46e4-a000-7c6d212a132a" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "group - 15 - Admin Detection Overrides - Allow", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "9b9baf2f-fd5f-41b6-8368-b515f8de4fd4" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Admin configured Detection Overrides (Block)\r\n
\r\n\r\nThis section provides insights into email messages blocked by administrative policies (e.g. Tenant allow/block list, Antimalware policy file type block), overriding detection actions defined by Microsoft Defender for Office 365.

**Recommended action:** Confirm these blocks are still needed and consolidate them into the Tenant Allow/Block List where appropriate." + }, + "name": "text - AdminOverridesBlockHeader", + "id": "6157683b-cce7-4165-886f-0da73e25ce86" + }, + { + "type": 1, + "content": { + "json": "### Admin Overrides (Block) Trend\r\n**Displays the count (per {Granularity}) of emails where an administrator policy with a \"Block\" action overrode detections. Helps track the frequency of admin blocks over time.**" + }, + "name": "text - AdminOverridesBlockTrend", + "id": "699820b4-a984-45cc-ab2f-607c3c8569d4" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to an admin policy with action of block, summarizing the data daily\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where isnotempty(OrgLevelPolicy) and OrgLevelAction == \"Block\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalAdminOverrides = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Admin Overrides'] = coalesce(TotalAdminOverrides, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Admin Overrides", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 5", + "styleSettings": { + "margin": "10", + "padding": "10" + }, + "id": "9ef5e7fb-843e-439b-b4f3-9b0bb149e74b" + }, + { + "type": 1, + "content": { + "json": "### Total Emails by Admin Override Type (Block)\r\n**Summarizes the total count of emails subject to administrator policies with a \"Block\" action, grouped by the type of override.**" + }, + "customWidth": "50", + "name": "text - AdminOverridesBlockByType", + "id": "5694a7c0-1ee5-40b4-ae2b-263d189c4b4e" + }, + { + "type": 1, + "content": { + "json": "### Admin Overrides (Block) by Override Type and Threat Type\r\n**Details the count of emails blocked by administrator policies, categorized by the override type and the detected threat type.**" + }, + "customWidth": "50", + "name": "text - AdminOverridesBlockByTypeAndThreat", + "id": "6e309742-37c0-4ad5-9b9a-63643059bfaf" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails subject to an admin policy with action of block, summarizing the data by type of override\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelAction == \"Block\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by OrgLevelPolicy", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 6", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "eabc80ed-d0e9-43d2-ab13-a5af478f11c8" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to an admin policy with action of block, summarizing the data by type of override and threats type found\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelAction == \"Block\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by OrgLevelAction,OrgLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=OrgLevelAction, ['Override Policy']=OrgLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 7", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1661bfa6-d8fd-4387-a334-1bc027a3f6d1" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "group - 36-Admin Detection Overrides - Block", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "7d514e9a-f67f-45a6-ba1b-6492348cc18b" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
User configured Detection Overrides (Allow)\r\n
\r\n\r\nThis section consolidates key visuals that track email messages subject to user policies (e.g. [Safe Senders list defined in Outlook](https://learn.microsoft.com/en-us/defender-office-365/create-safe-sender-lists-in-office-365#use-outlook-safe-senders)) with an \"Allow\" action, overriding Microsoft Defender for Office 365 detections.

**Recommended action:** Educate users that safe-sender allows can bypass protection; review high-risk user allow entries." + }, + "name": "text - UserOverridesAllowHeader", + "id": "4d41c560-0e73-40c5-b610-33e9500e88c4" + }, + { + "type": 1, + "content": { + "json": "### User Overrides (Allow) Trend\r\n**Displays the count (per {Granularity}) of emails where a user policy with an \"Allow\" action overrode detections. Helps track the frequency of user overrides over time.**" + }, + "name": "text - UserOverridesAllowTrend", + "id": "9432efff-9f03-4d74-8781-02be8b2d07fa" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to a user type policy with action of allow, summarizing the data daily\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalUserOverrides = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['User Overrides'] = coalesce(TotalUserOverrides, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "User Overrides", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 3", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "02da1d33-e477-479d-bdd3-95ab1ad7c75c" + }, + { + "type": 1, + "content": { + "json": "### Total Emails by User Override Type (Allow)\r\n**Summarizes the total count of emails subject to user policies with an \"Allow\" action, grouped by the type of override.**" + }, + "customWidth": "50", + "name": "text - UserOverridesAllowByType", + "id": "006a2e87-b1b6-4cc3-a763-ceebaa86b340" + }, + { + "type": 1, + "content": { + "json": "### User Overrides (Allow) by Override Type and Threat Type\r\n**Details the count of emails allowed by user policies, categorized by the override type and the detected threat type. Helps assess the risk associated with user-allowed emails.**" + }, + "customWidth": "50", + "name": "text - UserOverridesAllowByTypeAndThreat", + "id": "7c34bb4b-46c0-4054-9596-3dfd010bb036" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails subject to a user type policy with action of allow, summarizing the data by type of override\r\nEmailEvents \r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Allow\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by UserLevelPolicy", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 16", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d1d9021d-e6bf-47b1-bdd2-438a212d2767" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to a user type policy with action of allow, summarizing the data by type of override and threats type found\r\nEmailEvents \r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Allow\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by UserLevelAction,UserLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=UserLevelAction, ['Override Policy']=UserLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 2", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1acd913c-c945-4a58-b04e-d008ca53ffe3" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "group - 15 - User Detection Overrides - Allow", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "c939060e-6a8b-49ff-951b-a3abddbd9fb4" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
User configured Detection Overrides (Block)\r\n
\r\n\r\nThis section provides insights into emails blocked by user-configured policies (e.g., [Blocked Senders list in Outlook](https://support.microsoft.com/en-us/office/block-or-unblock-senders-in-outlook-9bf812d4-6995-4d19-901a-76d6e26939b0)).

**Recommended action:** Use user block trends to identify unwanted senders that may warrant tenant-wide blocking." + }, + "name": "text - UserOverridesBlockHeader", + "id": "be6c6a3e-08ee-47c5-b8e7-6a1078dd17d1" + }, + { + "type": 1, + "content": { + "json": "### User Overrides (Block) Trend\r\n**Displays the count (per {Granularity}) of emails where a user policy with a \"Block\" action overrode detections. Helps track the frequency of user blocks over time.**" + }, + "name": "text - UserOverridesBlockTrend", + "id": "7cd77d54-2e2b-4d23-a6a9-4bd6bca2642a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to a user type policy with action of block, summarizing the data daily\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Block\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalUserOverrides = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['User Overrides'] = coalesce(TotalUserOverrides, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "User Overrides", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 5", + "styleSettings": { + "margin": "10", + "padding": "10" + }, + "id": "0b21b66c-001d-4b3d-b47f-f3a420ccaaf8" + }, + { + "type": 1, + "content": { + "json": "### Total Emails by User Override Type (Block)\r\n**Summarizes the total count of emails subject to user policies with a \"Block\" action, grouped by the type of override.**" + }, + "customWidth": "50", + "name": "text - UserOverridesBlockByType", + "id": "fd513501-5e9d-45d9-9d0d-cd546002b8cf" + }, + { + "type": 1, + "content": { + "json": "### User Overrides (Block) by Override Type and Threat Type\r\n**Details the count of emails blocked by user policies, categorized by the override type and the detected threat type.**" + }, + "customWidth": "50", + "name": "text - UserOverridesBlockByTypeAndThreat", + "id": "4fbfa876-47ed-4c3b-81ee-1c40b982cecd" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails subject to a user type policy with action of block, summarizing the data by type of override\r\nEmailEvents \r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Block\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by UserLevelPolicy", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 6", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d3fccaa6-80fd-419d-bb37-aedf67263419" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to a user type policy with action of block, summarizing the data by type of override and threats type found\r\nEmailEvents \r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Block\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by UserLevelAction,UserLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=UserLevelAction, ['Override Policy']=UserLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 7", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e5e74ce1-fa67-45ea-bc80-97237342e370" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "group - 37-User Detection Overrides - Block", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "0c1d327a-c2f1-4b9b-b210-53c808b53b48" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
User & Sender Override Detail (Allow)\r\n
\r\n\r\nInbound messages that Microsoft Defender for Office 365 **detected as threats but delivered anyway** because of an admin- or user-configured **Allow** override (phishing-simulation and SecOps Mailbox traffic excluded). **Total Threats** is all detected threats to that recipient / sender domain in the selected range; **Overridden Threats** and **Override %** are the portion delivered due to an Allow override, and **Override Types** names the specific overrides responsible. **User-configured** overrides come from the recipient's own mailbox junk-email settings in Outlook / Outlook on the web (the mailbox \"safelist collection\") — the **Safe Senders** and **Safe Recipients** lists and **trusted contacts** (\"Also trust email from my Contacts\"). **Admin-configured** overrides come from the **Tenant Allow/Block List, Exchange mail flow (transport) rules, the IP Allow List, or allowed sender/domain lists in anti-spam policies**. Use this to spot users or domains where overrides are letting threats through — candidates for policy review or a Tenant Allow/Block List (TABL) block.

**Recommended action:** Focus on the users and sender domains with the most allow overrides - these are the biggest protection gaps." + }, + "name": "Overrides - User Detail Header", + "id": "3b0e83f3-f340-4b95-85c5-831783e8abc2" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top recipients receiving threats that were delivered due to an admin or user override, with the share of their threats that were overridden and a breakdown of which override types caused them.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend OverrideType = case(\r\n OrgLevelAction == \"Allow\" and OrgLevelPolicy != \"\" and OrgLevelPolicy != \"SecOps Mailbox\", OrgLevelPolicy,\r\n UserLevelAction == \"Allow\", strcat(\"User: \", UserLevelPolicy),\r\n \"(none)\")\r\n| summarize PerType = count() by RecipientEmailAddress, OverrideType\r\n| summarize TotalThreats = sum(PerType),\r\n OverriddenThreats = sumif(PerType, OverrideType != \"(none)\"),\r\n OverrideTypes = strcat_array(make_set_if(strcat(OverrideType, \" (\", PerType, \")\"), OverrideType != \"(none)\"), \"; \")\r\n by RecipientEmailAddress\r\n| where OverriddenThreats > 0\r\n| extend OverridePercent = round(OverriddenThreats * 100.0 / TotalThreats, 1)\r\n| top 15 by OverriddenThreats\r\n| project ['Recipient']=RecipientEmailAddress, ['Total Threats']=TotalThreats, ['Overridden Threats']=OverriddenThreats, ['Override %']=OverridePercent, ['Override Types']=OverrideTypes", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Overridden Threats", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Override %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ] + }, + "graphSettings": { + "type": 2, + "topContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Value", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + }, + "nodeIdField": "StatisticName", + "sourceIdField": "Value", + "targetIdField": "Value", + "graphOrientation": 3, + "showOrientationToggles": false, + "nodeSize": null, + "staticNodeSize": 100, + "colorSettings": null, + "hivesMargin": 5, + "edgeColorSettings": null + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "Overrides - Top Users", + "id": "d7e169a2-808a-4bbf-86ee-5be561c690f7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top sender domains sending threats to users, with the share of those threats that were delivered because of an admin or user override and a breakdown of which override types caused them. High override rates are strong candidates for policy review or a Tenant Allow/Block List (TABL) block.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend OverrideType = case(\r\n OrgLevelAction == \"Allow\" and OrgLevelPolicy != \"\" and OrgLevelPolicy != \"SecOps Mailbox\", OrgLevelPolicy,\r\n UserLevelAction == \"Allow\", strcat(\"User: \", UserLevelPolicy),\r\n \"(none)\")\r\n| summarize PerType = count() by SenderFromDomain, OverrideType\r\n| summarize TotalThreats = sum(PerType),\r\n OverriddenThreats = sumif(PerType, OverrideType != \"(none)\"),\r\n OverrideTypes = strcat_array(make_set_if(strcat(OverrideType, \" (\", PerType, \")\"), OverrideType != \"(none)\"), \"; \")\r\n by SenderFromDomain\r\n| where OverriddenThreats > 0\r\n| extend OverridePercent = round(OverriddenThreats * 100.0 / TotalThreats, 1)\r\n| top 10 by OverriddenThreats\r\n| project ['Sender Domain']=SenderFromDomain, ['Total Threats']=TotalThreats, ['Overridden Threats']=OverriddenThreats, ['Override %']=OverridePercent, ['Override Types']=OverrideTypes", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Overridden Threats", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Override %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ] + }, + "graphSettings": { + "type": 2, + "topContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Value", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + }, + "nodeIdField": "StatisticName", + "sourceIdField": "Value", + "targetIdField": "Value", + "graphOrientation": 3, + "showOrientationToggles": false, + "nodeSize": null, + "staticNodeSize": 100, + "colorSettings": null, + "hivesMargin": 5, + "edgeColorSettings": null + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "Overrides - Top Sender Domains", + "id": "0eda3153-10ea-4d4e-80ca-7e5ad99e9883" + } + ] + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "Overrides - User & Sender Detail", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "d5f38e54-a3c7-4df6-b569-bbabe85e1a36" + }, + { + "type": 1, + "content": { + "json": "# False Negative(FN) Submissions insights\r\n\r\n---\r\n\r\nThis tab provides insights into email message **False Negative(FN) Submissions** performed by users or administrators in Microsoft Defender for Office 365 where the message reported to have **Malware, Phish or Spam threat** within its **content, URLs or attachments**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "8" + }, + "name": "text - 13 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3b243dca-89ce-41e6-bccb-9ceb0953aa2e" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
False Negative(FN) Admin submissions\r\n
\r\n\r\nThis section provides insights into email message **False Negative(FN) Submissions performed by administrators** in Microsoft Defender for Office 365 where the message reported to have Malware, Phish or Spam threat within its content, URLs or attachments.

**Recommended action:** Prioritise admin-submitted misses for policy tuning; recurring sender domains may be block-list candidates." + }, + "name": "fn admin - section header", + "id": "64420254-0dae-4495-bd55-fc49e5bc1ed0" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) Admin Submissions per-{Granularity} trend by submission types \r\n**Displays counts (per {Granularity}) of False Negative(FN) Admin Submissions grouped by submission type (Spam, Phish, Malware) and content type (Mail, URL, Attachment). Helps to monitor where detections were missed and later submitted by admins as false negatives to Microsoft.**" + }, + "name": "fn admin - trend heading", + "id": "5f2de929-6f32-4079-a031-cbf689c15b29" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of admin false negative submission by submission type.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(CloudAppEvents\r\n| where ActionType contains \"Submission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| summarize Admin_Malware_FN=countif(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"), Admin_Phish_FN=countif(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"), Admin_Spam_FN=countif(SubmissionType == \"0\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"), Admin_Malware_URL_FN=countif(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\"), Admin_Malware_Attach_FN=countif(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\"), Admin_Phish_URL_FN=countif(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\"), Admin_Phish_Attach_FN=countif(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Malware (Mail)']=coalesce(Admin_Malware_FN,0), ['Phish (Mail)']=coalesce(Admin_Phish_FN,0), ['Spam (Mail)']=coalesce(Admin_Spam_FN,0), ['Malware (URL)']=coalesce(Admin_Malware_URL_FN,0), ['Malware (Attachment)']=coalesce(Admin_Malware_Attach_FN,0), ['Phish (URL)']=coalesce(Admin_Phish_URL_FN,0), ['Phish (Attachment)']=coalesce(Admin_Phish_Attach_FN,0) | sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "TotalAdminSubmissions", + "color": "redDark" + }, + { + "seriesName": "Phish (Mail)", + "color": "redBright" + }, + { + "seriesName": "Spam (Mail)", + "color": "orange" + }, + { + "seriesName": "Malware (Mail)", + "color": "redDark" + }, + { + "seriesName": "Phish (URL)", + "color": "purple" + }, + { + "seriesName": "Malware (Attachment)", + "color": "yellowDark" + }, + { + "seriesName": "Phish (Attachment)", + "color": "purpleDark" + }, + { + "seriesName": "Malware (URL)", + "color": "yellow" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "fn admin - submissions trend", + "id": "1b61155b-92a1-4533-9561-2e85e9a4dbf8" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) Admin Submissions by submission types \r\n**Displays counts (per {Granularity}) of False Negative(FN) Admin Submissions grouped by submission type (Spam, Phish, Malware) and content type (Mail, URL, Attachment).**" + }, + "customWidth": "50", + "name": "fn admin - by-type heading", + "id": "bbaa9ff9-a95d-495a-a44c-6b4cae888a24" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) Admin Submissions by submission State\r\n**Displays the total count of False Negative(FN) Admin Submissions by submission State (e.g., Pending, Completed, Failed). Helps track the processing status of admin submissions and identify bottlenecks or errors.**" + }, + "customWidth": "50", + "name": "fn admin - by-state heading", + "id": "b060c706-342a-4b2e-b81a-920bf4d8c5d9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of admin false negative submission by submission type.\r\nCloudAppEvents \r\n| where ActionType contains \"Submission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| extend Admin_SubmissionType=\r\niff(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Malware (Mail)\",\r\niff(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\r\niff(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\",\"Malware (URL)\",\r\niff(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\",\"Malware (Attachment)\",\r\niff(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\",\"Phish (URL)\",\r\niff(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\",\"Phish (Attachment)\",\r\n\"Other\")))))))\r\n| where Admin_SubmissionType!=\"Other\"\r\n| summarize count() by Admin_SubmissionType", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn admin - by-type pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "9d9d714a-357b-4ac3-bcb7-33601d3c3108" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of admin false negative submissions by the state of the submission.\r\nCloudAppEvents \r\n| where ActionType contains \"AdminSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType in (\"0\",\"1\",\"2\")\r\n| summarize count() by tostring(SubmissionState)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn admin - by-state pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "169f0f1c-1f1e-44fb-965e-850733f01879" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN)/False Positive(FP) Admin Submissions by Triage Verdict\r\n**Displays the total count of False Negative(FN)/False Positive(FP) Admin Submissions grouped by TriageVerdict (e.g., Malware, Spam, Phish, Clean). Helps assess how submissions were graded during triage and identify detection gaps.**" + }, + "customWidth": "50", + "name": "fn admin - triage-verdict heading", + "id": "3df841be-c1b0-4d61-8e38-316a34a48bd1" + }, + { + "type": 1, + "content": { + "json": "### Top Admins Submitting False Negatives \r\n**Displays the top 15 admin accounts that submitted the highest number of false negative messages (missed detections) via AdminSubmission. Helps identify key contributors to threat remediation and potential patterns in detection gaps.**" + }, + "customWidth": "50", + "name": "fn admin - top-admins heading", + "id": "e1e966f4-1f4d-4377-97c6-e2077fc0b8fa" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of admin false negative or false positive submissions by the verdict of the submission grading.\r\nCloudAppEvents \r\n| where ActionType contains \"AdminSubmissionTriage\" \r\n| extend UserKey = (parse_json(RawEventData)).UserKey, SubmissionState = (parse_json(RawEventData)).SubmissionState, SubmissionId=(parse_json(RawEventData)).SubmissionId, TriageVerdict=(parse_json(RawEventData)).GradingResult.TriageVerdict \r\n| summarize count() by tostring(TriageVerdict)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn admin - triage-verdict pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6df0db72-f9db-444e-856a-4369921d199b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top admins performing false negative submissions\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend Record= (parse_json(RawEventData)).RecordType,SubmissionState = (parse_json(RawEventData)).SubmissionState, UserId = (parse_json(RawEventData)).UserId,SubmissionType = parse_json(RawEventData).SubmissionType \r\n| where Record == 29 and SubmissionType in (\"0\",\"1\",\"2\")\r\n| summarize ['Submissions']=count() by ['Admin']=tostring(UserId)\r\n| top 15 by ['Submissions'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn admin - top-admins pie", + "id": "b5ccb4a1-9783-47cf-bf21-ded924f1a200" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) Admin Submissions by Top Sender Domains\r\n**For each top sender domain that admins reported missed threats for, shows the domain's MDO-detected threat profile (emails with threats and the Malware/Phish/Spam breakdown), the count of admin FN submissions, and the submission rate (Admin Submission % = admin submissions / total inbound from the domain). A high rate can flag a domain whose mail is frequently reported as missed.**" + }, + "customWidth": "100", + "name": "fn admin - top-sender-domains heading", + "id": "1a481c97-ac85-4b62-a86d-51b33b5a8e68" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top 10 sender domains that admins reported false negatives (missed threats) for, with each domain's MDO-detected threat profile for context.\r\nlet subs = CloudAppEvents\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType), SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), P2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"2\",\"1\",\"0\")\r\n| summarize AdminSubmissions=count() by P2SenderDomain;\r\nlet domainProfile = EmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalInbound=count(), EmailsWithThreats=countif(isnotempty(ThreatTypes)), Malware=countif(ThreatTypes has \"Malware\"), Phish=countif(ThreatTypes has \"Phish\"), Spam=countif(ThreatTypes has \"Spam\") by SenderFromDomain;\r\nsubs\r\n| join kind=leftouter (domainProfile) on $left.P2SenderDomain == $right.SenderFromDomain\r\n| extend AdminSubmissionPct = round(AdminSubmissions * 100.0 / todouble(coalesce(TotalInbound, AdminSubmissions)), 2)\r\n| top 10 by AdminSubmissions desc\r\n| project ['Sender Domain']=P2SenderDomain, ['Emails With Threats']=coalesce(EmailsWithThreats,0), ['Malware']=coalesce(Malware,0), ['Phish']=coalesce(Phish,0), ['Spam']=coalesce(Spam,0), ['Admin Submissions']=AdminSubmissions, ['Admin Submission %']=AdminSubmissionPct", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails With Threats", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Malware", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Phish", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Spam", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Admin Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "120px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Admin Submission %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "110px" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn admin - top-sender-domains table", + "id": "e56bed92-b0fb-4b76-90f3-169f4206418b" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) Admin Submissions by admin Detection override types\r\n**Displays the top 10 cases where emails were submitted as false negatives by admins, even though they were initially detected by Microsoft Defender for Office 365 but delivered due to an admin policy override. Includes details on PolicyOverride, PolicySource, and DetectionVerdict for deeper insight into override behaviour.**" + }, + "customWidth": "100", + "name": "fn admin - override-types heading", + "id": "293c174c-0197-4cf8-bbce-36fe42e5cf1b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises emails submitted as false negatives by admins where emails where already detected by MDO but there was a admin policy override\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| extend Admin_SubmissionType=\r\niff(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Malware (Mail)\",\r\niff(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\"))),\r\nP2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain),NetworkMessageId=tostring((parse_json(RawEventData).ObjectId)),DetectionVerdict=tostring((parse_json(RawEventData)).DeliveryMessageInfo.FinalFilterVerdict),PolicyOverride=tostring((parse_json(RawEventData)).DeliveryMessageInfo.PolicyOverride),PolicyPolicyOverrideType=tostring((parse_json(RawEventData)).DeliveryMessageInfo.PolicySource)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"2\",\"1\",\"0\") and PolicyOverride !=\"NoOverride\"\r\n| summarize count() by PolicyOverride, PolicyPolicyOverrideType,DetectionVerdict,Admin_SubmissionType\r\n| top 10 by count_ desc\r\n| project ['Policy Override']=PolicyOverride, ['Override Source']=PolicyPolicyOverrideType, ['Detection Verdict']=DetectionVerdict, ['Submission Type']=Admin_SubmissionType, ['Emails']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn admin - override-types table", + "id": "97799422-53e0-4e3b-8103-297fd1c744eb" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "8" + }, + "name": "group - 11-Fn Admin Submissions", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "45a1c185-4fbf-4e83-832e-1f20af427796" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
False Negative(FN) User submissions\r\n
\r\n\r\nThis section provides insights into email message **False Negative(FN) Submissions performed by end users** in Microsoft Defender for Office 365 where the message reported as having Phish, Spam threat within its content, URLs or attachments.

**Recommended action:** Recognise engaged reporters, coach over-reporters, and use graded phishing verdicts to tune anti-phishing policy." + }, + "name": "fn user - section header", + "id": "ca0b48e6-8bd8-4f99-956a-f9c72cc870db" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions per-{Granularity} trend by submission types \r\n**Displays counts (per {Granularity}) of False Negative(FN) User Submissions grouped by submission type (Spam, Phish and Attack simulations) . Helps to monitor where detections were missed and later submitted by users as false negatives.**" + }, + "name": "fn user - trend heading", + "id": "60ac8608-7875-45e6-8c83-e6bd0c34af8b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of users false negative submission by submission type, including phish simulations reported by users.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(CloudAppEvents\r\n| where ActionType contains \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| summarize User_Phish_FN=countif(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\"), User_Spam_FN=countif(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\"), User_AttackSim_Submission=countif(ActionType == \"AttackSimUserSubmission\" and SubmissionContentType==\"Mail\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Phish (Mail)']=coalesce(User_Phish_FN,0), ['Spam (Mail)']=coalesce(User_Spam_FN,0), ['Attack simulation reported']=coalesce(User_AttackSim_Submission,0) | sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "TotalAdminSubmissions", + "color": "redDark" + }, + { + "seriesName": "Phish (Mail)", + "color": "redDark" + }, + { + "seriesName": "Attack simulation reported", + "color": "green" + }, + { + "seriesName": "Spam (Mail)", + "color": "orangeDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "fn user - submissions trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "29355816-6cba-4264-938e-b0b27afdcb12" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions by submission State\r\n**Displays the total count of False Negative(FN) User Submissions by submission State (e.g., Pending, Completed, Failed). Helps track the processing status of user submissions and identify bottlenecks or errors.**" + }, + "customWidth": "50", + "name": "fn user - by-state heading", + "id": "6a4b32cc-b7e4-47bb-b1b9-f415df7e629c" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions by Triage Verdict\r\n**Displays the total count of False Negative(FN)/False Positive(FP) User Submissions grouped by TriageVerdict (e.g., Malware, Spam, Phish, Clean). Helps assess how submissions were graded during triage and identify detection gaps.**" + }, + "customWidth": "50", + "name": "fn user - triage-verdict heading", + "id": "1427e34f-be44-4517-ae73-cc4776a49fe7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of user false negative submissions by the state of the submission.\r\nCloudAppEvents \r\n| where ActionType contains \"UserSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType in (\"0\",\"1\")\r\n| summarize count() by tostring(SubmissionState)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - by-state pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a6151271-e925-4804-a3c1-06afee27c026" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of user false negative or false positive submissions by the verdict of the submission grading.\r\nCloudAppEvents \r\n| where ActionType contains \"UserSubmissionTriage\" \r\n| extend UserKey = (parse_json(RawEventData)).UserKey, SubmissionState = (parse_json(RawEventData)).SubmissionState, SubmissionId=(parse_json(RawEventData)).SubmissionId, TriageVerdict=(parse_json(RawEventData)).GradingResult.TriageVerdict \r\n| summarize count() by tostring(TriageVerdict)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - triage-verdict pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6ff319ea-b5c5-4e33-9e5c-065aadbf465d" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions of already detected Emails (from Junk folder)\r\n**Displays the total count of False Negative(FN) User Submissions where the email message was already detected by Microsoft Defender for Office 365 and the detection action was configured to deliver the message into the Junk folder of the user mailbox. It breaks down the result based on the original detection verdict determined by Microsoft Defender for Office 365. Helps track the user submissions of messages that already had a detection. Consider changing the detection action to Quarantine to avoid these submissions.**" + }, + "name": "fn user - junk-folder heading", + "id": "d6338907-489d-4c88-b82f-260fc0f9d302" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of user false negative submissions that are already detected by MDO and already delivered in the junk folder\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where DeliveryLocation == \"Junk folder\"\r\n| summarize count() by ThreatTypes,User_SubmissionType\r\n| project ThreatTypes,User_SubmissionType, Emails = count_", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - junk-folder pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "c13452cb-e864-4f01-8623-51f3ea13bbbc" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of user false negative submissions that are already detected by MDO and already delivered in the junk folder\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId,UserId = (parse_json(RawEventData)).UserId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where DeliveryLocation == \"Junk folder\"\r\n| extend MDO_detection = parse_json(DetectionMethods) \r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n| summarize TotalJunkSubmittedEmailCount=count(),PhishEmailCount = countif(FirstDetection == \"Phish\"),SpamEmailCount = countif(FirstDetection == \"Spam\") by tostring(UserId)\r\n| top 15 by TotalJunkSubmittedEmailCount desc\r\n| project ['User']=UserId, ['Junk Submissions']=TotalJunkSubmittedEmailCount, ['Phish']=PhishEmailCount, ['Spam']=SpamEmailCount", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Junk Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spam", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - junk-folder table", + "id": "b242f301-c9f7-41f9-aa73-03848bd58eae" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions - Admin review status (Mark and Notify)\r\n**Displays counts of False Negative(FN) User Submissions that were reviewed by admins and marked with a notify action. The Mark and Notify action also can be taken automatically with Automated investigation and response (AIR). Helps track cases where admins confirmed user reports and communicated the outcome, supporting transparency and user trust.**" + }, + "customWidth": "50", + "name": "fn user - mark-notify heading", + "id": "784bf171-53ae-4907-b2b0-7fc5039df231" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions accuracy vs Admin review verdict\r\n**Displays counts of False Negative(FN) User Submissions (Phish, Junk, NotJunk) compared to admin review results. Highlights whether submissions were Correct, Not Correct, or misclassified comparing user submission type with the Admin decision using Mark and Notify action in Microsoft Defender for Office 365 (e.g., “Phish reported as Junk”, “Reported but not malicious”).**" + }, + "customWidth": "50", + "name": "fn user - accuracy heading", + "id": "3d137383-6436-4213-9824-72f424b67290" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises user submissions where admin also performed 'mark and notify' action on the submission\r\nlet ReviewResults = CloudAppEvents | where ActionType == \"SubmissionNotification\" \r\n| extend SubmissionId = tostring(parse_json(RawEventData).SubmissionId)\r\n| extend Properties = parse_json(RawEventData.ExtendedProperties)\r\n| mv-expand element = Properties\r\n| where element.Name == \"AdminReviewResult\"\r\n| project SubmissionId, AdminReviewResult = element.Value;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionId = tostring(parse_json(RawEventData).SubmissionId), SubmissionType = parse_json(RawEventData).SubmissionType\r\n| join kind=leftouter ReviewResults on SubmissionId\r\n| extend UserReportedAs=iif(SubmissionType == 1, \"Phish\",iif(SubmissionType == 2, \"Junk\",iif(SubmissionType == 3, \"NotJunk\",\"\")))\r\n| extend ReviewedAccuracy=iif(UserReportedAs==AdminReviewResult, 1,0)\r\n| extend Reviewed=iif(isempty(AdminReviewResult),\"Not Reviewed\",\"Reviewed\")\r\n| project SubmissionId,UserReportedAs,Reviewed,AdminReviewResult, ReviewedAccuracy\r\n| summarize count() by Reviewed", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - mark-notify pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "7bb7d116-bd61-4e46-81dd-d634a31e7369" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises user submissions type compared to admin review verdict. \r\n//Eg. User reporting a phish but admin review is 'not threat found'\r\nlet ReviewResults = CloudAppEvents | where ActionType == \"SubmissionNotification\" \r\n| extend SubmissionId = tostring(parse_json(RawEventData).SubmissionId)\r\n| extend Properties = parse_json(RawEventData.ExtendedProperties)\r\n| mv-expand element = Properties\r\n| where element.Name == \"AdminReviewResult\"\r\n| project SubmissionId, AdminReviewResult = element.Value;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionId = tostring(parse_json(RawEventData).SubmissionId), SubmissionType = parse_json(RawEventData).SubmissionType\r\n| join kind=leftouter ReviewResults on SubmissionId\r\n| extend UserReportedAs=iif(SubmissionType == 1, \"Phish\",iif(SubmissionType == 2, \"Junk\",iif(SubmissionType == 3, \"NotJunk\",\"\")))\r\n| extend ReviewedAccuracy=iif(AdminReviewResult==UserReportedAs, \"Correct\", iif(AdminReviewResult==\"Phish\" and UserReportedAs == \"Junk\", \"Phish reported as junk\",iif(AdminReviewResult==\"Junk\" and UserReportedAs == \"Phish\",\"Junk reported as Phish\",iif(AdminReviewResult==\"NotJunk\",\"Reported but not malicious or spam\",iif(isempty(AdminReviewResult),\"Not Reviewed\",\"Not correct\")))))\r\n| extend Reviewed=iif(isempty(AdminReviewResult),\"Not Reviewed\",\"Reviewed\")\r\n| project SubmissionId,UserReportedAs,Reviewed,AdminReviewResult, ReviewedAccuracy\r\n| where Reviewed==\"Reviewed\"\r\n| summarize count() by ReviewedAccuracy", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - accuracy pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8af1b9f0-995c-4c58-9960-8e69c6960987" + }, + { + "type": 1, + "content": { + "json": "### Top 10 P2 Email Senders domains in False Negative(FN) User Submissions \r\n**Displays the top 10 P2 email sender domains of inbound emails reported by users as false negatives (missed detections). Includes total inbound email volume and calculates the percentage of user submissions per domain to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "fn user - top-p2-domains heading", + "id": "78dab1f9-09ec-46e2-aee4-f256e368cdd5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises top 10 sender domains of inbound emails submitted as false negatives by users.\r\nlet TotalInboundbySender=\r\nEmailEvents\r\n| where EmailDirection ==\"Inbound\"\r\n| summarize count() by SenderFromDomain;\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType),RecipientObjectId=AccountObjectId,NetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\"\r\n| summarize UserSubmissions=count() by SenderFromDomain\r\n| join TotalInboundbySender on SenderFromDomain\r\n| extend UserSubmissions_Percentage = todouble(round(UserSubmissions / todouble(count_) * 100, 2))\r\n| top 10 by UserSubmissions desc\r\n| project ['Sender Domain']=SenderFromDomain, ['User Submissions']=UserSubmissions, ['Total Inbound']=count_, ['User Submission %']=UserSubmissions_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "User Submission %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "12ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - top-p2-domains table", + "id": "6e6a59d4-70e1-4d85-bebb-6bb23d25d2d9" + }, + { + "type": 1, + "content": { + "json": "### Top 10 P2 Individual Email Senders in False Negative(FN) User Submissions \r\n**Displays the top 10 P2 individual email sender addresses of inbound emails reported by users as false negatives (missed detections). Includes total inbound email volume and calculates the percentage of user submissions per sender to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "fn user - top-p2-senders heading", + "id": "a6e8fda5-dd05-49ed-87e2-16443495396e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises top 10 sender email addresses of inbound emails submitted as false negatives by users.\r\nlet TotalInboundbySender=\r\nEmailEvents\r\n| where EmailDirection ==\"Inbound\"\r\n| summarize count() by SenderFromAddress;\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType),P2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain),RecipientObjectId=AccountObjectId,NetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\"\r\n| summarize UserSubmissions=count() by SenderFromAddress\r\n| join TotalInboundbySender on SenderFromAddress\r\n| extend UserSubmissions_Percentage = todouble(round(UserSubmissions / todouble(count_) * 100, 2))\r\n| top 10 by UserSubmissions desc\r\n| project ['Sender Address']=SenderFromAddress, ['User Submissions']=UserSubmissions, ['Total Inbound']=count_, ['User Submission %']=UserSubmissions_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "User Submission %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "12ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - top-p2-senders table", + "id": "878fd15f-2607-4d6d-b919-0b4bea6a1850" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Intra-org Email Senders in False Negative(FN) User Submissions \r\n**Displays the top 10 email senders of intra-org emails reported by users as false negatives (missed detections). Includes total intra-org email volume and calculates the percentage of user submissions per sender to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "fn user - intraorg-senders heading", + "id": "87a51814-7f01-42e3-aea2-4136c869d39d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises top 10 sender email address of intra-org emails submitted as false negatives by users.\r\nlet TotalInboundbySender=\r\nEmailEvents\r\n| where EmailDirection ==\"Intra-org\"\r\n| summarize count() by SenderFromAddress;\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType),P2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain),RecipientObjectId=AccountObjectId,NetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Intra-org\"\r\n| summarize UserSubmissions=count() by SenderFromAddress\r\n| join TotalInboundbySender on SenderFromAddress\r\n| extend UserSubmissions_Percentage = todouble(round(UserSubmissions / todouble(count_) * 100, 2))\r\n| top 10 by UserSubmissions desc\r\n| project ['Sender Address']=SenderFromAddress, ['User Submissions']=UserSubmissions, ['Total Intra-org']=count_, ['User Submission %']=UserSubmissions_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Intra-org", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "User Submission %", + "formatter": 4, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "12ch" + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - intraorg-senders table", + "id": "38edca4b-a403-41e8-8c2b-7c0595e93b7a" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Intra-org Email Subjects in False Negative(FN) User Submissions \r\n**Displays the top 10 Email Subjects of intra-org emails reported by users as false negatives (missed detections). Helps to highlight high-risk intra-org email sources.**" + }, + "customWidth": "100", + "name": "fn user - intraorg-subjects heading", + "id": "52b0bc5b-7e54-4a5b-a487-8a736a8c2397" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises top 10 subjects of intra-org emails submitted as false negatives by users.\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Intra-org\"\r\n| summarize count() by Subject\r\n| top 10 by count_ desc\r\n| project ['Subject']=Subject, ['User Submissions']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Subject", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "70ch" + } + }, + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - intraorg-subjects table", + "id": "ee2c1d2e-3d4e-4024-8422-985b22cb7475" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Detection Overrides defined by Admins in False Negative(FN) User Submissions \r\n**Displays the top 10 use cases where users submitted emails as false negatives (Spam or Phish) that were already detected by Microsoft Defender for Office 365 but delivered due to an admin-defined policy override. Includes details on OrgLevelAction, OrgLevelPolicy, and ThreatTypes for deeper insight into override behaviour.**" + }, + "customWidth": "100", + "name": "fn user - admin-override heading", + "id": "0dd9b3ce-9716-42bb-93de-495f0af2d075" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises emails submitted as false negatives by users where emails where already detected by MDO but there was an admin definded policy override.\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where ThreatTypes !=\"\"and OrgLevelAction!=\"\"\r\n| summarize count() by OrgLevelAction, OrgLevelPolicy,ThreatTypes,User_SubmissionType\r\n| top 10 by count_ desc\r\n| project ['Override Action']=OrgLevelAction, ['Override Policy']=OrgLevelPolicy, ['Threat Type']=ThreatTypes, ['Submission Type']=User_SubmissionType, ['User Submissions']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Override Policy", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "48ch" + } + }, + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - admin-override table", + "id": "100de6ca-beb0-44d7-a715-449a389e9e8a" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Detection Overrides defined by Users in False Negative(FN) User Submissions \r\n**Displays the top 10 use cases where users submitted emails as false negatives (Spam or Phish) that were already detected by Microsoft Defender for Office 365 but delivered due to a user-defined override. Includes details on UserLevelAction, UserLevelPolicy, and ThreatTypes for deeper insight into override behaviour.**" + }, + "customWidth": "100", + "name": "fn user - user-override heading", + "id": "67057c7d-c0af-4373-b23a-4001fbced888" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises emails submitted as false negatives by users where emails where already detected by MDO but there was an policy override.\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where ThreatTypes !=\"\"and UserLevelAction!=\"\"\r\n| summarize count() by UserLevelAction, UserLevelPolicy,ThreatTypes,User_SubmissionType\r\n| top 10 by count_ desc\r\n| project ['Override Action']=UserLevelAction, ['Override Policy']=UserLevelPolicy, ['Threat Type']=ThreatTypes, ['Submission Type']=User_SubmissionType, ['User Submissions']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Override Policy", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "48ch" + } + }, + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - user-override table", + "id": "1b97f7d2-152d-4eb0-bfac-e161fbfa4046" + }, + { + "type": 1, + "content": { + "json": "### Top 10 users performing the most False Negative(FN) User Submissions\r\n**Displays the Top 10 user accounts that performed the highest number of False Negative(FN) User Submissions (missed detections). Helps identify individuals most engaged in reporting suspicious, malicious messages and potential patterns in detection gaps.**" + }, + "customWidth": "100", + "name": "fn user - top-users heading", + "id": "7799a0a0-a835-4080-b59a-736b08ad809e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top 10 users performing false negative submissions\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType in (\"0\",\"1\")\r\n| extend UserId = (parse_json(RawEventData)).UserId\r\n| summarize ['Submissions']=count() by ['User']=tostring(UserId)\r\n| top 10 by ['Submissions'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - top-users pie", + "id": "44838734-43a0-4301-9ddb-a644c7ec509a" + }, + { + "type": 1, + "content": { + "json": "### Top 10 users performing the most User Submissions of Attack simulation messages\r\n**Displays the top 10 user accounts that reported phishing simulation emails during cyber security awareness campaigns. Supports evaluation of cyber security awareness programme effectiveness and identifies highly engaged users.**" + }, + "customWidth": "100", + "name": "fn user - attacksim-users heading", + "id": "8a96e90f-765f-40c0-8476-30c97d43c328" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top users reporting the phishing simulation emails.\r\nCloudAppEvents \r\n| extend Record= (parse_json(RawEventData)).RecordType \r\n| extend SubmissionState = (parse_json(RawEventData)).SubmissionState \r\n| extend UserId = (parse_json(RawEventData)).UserId\r\n| where Record == 29\r\n| where ActionType == \"AttackSimUserSubmission\" \r\n| summarize ['Submissions']=count() by ['User']=tostring(UserId)\r\n| top 10 by ['Submissions'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - attacksim-users pie", + "id": "ab648c4a-4c46-4c73-96f0-784c9bcef961" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "8" + }, + "name": "group - 11 - FN User submissions", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "348ce24a-7cbc-4b66-a471-dfe3827bed2d" + }, + { + "type": 1, + "content": { + "json": "# False Positive(FP) Submissions insights\r\n\r\n---\r\n\r\nThis tab provides insights into email message **False Positive(FP) Submissions** performed by users or administrators in Microsoft Defender for Office 365 where the message was flagged as a threat by Microsoft Defender for Office 365 but was later reported as No Threat by administrators or users." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "10" + }, + "name": "fp - tab description", + "id": "78e2df52-a0d2-499a-95fe-708f67db5ad6" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
False Positive(FP) Admin Submissions\r\n
\r\n\r\nAdministrator submissions represent escalated false positive reports submitted by security team members rather than end users. These typically involve more complex cases requiring expert review, such as recurring issues affecting multiple users, business-critical communications being blocked, or suspected policy misconfigurations. Admin submissions carry higher priority and can result in actions as allow-list additions or global policy changes to prevent widespread user impact.

**Recommended action:** Review recurring false-positive sender domains and consider allow entries or policy tuning to reduce business disruption." + }, + "name": "fp admin - section header", + "id": "02d54e9c-e989-4cde-a128-68a6381ed9d7" + }, + { + "type": 1, + "content": { + "json": "### Admin Submission Volume and Type Breakdown\r\n\r\n**These charts track the volume and composition of administrator-initiated false positive submissions. The trend chart shows submission patterns (per {Granularity}) across Email, URL, and Attachment types, while the pie chart reveals the distribution among these categories. Spikes in admin submissions often signal systemic issues requiring immediate policy review, as admins typically escalate only the most impactful or recurring problems.**" + }, + "name": "fp admin - volume/type heading", + "id": "103b8362-a10f-4b46-a757-8290c4269a5c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of admin false positive submission by submission type.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(CloudAppEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(CloudAppEvents | summarize max(Timestamp));\r\nlet agg = materialize(CloudAppEvents\r\n| where ActionType contains \"Submission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| summarize Admin_Email_FP=countif(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"), Admin_URL_FP=countif(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\"), Admin_Attach_FP=countif(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Email']=coalesce(Admin_Email_FP,0), ['URL']=coalesce(Admin_URL_FP,0), ['Attachment']=coalesce(Admin_Attach_FP,0) | sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "TotalAdminSubmissions", + "color": "redDark" + }, + { + "seriesName": "Admin_Phish_FN", + "color": "redBright" + }, + { + "seriesName": "Admin_Spam_FN", + "color": "orange" + }, + { + "seriesName": "Admin_Malware_FN", + "color": "redDark" + }, + { + "seriesName": "Admin_Phish_URL_FN", + "color": "purple" + }, + { + "seriesName": "Admin_Malware_Attach_FN", + "color": "yellowDark" + }, + { + "seriesName": "Admin_Phish_Attach_FN", + "color": "purpleDark" + }, + { + "seriesName": "Admin_Malware_URL_FN", + "color": "yellow" + }, + { + "seriesName": "Admin_Email_FP", + "color": "redDark" + }, + { + "seriesName": "Admin_URL_FP", + "color": "orangeDark" + }, + { + "seriesName": "Admin_Attach_FP", + "color": "yellow" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "fp admin - submissions trend", + "id": "326762ca-1f2b-48e9-90d6-ff2aa6a75e95" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of admin false positive submission by submission type.\r\nCloudAppEvents \r\n| where ActionType contains \"Submission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| extend Admin_SubmissionType=\r\niff(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Email\",\r\niff(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\",\"URL\",\r\niff(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\",\"Attachment\",\r\n\"Other\")))\r\n| where Admin_SubmissionType!=\"Other\"\r\n| summarize count() by Admin_SubmissionType", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "fp admin - by-type pie", + "id": "be925c4c-5718-4385-8e82-59c57b975ac5" + }, + { + "type": 1, + "content": { + "json": "### False Positive(FP) Admin Submissions by submission state
\r\n\r\n**Displays the total count of False Positive(FP) Admin Submissions by submission State (e.g., Pending, Completed, Failed). Helps track the processing status of admin submissions and identify bottlenecks or errors.**" + }, + "customWidth": "50", + "name": "fp admin - by-state heading", + "id": "2b2acb67-c070-48bd-acf1-025c05aae8b5" + }, + { + "type": 1, + "content": { + "json": "### Top Admins Submitting False Positives
\r\n\r\n**Displays the top 15 admin accounts that submitted the highest number of false positive messages via AdminSubmission.**" + }, + "customWidth": "50", + "name": "fp admin - top-admins heading", + "id": "52206f40-fae9-460f-97b8-2cf9b633098f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of admin false positive submissions by the state of the submission.\r\nCloudAppEvents \r\n| where ActionType contains \"AdminSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType == \"3\"\r\n| summarize count() by tostring(SubmissionState)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp admin - by-state pie", + "id": "96133d9e-24fb-417e-a3cd-df98dda4c60a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top admins performing false positive submissions.\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend Record= (parse_json(RawEventData)).RecordType,SubmissionState = (parse_json(RawEventData)).SubmissionState, UserId = (parse_json(RawEventData)).UserId,SubmissionType = parse_json(RawEventData).SubmissionType \r\n| where Record == 29 and SubmissionType ==\"3\"\r\n| summarize ['Submissions']=count() by ['Admin']=tostring(UserId)\r\n| top 15 by ['Submissions'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp admin - top-admins pie", + "id": "da7b4c89-904d-4917-b6cd-04b32e02d4a1" + }, + { + "type": 1, + "content": { + "json": "### Admin Submission False Positive Malware Detection Breakdown\r\n**Shows the count of administrator-submitted false positive reports (legitimate emails flagged as malware) grouped by the detection method that flagged them. Helps identify which filtering technologies most often misclassify valid messages as malware.**" + }, + "customWidth": "100", + "name": "fp admin - malware-detection heading", + "id": "69d649e0-86fd-4c08-afd4-e6c200b11c86" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Admin false positive submissions whose original verdict was Malware, grouped by the detection method that flagged them. A high count means that method most often misclassifies legitimate mail as Malware.\r\nlet total = toscalar(CloudAppEvents\r\n | where ActionType == \"AdminSubmissionSubmitted\"\r\n | extend R = parse_json(RawEventData)\r\n | where tostring(R.SubmissionContentType) == \"Mail\" and tostring(R.SubmissionType) == \"3\" and tostring(R.DeliveryMessageInfo.FinalFilterVerdict) == \"Malware\"\r\n | count);\r\nCloudAppEvents\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), DetectionMethod = tostring(R.DeliveryMessageInfo.FinalFilterVerdictControlSource), DetectionVerdict = tostring(R.DeliveryMessageInfo.FinalFilterVerdict), P2SenderDomain = tostring(R.P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\" and DetectionVerdict == \"Malware\"\r\n| extend DetectionMethod = iif(isempty(DetectionMethod), \"Not specified\", DetectionMethod)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(P2SenderDomain) by DetectionMethod\r\n| extend Pct = iif(total == 0, 0.0, round(FPSubmissions * 100.0 / total, 1))\r\n| sort by FPSubmissions desc\r\n| project ['Detection Method'] = DetectionMethod, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains, ['% of Malware FPs'] = Pct", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "% of", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp admin - malware-detection table", + "id": "607eb19b-1ded-488d-98db-8b23f9e90967" + }, + { + "type": 1, + "content": { + "json": "### Admin Submission False Positive Phish Detection Breakdown\r\n**Shows the count of administrator-submitted false positive reports (legitimate emails flagged as phishing) grouped by the detection method that flagged them. Helps identify which filtering technologies most often misclassify valid messages as phishing.**" + }, + "customWidth": "100", + "name": "fp admin - phish-detection heading", + "id": "c1f1e12f-d0aa-4023-9172-8182772b3331" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Admin false positive submissions whose original verdict was Phish, grouped by the detection method that flagged them. A high count means that method most often misclassifies legitimate mail as Phish.\r\nlet total = toscalar(CloudAppEvents\r\n | where ActionType == \"AdminSubmissionSubmitted\"\r\n | extend R = parse_json(RawEventData)\r\n | where tostring(R.SubmissionContentType) == \"Mail\" and tostring(R.SubmissionType) == \"3\" and tostring(R.DeliveryMessageInfo.FinalFilterVerdict) == \"Phish\"\r\n | count);\r\nCloudAppEvents\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), DetectionMethod = tostring(R.DeliveryMessageInfo.FinalFilterVerdictControlSource), DetectionVerdict = tostring(R.DeliveryMessageInfo.FinalFilterVerdict), P2SenderDomain = tostring(R.P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\" and DetectionVerdict == \"Phish\"\r\n| extend DetectionMethod = iif(isempty(DetectionMethod), \"Not specified\", DetectionMethod)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(P2SenderDomain) by DetectionMethod\r\n| extend Pct = iif(total == 0, 0.0, round(FPSubmissions * 100.0 / total, 1))\r\n| sort by FPSubmissions desc\r\n| project ['Detection Method'] = DetectionMethod, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains, ['% of Phish FPs'] = Pct", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "% of", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp admin - phish-detection pie", + "id": "b6c074f9-affa-41a3-802a-53541394ae73" + }, + { + "type": 1, + "content": { + "json": "### Admin Submission False Positive Spam Detection Breakdown\r\n**Shows the count of administrator-submitted false positive reports (legitimate emails flagged as spam) grouped by the detection method that flagged them. Helps identify which filtering technologies most often misclassify valid messages as spam.**" + }, + "customWidth": "100", + "name": "fp admin - spam-detection heading", + "id": "f0f2adb9-34af-4df0-90e6-087a265bedf6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Admin false positive submissions whose original verdict was Spam, grouped by the detection method that flagged them. A high count means that method most often misclassifies legitimate mail as Spam.\r\nlet total = toscalar(CloudAppEvents\r\n | where ActionType == \"AdminSubmissionSubmitted\"\r\n | extend R = parse_json(RawEventData)\r\n | where tostring(R.SubmissionContentType) == \"Mail\" and tostring(R.SubmissionType) == \"3\" and tostring(R.DeliveryMessageInfo.FinalFilterVerdict) == \"Spam\"\r\n | count);\r\nCloudAppEvents\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), DetectionMethod = tostring(R.DeliveryMessageInfo.FinalFilterVerdictControlSource), DetectionVerdict = tostring(R.DeliveryMessageInfo.FinalFilterVerdict), P2SenderDomain = tostring(R.P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\" and DetectionVerdict == \"Spam\"\r\n| extend DetectionMethod = iif(isempty(DetectionMethod), \"Not specified\", DetectionMethod)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(P2SenderDomain) by DetectionMethod\r\n| extend Pct = iif(total == 0, 0.0, round(FPSubmissions * 100.0 / total, 1))\r\n| sort by FPSubmissions desc\r\n| project ['Detection Method'] = DetectionMethod, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains, ['% of Spam FPs'] = Pct", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "% of", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp admin - spam-detection pie", + "id": "e877d9c9-3bd3-4368-997e-945f18ffcf5f" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains for Admin False Positive Submissions
\r\n\r\n**Lists the top 10 sender domains of emails reported as false positives by administrators (legitimate messages incorrectly flagged as spam or phishing). Helps identify domains frequently misclassified.**" + }, + "customWidth": "50", + "name": "fp admin - top-sender-domains heading", + "id": "37680101-7e4b-4bcc-9e7e-0ccd2d914881" + }, + { + "type": 1, + "content": { + "json": "### Admin False Positive Submissions by Original Threat Verdict
\r\n\r\n**Displays all administrator-submitted false positive emails by their original filter verdict (e.g., spam, phishing) and policy override details. Helps identify which threat categories are most often misclassified.**" + }, + "customWidth": "50", + "name": "fp admin - by-verdict heading", + "id": "879e81ad-00a6-4a10-bcb6-56879133bb9f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top 10 sender domains of emails which are submitted as false positive by admins\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType),P2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType ==\"3\"\r\n| summarize count() by P2SenderDomain\r\n| top 10 by count_ desc\r\n| project ['Sender Domain']=P2SenderDomain, ['Emails']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp admin - top-sender-domains table", + "id": "42844dc9-4418-487b-a5ad-31e1f6b4b487" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises all emails submitted as false positive by admins summarizing by the original filter verdict threat type\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| extend Admin_SubmissionType=\r\niff(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\" ,\"Email\",\r\n\"Other\"),\r\nP2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain),NetworkMessageId=tostring((parse_json(RawEventData).ObjectId)),DetectionVerdict=tostring((parse_json(RawEventData)).DeliveryMessageInfo.FinalFilterVerdict),PolicyOverride=tostring((parse_json(RawEventData)).DeliveryMessageInfo.PolicyOverride),PolicyPolicyOverrideType=tostring((parse_json(RawEventData)).DeliveryMessageInfo.PolicySource)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| summarize count() by PolicyOverride,DetectionVerdict,Admin_SubmissionType\r\n| top 10 by count_ desc\r\n| project ['Policy Override']=PolicyOverride, ['Detection Verdict']=DetectionVerdict, ['Submission Type']=Admin_SubmissionType, ['Emails']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp admin - by-verdict table", + "id": "3ebbd402-06ef-45a7-b4ee-c5938b98b540" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "10" + }, + "name": "fp admin - group", + "styleSettings": { + "showBorder": true + }, + "id": "b6215b53-c181-4693-a14f-441809f65f38" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
False Positive (FP) User Submissions\r\n
\r\n\r\nThis section provides insights into email message False Postive(FP) Submissions performed by end users in Microsoft Defender for Office 365 where the message was flagged as a threat by Microsoft Defender for Office 365 but was later reported as No Threat by users. User submissions are critical feedback mechanisms that help security teams identify overly aggressive detection rules, refine security policies, and reduce user friction. High false positive rates can erode user trust and lead to security fatigue, so monitoring these metrics helps balance protection with productivity.

**Recommended action:** High user false-positive volume suggests over-aggressive filtering - review the affected senders and adjust policy." + }, + "name": "fp user - section header", + "id": "0d93d7ee-a61e-43b7-bdcd-172bd79ad050" + }, + { + "type": 1, + "content": { + "json": "### User Submission Trend\r\n\r\n**Displays the volume (per {Granularity}) of false positive submissions from end users. A sudden spike may indicate a new detection rule causing widespread misclassification, while a declining trend suggests improving detection accuracy. Monitoring this trend helps security teams respond quickly to detection issues before they impact user productivity.**" + }, + "name": "fp user - trend heading", + "id": "c3f8ae45-0498-4fa8-b9d1-35e926932639" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of user false positive submission by submission type.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(CloudAppEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(CloudAppEvents | summarize max(Timestamp));\r\nlet agg = materialize(CloudAppEvents\r\n| where ActionType contains \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where SubmissionType == \"3\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\"\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['User FP Submissions'] = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "User FP Submissions", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - submissions trend", + "id": "847032f5-56a8-4681-9665-9e917c7c9355" + }, + { + "type": 1, + "content": { + "json": "### User False Positive Submissions by State
\r\n\r\n**Displays the total number of user-reported false positive email submissions grouped by their processing state (e.g., pending, completed). Helps track submission workflow and resolution progress.**" + }, + "customWidth": "50", + "name": "fp user - by-state heading", + "id": "7bd03278-7734-4fbf-a502-95b42e90160e" + }, + { + "type": 1, + "content": { + "json": "### Top Users Performing False Positive Submissions
\r\n\r\n**Lists the top 15 users who reported emails as false positives (legitimate messages incorrectly flagged as threats). Helps identify frequent reporters and potential training or policy adjustment needs.**" + }, + "customWidth": "50", + "name": "fp user - top-users heading", + "id": "7e2b987b-325d-4f69-8d6b-fafd6676a03a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of user false positive submission by submission state.\r\nCloudAppEvents \r\n| where ActionType contains \"UserSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType == \"3\"\r\n| summarize count() by tostring(SubmissionState)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp user - by-state pie", + "id": "df79d08b-3eac-4101-a3f2-3a4a3bf450ce" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top users performing false positive submissions.\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType == \"3\"\r\n| extend UserId = (parse_json(RawEventData)).UserId\r\n| summarize ['Submissions']=count() by ['User']=tostring(UserId)\r\n| top 15 by ['Submissions'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp user - top-users pie", + "id": "ec7505d8-3a70-4bde-a985-baf5a0c4ec34" + }, + { + "type": 1, + "content": { + "json": "### User Submission False Positive Malware Detection Breakdown\r\n**Shows the count of user-submitted false positive reports (legitimate emails flagged as malware) grouped by the detection technique that flagged them. Malware quarantine is admin-only by default, so this table only populates when a custom quarantine policy lets users view and report their own malware detections - it is usually empty.**" + }, + "customWidth": "100", + "name": "fp user - malware-verdict heading", + "id": "693b1072-5ddd-49d0-a0f5-2bba4c287edf" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//User false positive submissions whose email was originally flagged as Malware, by the detection technique that flagged it. A high count means that technique most often misclassifies legitimate mail as Malware.\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has \"Malware\"\r\n| mv-expand Technique = parse_json(DetectionMethods).Malware to typeof(string)\r\n| where isnotempty(Technique)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(SenderFromDomain) by Technique\r\n| sort by FPSubmissions desc\r\n| project ['Detection Technique'] = Technique, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "22ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - malware-verdict table", + "id": "10ea55bd-937e-454d-b6cc-a9dccfdf3417" + }, + { + "type": 1, + "content": { + "json": "### User Submission False Positive Phish Detection Breakdown\r\n**Shows the count of user-submitted false positive reports (legitimate emails flagged as phishing) grouped by the detection technique that flagged them. Helps identify which filtering technologies most often misclassify valid messages as phishing.**" + }, + "customWidth": "100", + "name": "fp user - phish-verdict heading", + "id": "6dd14abb-2772-4271-89d8-8c0dcdbfd9e5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//User false positive submissions whose email was originally flagged as Phish, by the detection technique that flagged it. A high count means that technique most often misclassifies legitimate mail as Phish.\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has \"Phish\"\r\n| mv-expand Technique = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Technique)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(SenderFromDomain) by Technique\r\n| sort by FPSubmissions desc\r\n| project ['Detection Technique'] = Technique, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "22ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - phish-verdict pie", + "id": "57049aad-eb17-4e65-a8a4-b5d05b0501cd" + }, + { + "type": 1, + "content": { + "json": "### User Submission False Positive Spam Detection Breakdown\r\n**Shows the count of user-submitted false positive reports (legitimate emails flagged as spam) grouped by the detection technique that flagged them. Helps identify which filtering technologies most often misclassify valid messages as spam.**" + }, + "customWidth": "100", + "name": "fp user - spam-verdict heading", + "id": "5479b2ed-b629-41e7-9857-c91191b09c8f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//User false positive submissions whose email was originally flagged as Spam, by the detection technique that flagged it. A high count means that technique most often misclassifies legitimate mail as Spam.\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has \"Spam\"\r\n| mv-expand Technique = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Technique)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(SenderFromDomain) by Technique\r\n| sort by FPSubmissions desc\r\n| project ['Detection Technique'] = Technique, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "22ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - spam-verdict pie", + "id": "45a2122e-0281-4602-906d-a0406ed20d54" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains for User False Positive Submissions
\r\n\r\n**Lists the top 10 sender domains of emails reported as false positives by users (legitimate messages incorrectly flagged as threats). Helps identify domains frequently misclassified.**" + }, + "customWidth": "100", + "name": "fp user - top-sender-domains heading", + "id": "2751fca4-3ac5-45fe-a965-8c811018926a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top 10 sender domains reported as false positives by users, with each domain's total inbound volume and the share of it reported as FP (a high rate flags a domain whose legitimate mail is most often misclassified).\r\nlet totalByDomain = EmailEvents | where EmailDirection == \"Inbound\" | summarize TotalInbound = count() by SenderFromDomain;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), P2SenderDomain = tostring(R.P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| summarize FPSubmissions = count() by P2SenderDomain\r\n| join kind=leftouter (totalByDomain) on $left.P2SenderDomain == $right.SenderFromDomain\r\n| extend FPPct = iif(isnull(TotalInbound) or TotalInbound == 0, 0.0, round(FPSubmissions * 100.0 / TotalInbound, 2))\r\n| top 10 by FPSubmissions desc\r\n| project ['Sender Domain'] = P2SenderDomain, ['FP Submissions'] = FPSubmissions, ['Total Inbound'] = coalesce(TotalInbound, 0), ['FP Submission %'] = FPPct", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "18ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "FP Submission %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - top-sender-domains table", + "id": "c69b126d-9f25-44a0-b96d-601d89a563f1" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Senders in User False Positive Submissions
\r\n\r\n**Displays the top 10 email senders whose messages were reported as false positives by users (legitimate emails incorrectly flagged as threats). Helps identify senders frequently misclassified.**" + }, + "customWidth": "100", + "name": "fp user - top-senders heading", + "id": "b39966ad-2b40-4144-ae3f-c7ac6b9fb97c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top 10 email senders reported as false positives by users, with each sender's total inbound volume and the share reported as FP.\r\nlet totalBySender = EmailEvents | where EmailDirection == \"Inbound\" | summarize TotalInbound = count() by SenderMailFromAddress;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\"\r\n| summarize FPSubmissions = count() by SenderMailFromAddress\r\n| join kind=leftouter (totalBySender) on SenderMailFromAddress\r\n| extend FPPct = iif(isnull(TotalInbound) or TotalInbound == 0, 0.0, round(FPSubmissions * 100.0 / TotalInbound, 2))\r\n| top 10 by FPSubmissions desc\r\n| project ['Sender Address'] = SenderMailFromAddress, ['FP Submissions'] = FPSubmissions, ['Total Inbound'] = coalesce(TotalInbound, 0), ['FP Submission %'] = FPPct", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "18ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "FP Submission %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - top-senders table", + "id": "077ab610-58ed-4d23-886c-dbf912cef2d7" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Subjects in User False Positive Submissions
\r\n\r\n**Displays the top 10 email subjects reported as false positives by users (legitimate messages incorrectly flagged as threats). Helps identify common patterns in misclassified emails.**" + }, + "customWidth": "100", + "name": "fp user - top-subjects heading", + "id": "a5b939e1-0fbf-4ee1-a6a3-01fa7639af3a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top 10 email subjects reported as false positives by users, with how many distinct recipients reported each (a subject reported by many users is a broad misclassification pattern).\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\"\r\n| summarize FPSubmissions = count(), DistinctRecipients = dcount(RecipientObjectId) by Subject\r\n| top 10 by FPSubmissions desc\r\n| project ['Subject'] = Subject, ['FP Submissions'] = FPSubmissions, ['Distinct Recipients'] = DistinctRecipients", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Subject", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "70ch" + } + }, + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Recipients", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "18ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - top-subjects table", + "id": "71d5c290-f5d0-493c-b821-b5345dbe7312" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Intra-Org Senders in User False Positive Submissions
\r\n\r\n**Displays the top 10 internal senders whose emails were reported as false positives by users (legitimate intra-org messages incorrectly flagged as threats). Helps identify internal communication patterns causing misclassification.**" + }, + "customWidth": "100", + "name": "fp user - intraorg-senders heading", + "id": "1d38f458-dfde-4608-ad7d-ee8628e85ee7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top 10 internal senders whose emails were reported as false positives by users, with total intra-org volume and the share reported as FP.\r\nlet totalBySender = EmailEvents | where EmailDirection == \"Intra-org\" | summarize TotalIntraOrg = count() by SenderMailFromAddress;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Intra-org\"\r\n| summarize FPSubmissions = count() by SenderMailFromAddress\r\n| join kind=leftouter (totalBySender) on SenderMailFromAddress\r\n| extend FPPct = iif(isnull(TotalIntraOrg) or TotalIntraOrg == 0, 0.0, round(FPSubmissions * 100.0 / TotalIntraOrg, 2))\r\n| top 10 by FPSubmissions desc\r\n| project ['Sender Address'] = SenderMailFromAddress, ['FP Submissions'] = FPSubmissions, ['Total Intra-org'] = coalesce(TotalIntraOrg, 0), ['FP Submission %'] = FPPct", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Intra-org", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "18ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "FP Submission %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - intraorg-senders table", + "id": "b6699a7f-897a-4016-ae2c-d816f3a9492b" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "10" + }, + "name": "fp user - group", + "styleSettings": { + "showBorder": true + }, + "id": "2ad3311e-e92b-4a49-bdd0-775f085c4587" + }, + { + "type": 1, + "content": { + "json": "# File Malware Detections (SharePoint, Teams and OneDrive)\r\n\r\n---\r\n\r\nThis tab provides insights into malicious file detections across Microsoft collaboration platforms such as SharePoint, OneDrive, and Teams.\r\n\r\n[

Safe Attachments for SharePoint, OneDrive, and Microsoft Teams

](https://learn.microsoft.com/en-us/defender-office-365/safe-attachments-for-spo-odfb-teams-about)\r\n[

Built-in virus protection in SharePoint, SharePoint Embedded, OneDrive, and Microsoft Teams

](https://learn.microsoft.com/en-us/defender-office-365/anti-malware-protection-for-spo-odfb-teams-about) " + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "9" + }, + "name": "filemal - tab description", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "cefcac88-f373-4748-b0ea-e7600f63edd7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Microsoft Defender for Office 365 value for files in SharePoint / OneDrive / Teams: total files processed, how many had a malware detection, and how many were scanned with no detection. A per-period Trend series feeds the tile sparkline.\r\nlet gran = {Granularity};\r\nlet base = FileMaliciousContentInfo;\r\nlet counts = union\r\n(base | summarize Count = count() | extend Cat = \"Total Files Processed (SPO/ODB/Teams)\", Ord = 1),\r\n(base | where isnotempty(ThreatTypes) | summarize Count = count() | extend Cat = \"Files with Malware Detected\", Ord = 2),\r\n(base | where isempty(ThreatTypes) | summarize Count = count() | extend Cat = \"Files Scanned - No Detection\", Ord = 3);\r\nlet tagged = union\r\n(base | extend Cat = \"Total Files Processed (SPO/ODB/Teams)\"),\r\n(base | where isnotempty(ThreatTypes) | extend Cat = \"Files with Malware Detected\"),\r\n(base | where isempty(ThreatTypes) | extend Cat = \"Files Scanned - No Detection\");\r\nlet trends = tagged | make-series Trend = count() default = 0 on Timestamp step gran by Cat;\r\ncounts\r\n| join kind=leftouter (trends) on Cat\r\n| sort by Ord asc\r\n| project Count, Details = Cat, Trend", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "filemal - MDO value tiles", + "id": "843e58a9-6324-4a90-a652-bfb0549e79dc", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "9" + } + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
File Malware Detection (SharePoint, OneDrive, and Teams)\r\n
\r\n\r\nThis section monitors malware detections in files stored across Microsoft 365 collaboration platforms. Microsoft Defender for Office 365 and built-in SharePoint Online antivirus work together to scan files uploaded to SharePoint, OneDrive, and Teams. Understanding file-based malware patterns helps protect collaborative workspaces and identify potential security risks in shared content.

**Recommended action:** For repeat file owners or sites, investigate possible compromise and confirm Safe Attachments for SharePoint, OneDrive and Teams is enabled." + }, + "name": "filemal - section header", + "id": "373fe4e5-fc90-49cf-93ba-c8b100efce57" + }, + { + "type": 1, + "content": { + "json": "### File Malware Detection Trend
\r\n\r\n**This visual tracks the volume (per {Granularity}) of malware detections in files across all Microsoft 365 workloads. Spikes in detection activity may indicate targeted attacks or emerging malware campaigns affecting collaborative platforms. Regular monitoring helps identify unusual patterns that require investigation.**" + }, + "name": "filemal - trend heading", + "id": "30145585-8998-443a-b6ec-062d136c621f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total files located on SharePoint, OneDrive and Teams with Malware detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(FileMaliciousContentInfo\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Files']=coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "tileSettings": { + "showBorder": false + }, + "graphSettings": { + "type": 0 + }, + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Files", + "color": "blueDark" + } + ], + "showDataPoints": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "filemal - detection trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d39cea9b-75a8-4c29-bfdb-2e0db855e98a" + }, + { + "type": 1, + "content": { + "json": "### Malware Family Analysis - Defender for Office 365\r\n**Provides a breakdown of malware detections in files scanned by Microsoft Defender for Office 365 (Safe Attachments detonation) across SharePoint, OneDrive, and Teams. The table lists each malware family with total detections, distinct files, affected locations and when it was last seen, helping identify dominant threats and their spread across collaboration platforms.**" + }, + "customWidth": "100", + "name": "filemal - family MDO heading", + "id": "4e330873-f732-4d37-a7b0-dced08b019b0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query summarizes File malware detections by Microsoft Defender for Office 365 (Safe Attachments detonation) into a per-family table: total detections, distinct files, affected locations (file owner or site) and when the family was last seen.\r\nFileMaliciousContentInfo\r\n| where tostring(DetectionMethods) contains \"detonation\"\r\n| extend Owner = iff(isnotempty(FileOwnerUpn), FileOwnerUpn, strcat(\"Site: \", tostring(split(FolderPath, \"/\")[4])))\r\n| summarize ['Files']=count(), ['Distinct Files']=dcount(SHA256), ['Affected Locations']=dcount(Owner), ['Last Seen']=max(Timestamp) by ThreatNames\r\n| sort by ['Files'] desc\r\n| project ['Threat Name']=ThreatNames, ['Files'], ['Distinct Files'], ['Affected Locations'], ['Last Seen']", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "tileSettings": { + "showBorder": false, + "titleContent": { + "columnMatch": "RawinfoVirusInfo", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "count_", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "graphSettings": { + "type": 0, + "topContent": { + "columnMatch": "RawinfoVirusInfo", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "count_", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "chartSettings": { + "xAxis": "RawinfoVirusInfo", + "createOtherGroup": 15 + }, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Files", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "filemal - family MDO table", + "id": "c3fbb1c9-be67-43b9-9a32-7fb265a84ffc" + }, + { + "type": 1, + "content": { + "json": "### Malware Family Analysis - SharePoint AV\r\n**Provides a breakdown of malware detections in files across SharePoint, OneDrive, and Teams caught by the built-in SharePoint antivirus (Antimalware engine). The table lists each malware family with total detections, distinct files, affected locations and when it was last seen, helping identify prevalent threats and their spread across collaboration environments.**" + }, + "customWidth": "100", + "name": "filemal - family SPO-AV heading", + "id": "331a8361-6e81-4615-b33a-97ebb3e31529" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query summarizes File malware detections by the built-in SharePoint antivirus (Antimalware engine) into a per-family table: total detections, distinct files, affected locations (file owner or site) and when the family was last seen.\r\nFileMaliciousContentInfo\r\n| where tostring(DetectionMethods) contains \"Antimalware engine\"\r\n| extend Owner = iff(isnotempty(FileOwnerUpn), FileOwnerUpn, strcat(\"Site: \", tostring(split(FolderPath, \"/\")[4])))\r\n| summarize ['Files']=count(), ['Distinct Files']=dcount(SHA256), ['Affected Locations']=dcount(Owner), ['Last Seen']=max(Timestamp) by ThreatNames\r\n| sort by ['Files'] desc\r\n| project ['Threat Name']=ThreatNames, ['Files'], ['Distinct Files'], ['Affected Locations'], ['Last Seen']", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "chartSettings": { + "xAxis": "RawinfoVirusInfo", + "createOtherGroup": 10 + }, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Files", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "filemal - family SPO-AV table", + "id": "bbcdccd9-eedb-476a-a0e7-8504f8770229" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by Location
\r\n\r\n**Displays the number of malware detections grouped by specific SharePoint sites or OneDrive locations. Helps identify which sites have the highest volume of detected threats for targeted remediation and security hardening.**" + }, + "customWidth": "50", + "name": "filemal - by-location heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "c5668d6e-7c0e-4ce3-9509-ca93dda3efad" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by Application
\r\n\r\n**Summarizes malware detections across Microsoft collaboration apps, including SharePoint, OneDrive, and Teams. Helps identify which applications experience the highest volume of detected threats for targeted security measures.**" + }, + "customWidth": "50", + "name": "filemal - by-application heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "07e64ca9-04a2-44b2-a044-e927bc73ef1b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists total Malware detections of files on SharePoint, OneDrive and Teams by the location (site or personal path) where the file resides.\r\nFileMaliciousContentInfo\r\n| extend ['Site / Location'] = tostring(split(FolderPath, '/')[4])\r\n| summarize ['Detections'] = count() by ['Site / Location']\r\n| sort by ['Detections'] desc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "filemal - by-location table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3ce3ea65-a4df-450f-871c-8956d59818a9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total Malware detections of files located on SharePoint, OneDrive and Teams summarizing the data by the Microsoft collaboration application (workload).\r\nFileMaliciousContentInfo\r\n| summarize count() by Workload\r\n| sort by count_ desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "filemal - by-application pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "003afc8e-0403-4aa9-9084-a3c2e435216a" + }, + { + "type": 1, + "content": { + "json": "### Top File Owners Holding Malware\r\n**Lists the users (or the SharePoint/Teams site, when a file has no individual owner) whose files in SharePoint, OneDrive or Teams were flagged as malware, with the count of malicious files, distinct files, affected workloads and sample threat names. Helps pinpoint the accounts and collaboration locations most affected by malicious content for targeted remediation.**" + }, + "customWidth": "100", + "name": "filemal - top-owners heading", + "id": "c2f8d3b5-0a4e-4b7c-9d23-8e6f0a1b2c34" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top file owners (or the SharePoint/Teams site, when a file has no user owner) whose SharePoint/OneDrive/Teams files were flagged as malware, with distinct files, workloads and sample threat names.\r\nFileMaliciousContentInfo\r\n| extend Owner = iff(isnotempty(FileOwnerUpn), FileOwnerUpn, strcat(\"Site: \", tostring(split(FolderPath, \"/\")[4])))\r\n| summarize ['Malicious Files'] = count(),\n ['Distinct Files'] = dcount(SHA256),\n ['Workloads'] = make_set(Workload, 3),\n ['Sample Threats'] = make_set_if(ThreatNames, isnotempty(ThreatNames), 5),\n ['Last Seen'] = max(Timestamp)\n by ['Owner']=Owner\n| top 20 by ['Malicious Files']", + "size": 0, + "title": "Top File Owners Holding Malware", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Malicious Files", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Distinct Files", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "filemal - top-owners table", + "id": "36d9a683-9f9d-4a70-84d9-ec351542f827" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "9" + }, + "name": "filemal - group", + "styleSettings": { + "showBorder": true + }, + "id": "50886cd9-87bf-4a84-bd80-d7f44441b3f7" + }, + { + "type": 1, + "content": { + "json": "# Post-Delivery & Quarantine Insights\r\n\r\n---\r\nThis tab covers what happens to threats **after delivery**: Zero-hour Auto Purge (ZAP) remediation of malicious messages already in mailboxes, and quarantine management - what is held, released, and by whom. Together they show how effectively post-delivery response contains threats that reached the inbox." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "11" + }, + "name": "postdelivery - tab description", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "93371620-d968-4987-bddd-6c9b9e5a0344" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Post Delivery Protection offered by ZAP\r\n
\r\n\r\nThis section provides insights into Microsoft Defender for Office 365's post-delivery protection capabilities through Zero-Hour Auto Purge (ZAP). ZAP is a critical security feature that continuously monitors delivered emails and automatically removes messages that are later identified as malicious. These visuals help track ZAP effectiveness, response times, and remediation patterns.

**Recommended action:** High post-delivery ZAP volume means threats are reaching inboxes before being caught - review pre-delivery filtering and detection latency." + }, + "name": "postdelivery - section header", + "id": "b22ee5f1-a2dc-4509-92a3-1dbcad3a6ee7" + }, + { + "type": 1, + "content": { + "json": "### ZAP Post-Delivery Actions (per {Granularity})
\r\n\r\n**Shows the count (per {Granularity}) of emails that were remediated post-delivery by Zero-Hour Auto Purge (ZAP). Helps track how often threats are detected and removed after reaching user mailboxes.**" + }, + "customWidth": "50", + "name": "postdelivery - zap-actions heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "af1aa73f-d952-4827-bcc9-b97a19016829" + }, + { + "type": 1, + "content": { + "json": "### ZAP Actions by Detection Type (per {Granularity})
\r\n\r\n**Visualizes the count (per {Granularity}) of post-delivery remediation actions performed by Zero-Hour Auto Purge (ZAP), broken down by detection type (Spam ZAP, Phish ZAP, Malware ZAP). Helps track which threat categories are most frequently remediated after delivery.**" + }, + "customWidth": "50", + "name": "postdelivery - by-detection-type heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8eb38cb1-4e2d-435a-81be-e661c9b89ff4" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of emails that had a post delivery action from zero-hour auto purge.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailPostDeliveryEvents \r\n| where ActionType has \"ZAP\"\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Zapped Emails'] = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Zapped Emails", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "postdelivery - zap-actions trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "dd60fd71-4e14-4b38-ad22-39f1e3e3f55a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of emails that had a post delivery action from zero-hour auto purge, summarizing by phish,spam or malware detection action\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailPostDeliveryEvents\r\n| where ActionType has \"ZAP\"\r\n| summarize [\"Spam ZAP\"]=countif(ActionType has 'Spam ZAP'), [\"Phish ZAP\"]=countif(ActionType has 'Phish ZAP'), [\"Malware ZAP\"]=countif(ActionType has 'Malware ZAP') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, [\"Spam ZAP\"]=coalesce([\"Spam ZAP\"],0), [\"Phish ZAP\"]=coalesce([\"Phish ZAP\"],0), [\"Malware ZAP\"]=coalesce([\"Malware ZAP\"],0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "postdelivery - by-detection-type trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "511f4a43-9f56-48ad-a644-b72722af82d7" + }, + { + "type": 1, + "content": { + "json": "### ZAP Remediation by Destination
\r\n\r\n**This visual shows where ZAP moves malicious emails during remediation. Post-delivery actions can send emails to different locations: Quarantine (isolated for admin review), Deleted Items (soft delete), Junk Email folder, or back to Inbox (for false positive corrections). Understanding these patterns helps evaluate ZAP policy configurations and ensures malicious content is properly isolated from users.**" + }, + "name": "postdelivery - by-destination heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "dc7b9b6c-36fb-4ae4-a3e8-ff11da681c97" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails that had a post delivery action, summarizing the data daily by the final location as a result of the action\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailPostDeliveryEvents\r\n| where ActionType contains \"ZAP\"\r\n| summarize Quarantine=countif(DeliveryLocation has 'Quarantine'), ['Deleted Items']=countif(DeliveryLocation has 'Delete'), Junk=countif(DeliveryLocation has 'Junk'), Inbox=countif(DeliveryLocation has 'Inbox') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, Quarantine=coalesce(Quarantine,0), ['Deleted Items']=coalesce(['Deleted Items'],0), Junk=coalesce(Junk,0), Inbox=coalesce(Inbox,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "name": "postdelivery - by-destination trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "cbb737ef-1c7e-4b3e-af26-a553fe6147c9" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "11" + }, + "name": "postdelivery - group", + "styleSettings": { + "showBorder": true + }, + "id": "e436ecee-8886-4179-a578-9e4a42e75b9e" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Quarantine Management and Insights\r\n
\r\n\r\nThis section provides comprehensive insights into quarantine operations, including release patterns, detection methods, and threat categorization. It helps security teams understand what types of threats are being quarantined and monitor quarantine release activity to identify potential false positives or security policy effectiveness.

**Recommended action:** Investigate high release rates - they indicate false positives or risky user releases; review quarantine policies and release permissions." + }, + "name": "quarantine - section header", + "id": "c4862977-6670-4716-8109-252a361d7478" + }, + { + "type": 1, + "content": { + "json": "### Quarantine Release Trend
\r\n\r\n**This visual displays the per-{Granularity} trend of emails released from quarantine by administrators. Monitoring this metric helps identify patterns in quarantine management and potential areas where policy adjustments may be needed to reduce unnecessary quarantines.**" + }, + "name": "quarantine - release-trend heading", + "id": "8526a5e0-c6a4-44e3-b00a-5e135374f58e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of emails released from quarantine\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailPostDeliveryEvents\r\n| where ActionTrigger has \"AdminAction\" and Action has 'Quarantine release'\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Quarantine Releases'] = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Quarantine Releases", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - release trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3625d1f1-f34a-4cbf-a78f-eb2e5506bad4" + }, + { + "type": 1, + "content": { + "json": "### Quarantine Release Percentage
\r\n\r\n**Calculates the percentage of quarantined emails that were successfully released compared to the total quarantined messages. This metric helps measure engagement with quarantine and assess the effectiveness of quarantine policies.**" + }, + "customWidth": "40", + "name": "quarantine - release-pct heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e3a9502c-9030-4621-b248-55cdf69f81ae" + }, + { + "type": 1, + "content": { + "json": "### Quarantine Release Analysis by Detection Type
\r\n\r\n**For each detection technology, this shows the share of its quarantined emails that were later released from quarantine (Release % = released / quarantined). A high release rate flags a detector that may be over-flagging legitimate mail - a strong candidate for policy or rule tuning. The Released count shows the volume behind each rate.**" + }, + "customWidth": "60", + "name": "quarantine - release-by-detection heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "976fc90f-bf46-4315-b05e-4e501b37b869" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the percentage of emails released from quarantine out of the total ammount of quarantined emails\r\nlet Quarantine_Releases = toscalar(EmailPostDeliveryEvents\r\n| where Action == \"Quarantine release\"\r\n| join kind=leftouter (EmailEvents | where DeliveryLocation == \"Quarantine\") on NetworkMessageId\r\n| summarize count());\r\nlet Quarantined_Mailflow = toscalar(EmailEvents | where DeliveryLocation == \"Quarantine\"\r\n| summarize count());\r\nprint\r\nQuarantine_Releases = toreal(Quarantine_Releases),\r\nQuarantined_Mailflow = toreal(Quarantined_Mailflow),\r\nRelease_Percentage = abs(round(((toreal(Quarantine_Releases)/toreal(Quarantined_Mailflow))*100),2))", + "size": 0, + "showAnalytics": true, + "title": " ", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "tileSettings": { + "titleContent": { + "columnMatch": "Release_Percentage", + "formatter": 12, + "formatOptions": { + "palette": "none" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + "showBorder": true, + "sortCriteriaField": "Release_Percentage", + "size": "auto" + }, + "statSettings": { + "valueField": "Release_Percentage", + "valueAggregation": "None", + "colorSettings": { + "type": "thresholds", + "mode": "foreground", + "heatmapPalette": "greenRed", + "thresholdsGrid": [ + { + "operator": "<", + "thresholdValue": "5", + "representation": "green" + }, + { + "operator": ">", + "thresholdValue": "5", + "representation": "redDark" + } + ] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "numberFormatSettings": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "tagText": "Quarantine Release Percentage", + "valueFontStyle": "mega", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "40", + "name": "quarantine - release-pct stat", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "64e157ce-2f6a-423f-9ce5-eade8b6f41d5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Per detection technology: the share of its quarantined emails that were later released from quarantine.\r\n//Release % = released / quarantined for that detection technology - a high rate flags a detector that may be over-flagging legitimate mail (potential false positives). Detectors with fewer than 10 quarantined emails are excluded so the rate is statistically meaningful.\r\nEmailEvents\r\n| where DeliveryLocation == \"Quarantine\"\r\n| extend MDO_detection = parse_json(DetectionMethods)\r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0]))\r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\")\r\n| where FirstSubcategory contains \"Malware\" or FirstSubcategory contains \"Phish\" or FirstSubcategory contains \"Spam\"\r\n| join kind=leftouter (\r\n EmailPostDeliveryEvents\r\n | where Action == \"Quarantine release\"\r\n | distinct NetworkMessageId\r\n | extend ReleasedFlag = \"yes\"\r\n ) on NetworkMessageId\r\n| summarize Quarantined = dcount(NetworkMessageId), Released = dcountif(NetworkMessageId, ReleasedFlag == \"yes\") by FirstSubcategory\r\n| where Quarantined >= 10 and Released > 0\r\n| extend ReleaseRate = round(Released * 100.0 / Quarantined, 2)\r\n| project ['Detection Type']=FirstSubcategory, ['Quarantined Emails']=Quarantined, ['Released']=Released, ['Release %']=ReleaseRate\r\n| order by ['Release %'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Quarantined Emails", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Released", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Release %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "60", + "name": "quarantine - release-by-detection pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "9a6d21b7-7542-4ae5-8f3f-b18474b52a20" + }, + { + "type": 1, + "content": { + "json": "### Malware Email Quarantine Analysis
\r\n\r\n**These visuals break down quarantined malware emails by their specific detection methods. Microsoft Defender for Office 365 employs multiple malware detection techniques including file detonation, file reputation analysis, and advanced filters. Understanding which detection methods are most frequently triggered helps optimize anti-malware policies and identify emerging malware tactics.
The line chart shows per-{Granularity} trends across all malware detection methods, while the table provides an overall distribution of detection reasons.**" + }, + "name": "quarantine - malware heading", + "id": "59f84161-a010-44c2-aec1-b72ed98ccdff" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of malware emails that are quarantined, summarized daily by the detection method\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has \"Malware\" and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Details = parse_json(DetectionMethods).Malware to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - malware trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a54a8daf-0be2-4c0e-a8d7-4ff0e0879fd2" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of malware emails that are quarantined, summarized by the detection method\r\n//(QA 2026-07-14) mv-expand over DetectionMethods.Malware (matching the sibling line chart) so each slice is a clean single method name instead of a bracketed JSON array.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has 'Malware' and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Malware = parse_json(DetectionMethods).Malware to typeof(string)\r\n| where isnotempty(Malware)\r\n| summarize count() by Malware\r\n| sort by count_ desc\r\n| project ['Detection Technology']=Malware, ['Detections']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - malware table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b5d0d022-cf41-47e5-ae06-cf2176b47758" + }, + { + "type": 1, + "content": { + "json": "### Phishing Email Quarantine Analysis
\r\n\r\n**These visuals break down quarantined phishing emails by their specific detection methods. Microsoft Defender for Office 365 employs multiple phishing detection techniques including impersonation protection, URL detonation, spoof detection, and advanced filters. Understanding which detection methods are most frequently triggered helps optimize anti-phishing policies and identify emerging phishing tactics.
The line chart shows per-{Granularity} trends across all phishing detection methods, while the table provides an overall distribution of detection reasons.**" + }, + "name": "quarantine - phish heading", + "id": "aca50104-cb68-4a8f-82ee-ea8eee25fe14" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of phish emails that are quarantined, summarized daily by the detection method\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has \"Phish\" and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - phish trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "57151360-0577-45ce-8fc6-10a3790865ce" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of phish emails that are quarantined, summarized by the detection method\r\n//(QA 2026-07-14) mv-expand over DetectionMethods.Phish (matching the sibling line chart) so each slice is a clean single method name instead of a bracketed JSON array.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has 'Phish' and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Phish = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Phish)\r\n| summarize count() by Phish\r\n| sort by count_ desc\r\n| project ['Detection Technology']=Phish, ['Detections']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - phish pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "df78c64b-76f6-4980-80df-d0d432e780a5" + }, + { + "type": 1, + "content": { + "json": "### Spam Email Quarantine Analysis
\r\n\r\n**These visuals provide detailed insights into quarantined spam emails categorized by detection methods. Spam detection technologies include advanced filters, general filters, bulk email filtering, reputation-based systems (IP, domain, URL), and mixed analysis detection. Analyzing spam quarantine patterns helps fine-tune spam filtering policies to balance security with user productivity and reduce false positives.
The line chart displays per-{Granularity} trends for each spam detection method, while the table shows the overall distribution.**" + }, + "name": "quarantine - spam heading", + "id": "e131910f-0233-474a-a9b8-9f70a49246cf" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of spam emails that are quarantined, summarized daily by the detection method\r\nlet gran = {Granularity};\r\nlet baseQuery = EmailEvents\r\n| where DetectionMethods has \"Spam\" and DeliveryLocation == \"Quarantine\";\r\nlet agg = materialize(baseQuery\r\n| mv-expand Details = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - spam trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5762bcc7-bbda-4a3d-91cf-de18fbdd2775" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of spam emails that are quarantined, summarized by the detection method\r\n//(QA 2026-07-14) mv-expand over DetectionMethods.Spam (matching the sibling line chart) so each slice is a clean single method name instead of a bracketed JSON array.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has 'Spam' and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Spam = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Spam)\r\n| summarize count() by Spam\r\n| sort by count_ desc\r\n| project ['Detection Technology']=Spam, ['Detections']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - spam pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "2995f55b-17f9-458b-8630-e0370d14522a" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "11" + }, + "name": "quarantine - group", + "id": "430294af-c68f-4427-8b55-d552a3d89d42", + "styleSettings": { + "showBorder": true + } + }, + { + "type": 1, + "content": { + "json": "# Security Operations Center (SOC) Insights \r\n\r\n---\r\n\r\nThis tab provides a view for security operations. Combines incident response metrics with investigation insights to evaluate the effectiveness of both automated systems and manual interventions." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "13" + }, + "name": "soc - tab description", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "fd65243c-514c-4813-978f-fb908226d049" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Security Incident Response Metrics\r\n
\r\n\r\n**Operational efficiency insights.** Tracks incident volume, resolution speed, automation efficacy, and classification accuracy to evaluate SOC performance.

**Recommended action:** Track mean time to close by severity against your SLA and investigate any severity trending upward." + }, + "name": "soc - incident-metrics section header", + "id": "f92c3e24-3e0f-4f4c-8ee9-3ec60832f7b1" + }, + { + "type": 1, + "content": { + "json": "### Email Security Incidents
\r\n\r\n**These visuals display the per-{Granularity} trend of email-related security incidents, as well as the proportion of email incidents compared to the total number of incidents in Defender.**" + }, + "name": "soc - email-incidents heading", + "id": "c1cf6796-6071-4d2e-bf2c-c5e8d2a99a12" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "customWidth": "75", + "name": "soc - email-incidents trend", + "id": "e23cfcda-1017-4fd0-ac71-8a861c450f71" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "customWidth": "25", + "name": "soc - incident-category pie", + "id": "baae2150-1b04-43b4-9713-48fd3cc6247f" + }, + { + "type": 1, + "content": { + "json": "### Average Incident Time To Close (minutes)\r\n**This visual displays the average time, in minutes, to close email-related security incidents (per {Granularity}), split by severity, so you can see how resolution speed changes over time. Reference SLA targets: High 60, Medium 120, Low 240, Informational 480 minutes.**" + }, + "name": "soc - time-to-close heading", + "id": "e23ccc6c-b0f0-407b-8e01-d8b69c40a745" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "name": "soc - sla-by-severity trend", + "id": "3f7d1f17-8d2f-4a1b-a97e-17973812ca6f" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "### Closed Incident Classification (True Positive vs False Positive)\r\n\r\nThis visual shows the distribution of closed email-related incidents classified as True Positive versus False Positive. It helps assess detection accuracy and provides insight into validation trends." + }, + "customWidth": "33.3", + "name": "soc - classification heading", + "styleSettings": { + "margin": "10px" + }, + "id": "48db10ce-8246-4f5e-8b68-f618d9c7f77c" + }, + { + "type": 1, + "content": { + "json": "### True Positive Incident Classification Rate\r\n\r\nThis visual displays the percentage of email-related incidents confirmed as True Positive. It offers a clear measure of classification accuracy and highlights changes in detection effectiveness over time." + }, + "customWidth": "33.3", + "name": "soc - tp-rate heading", + "styleSettings": { + "margin": "10px" + }, + "id": "34a84dbf-609a-407f-afef-f1592eb4a92b" + }, + { + "type": 1, + "content": { + "json": "### Incidents Automated vs Manual Closure\r\n\r\nThis visual illustrates the proportion of email-related incidents closed automatically versus manually. It provides visibility into operational efficiency and the impact of automation on incident resolution.\r\n
⚠️ *You will have to review the underlying query and add any automation system specific to your organization.*" + }, + "customWidth": "33.3", + "name": "soc - auto-vs-manual-closure heading", + "styleSettings": { + "margin": "10px" + }, + "id": "a1fd9136-7a12-4d80-b3e1-e2704a84f734" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "customWidth": "33.3", + "name": "soc - classification pie", + "styleSettings": { + "margin": "10px" + }, + "id": "cfa5b7c5-50cc-4b3b-8bba-1a93c57bff43" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "customWidth": "33.3", + "name": "soc - tp-rate stat", + "styleSettings": { + "margin": "10px" + }, + "id": "eca235aa-38aa-46dd-a569-74dd8f83b2f0" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "customWidth": "33.3", + "name": "soc - closure pie", + "styleSettings": { + "margin": "10px" + }, + "id": "a4bc160f-1ba6-4779-86cd-ef44422f1e29" + } + ] + }, + "name": "soc - incident-insights group", + "id": "3083ac4d-0bdd-4db7-a5f0-0d41cb67a4eb" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "13" + }, + "name": "soc - incident-metrics group", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "18ff8970-e5f6-4c51-918a-aa693a45d18f" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Investigation & Response Actions\r\n
\r\n\r\n**Remediation efficacy analysis.** Compares automated (AIR) and manual admin actions to evaluate response times and investigation outcomes.\r\n

**Recommended action:** Reduce AIR pending-action latency by reviewing why approvals take long, and increase automation where it is safe to do so." + }, + "name": "soc - air section header", + "id": "5e0b06c8-7774-4eb4-8b7f-572b3732de84" + }, + { + "type": 1, + "content": { + "json": "### Automated Investigation and Response (AIR) Actions (per {Granularity})\r\n\r\nThis visual shows the per-{Granularity} trend of Automated Investigation and Response (AIR) actions, including the number of successful and failed attempts (because of prior remediation)." + }, + "customWidth": "100", + "name": "soc - air-actions heading", + "styleSettings": { + "margin": "10px" + }, + "id": "05f14dec-e76c-413c-83a0-31a05dce65e7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query attempts to show AIR Efficiency Over Time by displaying the number of successes and failures over time\r\nEmailPostDeliveryEvents\r\n| where ActionType =~ \"Automated Remediation\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Count = count() by bin(Timestamp, {Granularity}), ActionResult", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "graphSettings": { + "type": 0, + "topContent": { + "columnMatch": "AlertId", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Count", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "soc - air-efficiency trend", + "styleSettings": { + "margin": "10px" + }, + "id": "ae2a1850-5b7e-49f7-bac4-d888053ab49b" + }, + { + "type": 1, + "content": { + "json": "### Automated Investigation and Response (AIR) Response Time After Email Delivery (per {Granularity})\r\n\r\nThis visual displays the average (per {Granularity}), 80th percentile (p80), 90th percentile (p90) and 99th percentile (p99) time needed, measured in minutes, from email delivery to AIR action. It serves as a SOC metric to monitor responsiveness (security team members reviewing and manually approving AIR Pending Actions) and identify potential latency in automated incident handling. If the latency is high focus on reviewing why reviwing AIR Pending Actions takes longer time for admins and consider auto-aproval of URL, Files and Email clusters. \r\n" + }, + "customWidth": "100", + "name": "soc - air-response-time heading", + "styleSettings": { + "margin": "10px" + }, + "id": "98c66d9e-efdf-40fc-b8b0-be35d7fd97a9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// SOC metric: Daily average/p75 delay (in minutes) from email delivery to AIR action\r\nlet deliveries = EmailEvents\r\n | where DeliveryAction == \"Delivered\"// delivered emails\r\n | extend MsgKey = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n | summarize FirstDelivery = min(Timestamp) by MsgKey, Threat = tostring(ThreatTypes);\r\nlet remediations = EmailPostDeliveryEvents\r\n | where ActionType =~ \"Automated Remediation\"// automated remediation events\r\n | extend MsgKey = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n | summarize FirstRemediation = min(Timestamp) by MsgKey;\r\ndeliveries\r\n| join kind=inner remediations on MsgKey\r\n| extend DelayMinutes = datetime_diff(\"minute\", FirstRemediation, FirstDelivery)\r\n| where DelayMinutes >= 0\r\n| summarize ['Avg (min)'] = avg(DelayMinutes),\r\n ['P80 (min)'] = percentile(DelayMinutes, 80),\r\n ['P90 (min)'] = percentile(DelayMinutes, 90),\r\n ['P99 (min)'] = percentile(DelayMinutes, 99),\r\n CountEmails = count()\r\n by bin(FirstRemediation, 1d) ", + "size": 0, + "aggregation": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "gridSettings": { + "sortBy": [ + { + "itemKey": "FirstRemediation", + "sortOrder": 1 + } + ] + }, + "sortBy": [ + { + "itemKey": "FirstRemediation", + "sortOrder": 1 + } + ], + "chartSettings": { + "xAxis": "FirstRemediation", + "yAxis": [ + "P99 (min)", + "P90 (min)", + "P80 (min)", + "Avg (min)" + ], + "showLegend": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "soc - air-latency area", + "styleSettings": { + "margin": "10px" + }, + "id": "900383f1-6443-4d50-b15d-26e4ac11b255" + }, + { + "type": 1, + "content": { + "json": "### Automated Investigation and Response (AIR) Investigation Results Trend\r\n\r\nThis visual displays the per-{Granularity} trend of AIR investigation outcomes, categorized as **Threat Detected** or **Clean**. It helps track the effectiveness of automated investigations over time and highlights patterns in threat detection." + }, + "customWidth": "67", + "name": "soc - air-outcomes heading", + "styleSettings": { + "margin": "10px" + }, + "id": "d1cabfbe-6040-4b6e-9ce5-f48e9973dfc9" + }, + { + "type": 1, + "content": { + "json": "### Investigation Actions Taken: Automated Investigation and Response (AIR) vs Manual (Human)\r\n\r\nThis visual shows whether actions taken after an Automated Investigation and Response (AIR) required manual approval by an administrator or were executed automatically. It provides insight into the level of automation versus human intervention in post-investigation remediation." + }, + "customWidth": "33", + "name": "soc - air-auto-vs-manual heading", + "styleSettings": { + "margin": "10px" + }, + "id": "2f98514b-0172-4c4e-ba25-9a5e4138c570" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// AIR investigation outcomes by day: ThreatDetected vs. Clean\r\n\r\n// Step 1: Deduplicate automated remediation events by message and recipient\r\nlet AutoRemediations = \r\n EmailPostDeliveryEvents\r\n | where ActionType == \"Automated Remediation\"\r\n | summarize arg_max(Timestamp, ActionResult) by NetworkMessageId, RecipientEmailAddress\r\n | project NetworkMessageId, RecipientEmailAddress, Timestamp;\r\n\r\n// Step 2: Derive threat verdicts using AlertEvidence\r\nlet EvidenceVerdicts =\r\n AlertEvidence\r\n | where EntityType in (\"MailMessage\", \"MailCluster\")\r\n | extend extra = todynamic(AdditionalFields)\r\n // If this is a mail cluster, use provided NetworkMessageIds array; otherwise wrap NetworkMessageId as a single-item array\r\n | extend networkIds = iff(\r\n isnull(extra.NetworkMessageIds) or array_length(extra.NetworkMessageIds) == 0,\r\n pack_array(NetworkMessageId), // create a single-element array using pack_array\r\n extra.NetworkMessageIds // use the array as-is if it exists\r\n )\r\n | mv-expand nmID = networkIds // expand to individual message IDs\r\n // Derive verdict from LastVerdict, ThreatAnalysisSummary, and ThreatIntelligence\r\n | extend \r\n lastVerdict = tolower(tostring(extra.LastVerdict)),\r\n threatAIList = extra.ThreatAnalysisSummary,\r\n threatInt = extra.ThreatIntelligence\r\n | extend verdictFromAnalysis = iff(array_length(threatAIList) > 0, tolower(tostring(threatAIList[0].Verdict)), \"\"),\r\n verdictTI = iff(array_length(threatInt) > 0, \"malicious\", \"\") // any item in ThreatIntelligence indicates malicious\r\n // Mark as threat-detected if verdict is malicious/suspicious or threat evidence is present\r\n | extend ThreatDetectedFlag = \r\n case(\r\n lastVerdict in (\"malicious\",\"suspicious\") or verdictFromAnalysis in (\"malicious\",\"suspicious\")\r\n or verdictTI == \"malicious\",\r\n true,\r\n false\r\n )\r\n // Weight mail clusters by MailCount; default to 1 for single messages\r\n | extend MailCountInt = toint(extra.MailCount)\r\n | extend Weight = iff(EntityType == \"MailCluster\", \r\n coalesce(MailCountInt, 1), // default to 1 if MailCount is missing\r\n 1)\r\n | summarize IsThreatDetected = any(ThreatDetectedFlag), \r\n WeightSum = sum(Weight) \r\n by nmID = tostring(nmID);\r\n\r\n// Step 3: Join remediation events with verdicts and aggregate by day\r\nAutoRemediations\r\n| join kind=leftouter EvidenceVerdicts on $left.NetworkMessageId == $right.nmID\r\n| extend isThreat = coalesce(IsThreatDetected, false), \r\n effectiveWeight= coalesce(WeightSum, 1)\r\n| extend InvestigationOutcome = iif(isThreat, \"Threat Detected\", \"Clean\")\r\n| summarize PreventionCount = sum(effectiveWeight) by Day = bin(Timestamp, {Granularity}), InvestigationOutcome\r\n| order by Day asc, InvestigationOutcome asc", + "size": 0, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "67", + "name": "soc - air-outcomes trend", + "styleSettings": { + "margin": "10px" + }, + "id": "18552ccb-d8d4-45c4-a3cf-072203df9325" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows if the action taken after an Automated Investigation required manual approval by and admin or was automatically taken\r\nEmailPostDeliveryEvents\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ActionType == \"Automated Remediation\"\r\n| summarize count() by ActionTrigger", + "size": 3, + "showAnalytics": true, + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "soc - air-auto-vs-manual pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "03bc6e3c-05de-426d-91d8-b48a36b4ea74" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "### Post-Delivery Actions by Admin\r\n\r\nThis visual displays the number (per {Granularity}) of emails where an administrator performed a post-delivery action. Actions are summarized by type, including **Soft Delete**, **Hard Delete**, **Moved to Junk Folder**, **Moved to Inbox**, and **Quarantine Release**, providing insight into manual intervention trends after email delivery." + }, + "name": "soc - post-delivery-by-admin heading", + "styleSettings": { + "margin": "10px" + }, + "id": "a0961ca9-da58-49c4-9a1c-873c5569bed9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of emails that had an admin post delivery action, summarizing the data by action type\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailPostDeliveryEvents\r\n| where ActionTrigger has \"AdminAction\"\r\n| summarize [\"Soft Delete\"]=countif(Action has 'Soft Delete'), [\"Hard Delete\"]=countif(Action has 'Hard Delete'), [\"Moved to junk folder\"]=countif(Action has 'Moved to junk folder'), [\"Moved to inbox\"]=countif(Action has 'Moved to inbox'), [\"Quarantine release\"]=countif(Action has 'Quarantine release') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, [\"Soft Delete\"]=coalesce([\"Soft Delete\"],0), [\"Hard Delete\"]=coalesce([\"Hard Delete\"],0), [\"Moved to junk folder\"]=coalesce([\"Moved to junk folder\"],0), [\"Moved to inbox\"]=coalesce([\"Moved to inbox\"],0), [\"Quarantine release\"]=coalesce([\"Quarantine release\"],0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "name": "soc - post-delivery-by-admin trend", + "styleSettings": { + "margin": "10px" + }, + "id": "d2ea8eac-a3db-46b0-bcb4-3abbb95ba4ad" + } + ] + }, + "customWidth": "100", + "name": "soc - post-delivery group", + "id": "ebca14d5-954d-4e35-a225-cb0f8a3ea81b" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "13" + }, + "name": "soc - air group", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "0a05394d-f813-4408-ac4d-8f481ae34c0b" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Top Malicious Email Campaigns (Clustered)\r\n
\r\n\r\n**Groups malicious inbound emails into campaigns (attack waves) using the Email Cluster ID assigned by Microsoft Defender for Office 365, showing one row per campaign with the message count, distinct recipients, sender domains, threat mix and sample subjects. Helps the SOC understand the scale and shape of coordinated attacks rather than viewing individual messages in isolation.**

**Recommended action:** Pivot on the top campaign clusters to hunt related messages and consider blocking shared sender infrastructure." + }, + "name": "soc - campaigns heading", + "id": "d3a9e4c6-1b5f-4c8d-ae34-9f7a1b2c3d45" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Largest malicious inbound email campaigns clustered by EmailClusterId - one row per attack wave (messages, recipients, URL clicks, sender domains, threat mix, sample subjects).\r\n//URL Clicks = clicks by recipients on URLs within the campaign's messages (UrlClickEvents joined via NetworkMessageId).\r\nlet clicksByCluster = UrlClickEvents\r\n| join kind=inner (EmailEvents | where EmailClusterId > 0 | distinct NetworkMessageId, EmailClusterId) on NetworkMessageId\r\n| summarize UrlClicks = count() by EmailClusterId;\r\nlet qrClusters = EmailUrlInfo\r\n| where UrlLocation == \"QRCode\"\r\n| join kind=inner (EmailEvents | where EmailClusterId > 0 | distinct NetworkMessageId, EmailClusterId) on NetworkMessageId\r\n| summarize QrMessages = dcount(NetworkMessageId) by EmailClusterId;\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and EmailClusterId > 0\r\n| where OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Messages = count(),\r\n Recipients = dcount(RecipientEmailAddress),\r\n SenderDomains = dcount(SenderFromDomain),\r\n SampleSenderDomains = make_set(SenderFromDomain, 5),\r\n ThreatTypesRaw = make_set(ThreatTypes, 50),\r\n SampleSubjects = make_set(Subject, 5),\r\n FirstSeen = min(Timestamp),\r\n LastSeen = max(Timestamp)\r\n by EmailClusterId\r\n| join kind=leftouter (clicksByCluster) on EmailClusterId\r\n| extend UrlClicks = coalesce(UrlClicks, 0)\r\n| join kind=leftouter (qrClusters) on EmailClusterId\r\n| extend ['QR Code'] = iif(coalesce(QrMessages, 0) > 0, \"QR code\", \"\")\r\n| extend ThreatMix = array_sort_asc(set_union(split(strcat_array(ThreatTypesRaw, \", \"), \", \"), dynamic([])))\r\n| top 20 by Messages\r\n| project ['Email Cluster ID']=EmailClusterId, ['Messages']=Messages, ['Recipients']=Recipients, ['URL Clicks']=UrlClicks, ['Sender Domains']=SenderDomains, ['Sample Sender Domains']=SampleSenderDomains, ['Threat Mix']=ThreatMix, ['QR Code']=['QR Code'], ['Sample Subjects']=SampleSubjects, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", + "size": 0, + "title": "", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Recipients", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "URL Clicks", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "soc - campaigns table", + "id": "a2a391e1-0e26-4e0e-a8d3-26e3c7132079" + }, + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Most-Clicked Email Campaigns (Recipient Engagement)\r\n
\r\n\r\n**Ranks malicious inbound campaigns by recipient URL clicks, surfacing the attack waves that reached a mailbox and drew engagement regardless of raw message volume. The highest-volume campaigns are usually quarantined before delivery, so the clusters that draw clicks are often smaller, targeted waves. A non-zero URL Clicks count means a recipient opened a URL within the campaign's messages. Because attackers often mix legitimate URLs with malicious ones to build credibility, and a per-URL threat verdict is not available here, treat these as clicks on potentially malicious URLs that warrant review rather than confirmed malicious clicks.**

**Recommended action:** Focus on these clusters for user follow-up (awareness and, where credentials may be exposed, password reset) and hunt for related messages sharing sender infrastructure." + }, + "name": "soc - mostclicked heading", + "id": "e9e41b47-0434-42e5-8b04-4170ab061b81" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Malicious inbound campaigns ranked by recipient URL clicks - the attack waves that reached a mailbox and drew engagement, regardless of message volume.\r\n//URL Clicks = clicks by recipients on URLs within the campaign's messages (UrlClickEvents joined via NetworkMessageId).\r\nlet clicksByCluster = UrlClickEvents\r\n| join kind=inner (EmailEvents | where EmailClusterId > 0 | distinct NetworkMessageId, EmailClusterId) on NetworkMessageId\r\n| summarize UrlClicks = count() by EmailClusterId;\r\nlet qrClusters = EmailUrlInfo\r\n| where UrlLocation == \"QRCode\"\r\n| join kind=inner (EmailEvents | where EmailClusterId > 0 | distinct NetworkMessageId, EmailClusterId) on NetworkMessageId\r\n| summarize QrMessages = dcount(NetworkMessageId) by EmailClusterId;\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and EmailClusterId > 0\r\n| where OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Messages = count(),\r\n Recipients = dcount(RecipientEmailAddress),\r\n SenderDomains = dcount(SenderFromDomain),\r\n SampleSenderDomains = make_set(SenderFromDomain, 5),\r\n ThreatTypesRaw = make_set(ThreatTypes, 50),\r\n SampleSubjects = make_set(Subject, 5),\r\n FirstSeen = min(Timestamp),\r\n LastSeen = max(Timestamp)\r\n by EmailClusterId\r\n| join kind=inner (clicksByCluster) on EmailClusterId\r\n| where UrlClicks > 0\r\n| join kind=leftouter (qrClusters) on EmailClusterId\r\n| extend ['QR Code'] = iif(coalesce(QrMessages, 0) > 0, \"QR code\", \"\")\r\n| extend ThreatMix = array_sort_asc(set_union(split(strcat_array(ThreatTypesRaw, \", \"), \", \"), dynamic([])))\r\n| top 20 by UrlClicks\r\n| project ['Email Cluster ID']=EmailClusterId, ['URL Clicks']=UrlClicks, ['Messages']=Messages, ['Recipients']=Recipients, ['Sender Domains']=SenderDomains, ['Sample Sender Domains']=SampleSenderDomains, ['Threat Mix']=ThreatMix, ['QR Code']=['QR Code'], ['Sample Subjects']=SampleSubjects, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", + "size": 0, + "title": "", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "URL Clicks", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Recipients", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "soc - mostclicked table", + "id": "1ffe8f97-ad79-47d9-9598-dd73ee54cd8d" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "13" + }, + "name": "soc - campaigns group", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "b8f2a1c4-5d6e-4a7b-9c8d-0e1f2a3b4c5d" + } + ], + "isLocked": false, + "fallbackResourceIds": [], + "$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json" +} diff --git a/Solutions/Microsoft Defender for Office 365/XDR Workbooks/MicrosoftDefenderForOffice365DetectionsAndInsights.json b/Solutions/Microsoft Defender for Office 365/XDR Workbooks/MicrosoftDefenderForOffice365DetectionsAndInsights.json new file mode 100644 index 00000000000..3c8db20130e --- /dev/null +++ b/Solutions/Microsoft Defender for Office 365/XDR Workbooks/MicrosoftDefenderForOffice365DetectionsAndInsights.json @@ -0,0 +1,17407 @@ +{ + "version": "Notebook/1.0", + "items": [ + { + "type": 1, + "content": { + "json": "# Microsoft Defender for Office 365 Detections and Insights\n\nThis workbook provides email and collaboration security insights directly in Microsoft Defender using Advanced Hunting. It is designed for customers using workspace-less Workbooks in the Integrated Security Operations Center (ISOC) and does not require Microsoft Sentinel or a Log Analytics workspace.\n\n[Learn about Integrated Security Operations Center in Microsoft Defender](https://techcommunity.microsoft.com/blog/microsoftthreatprotectionblog/integrated-security-operations-center-in-microsoft-defender/4559097)\n\n- The time selector is bounded by the Defender data available to this tenant.\n- The default range is 7 days and the maximum selectable range is 90 days.\n- Subscription, workspace, cross-workspace, and MSSP selectors are not available in the workspace-less experience.\n- Incident visuals that depend on Microsoft Sentinel tables show an explicit ISOC workspace-required notice." + }, + "name": "text - 2", + "id": "d2b45ab8-a1c1-43d2-853d-290640bf4c94" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "2e238f92-709c-410b-93e0-60eab6150a75", + "version": "KqlParameterItem/1.0", + "name": "TimeRange", + "type": 4, + "isRequired": true, + "isGlobal": true, + "typeSettings": { + "selectableValues": [ + { + "durationMs": 3600000 + }, + { + "durationMs": 14400000 + }, + { + "durationMs": 43200000 + }, + { + "durationMs": 86400000 + }, + { + "durationMs": 172800000 + }, + { + "durationMs": 259200000 + }, + { + "durationMs": 604800000 + }, + { + "durationMs": 1209600000 + }, + { + "durationMs": 2592000000 + }, + { + "durationMs": 5184000000 + }, + { + "durationMs": 7776000000 + } + ], + "allowCustom": true + }, + "timeContext": { + "durationMs": 86400000 + }, + "value": { + "durationMs": 604800000 + }, + "key": "2e238f92-709c-410b-93e0-60eab6150a75" + }, + { + "id": "165f2f4a-e49f-4561-adc5-d0527a4caf32", + "version": "KqlParameterItem/1.0", + "name": "Granularity", + "label": "Trend interval", + "type": 2, + "isRequired": true, + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "jsonData": "[{\"value\":\"1d\",\"label\":\"Daily (1d)\",\"selected\":true},{\"value\":\"7d\",\"label\":\"Weekly (7d)\",\"selected\":false},{\"value\":\"30d\",\"label\":\"Monthly (30d)\",\"selected\":false},{\"value\":\"90d\",\"label\":\"Quarterly (90d)\",\"selected\":false}]", + "timeContext": { + "durationMs": 86400000 + }, + "value": "1d" + } + ], + "style": "pills" + }, + "name": "parameters - 1", + "id": "0021e733-42b4-461f-8f6c-14e6e765389d" + }, + { + "type": 11, + "content": { + "version": "LinkItem/1.0", + "style": "tabs", + "links": [ + { + "id": "3d26d949-bba8-486c-9af7-2b85bd5c8ab0", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Executive Summary", + "subTarget": "1", + "style": "link", + "key": "3d26d949-bba8-486c-9af7-2b85bd5c8ab0" + }, + { + "id": "a5f95467-84c1-4d8b-858c-7819339af748", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Email - Malware", + "subTarget": "2", + "style": "link", + "key": "a5f95467-84c1-4d8b-858c-7819339af748" + }, + { + "id": "b6c93de8-16d9-4c90-999b-837935de5645", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Email - Phish", + "subTarget": "3", + "style": "link", + "key": "b6c93de8-16d9-4c90-999b-837935de5645" + }, + { + "id": "9e006e81-4fd4-40b9-9d20-3705dd6c17ad", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Email - Impersonation & BEC", + "subTarget": "15", + "style": "link", + "key": "75f1e28f-e95a-4810-af40-6b47b35cda46" + }, + { + "id": "df2c53b4-b6ed-4151-95fb-b3f08b849b84", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Email - Spam", + "subTarget": "4", + "style": "link", + "key": "df2c53b4-b6ed-4151-95fb-b3f08b849b84" + }, + { + "id": "fd2006c9-39b5-43ac-b05d-47309ee22deb", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Teams & Collaboration", + "subTarget": "14", + "style": "link", + "key": "fd2006c9-39b5-43ac-b05d-47309ee22deb" + }, + { + "id": "ee01f95a-c5f7-4864-82e8-54a164741ba2", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "File - Malware (SharePoint, Teams and OneDrive)", + "subTarget": "9", + "style": "link", + "key": "ee01f95a-c5f7-4864-82e8-54a164741ba2" + }, + { + "id": "9df30067-3266-48a8-b9e3-d65952098d46", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "URL & Clicks", + "subTarget": "5", + "style": "link", + "key": "9df30067-3266-48a8-b9e3-d65952098d46" + }, + { + "id": "b4be0ac3-3f48-44a8-b4b6-b46e17c710cd", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Top Users & Exfiltration", + "subTarget": "6", + "style": "link", + "key": "b4be0ac3-3f48-44a8-b4b6-b46e17c710cd" + }, + { + "id": "e1d34091-7b3c-4e2d-a032-8be82a989313", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Email - Detection Overrides", + "subTarget": "7", + "style": "link", + "key": "e1d34091-7b3c-4e2d-a032-8be82a989313" + }, + { + "id": "a1e6264d-8f85-4a94-9ffd-eee36c04a0d5", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Post-Delivery & Quarantine", + "subTarget": "11", + "style": "link", + "key": "a1e6264d-8f85-4a94-9ffd-eee36c04a0d5" + }, + { + "id": "08c43a4f-f502-4813-9b8d-3f6b0b62b2fd", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "False Negative(FN) Submissions", + "subTarget": "8", + "style": "link", + "key": "08c43a4f-f502-4813-9b8d-3f6b0b62b2fd" + }, + { + "id": "638d931f-f319-4914-b72d-8d68e914c7d4", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "False Positive(FP) Submissions", + "subTarget": "10", + "style": "link", + "key": "638d931f-f319-4914-b72d-8d68e914c7d4" + }, + { + "id": "b2920bee-c32a-4fdd-9d32-b004db2f3ac8", + "cellValue": "Tab", + "linkTarget": "parameter", + "linkLabel": "Security Operations Center (SOC) Insights", + "subTarget": "13", + "style": "link", + "key": "b2920bee-c32a-4fdd-9d32-b004db2f3ac8" + } + ] + }, + "name": "links - 14", + "id": "5c9a1d6b-c248-432b-a1c0-496337635775" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Defender for Office 365 - Protection Insights\r\n
\r\n\r\n**Microsoft Defender for Office 365** is a comprehensive security solution designed to protect organizations from advanced threats targeting their email and collaboration tools. It leverages a multi-layered approach to safeguard against phishing, malware, business email compromise (BEC), and other sophisticated attacks.\r\n" + }, + "name": "text - 13", + "styleSettings": { + "margin": "0", + "padding": "0" + }, + "id": "46119f93-fad9-413c-8e10-7615c6fdde2f" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows the number behind the effectiveness of phish and malware false positives including post delivery events but without edge data detections.\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\n\r\n// Get all mailflow detected as clean at time of delivery \r\nlet EmailEventsClean = materialize( \r\n EmailEvents \r\n | where Timestamp between (toscalar(minTime) .. toscalar(maxTime)) and EmailDirection == \"Inbound\" \r\n // | where ThreatTypes !contains \"Phish\" and ThreatTypes !contains \"Malware\" // Streaming-SIEM branch disabled for Advanced Hunting current-state semantics.\r\n // this alteration is due to the threat types being updated directly within advanced hunting.\r\n | where DeliveryLocation != \"Quarantine\" // Advanced Hunting current-state branch.\r\n | project NetworkMessageId,ThreatTypes \r\n); \r\n// Get all mailflow detected as phish or malware at time of delivery \r\nlet EmailEventsThreats = materialize( \r\n EmailEvents \r\n | where Timestamp between (toscalar(minTime) .. toscalar(maxTime)) and EmailDirection == \"Inbound\" \r\n | where ThreatTypes contains \"Phish\" or ThreatTypes contains \"Malware\" \r\n | extend MDO_detection = parse_json(DetectionMethods) \r\n | extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n | extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n | project NetworkMessageId,FirstDetection,FirstSubcategory,MDO_detection,ThreatTypes \r\n); \r\n// Get all post delivery ZAP / Redelivery events, and arg_max them to ensure we have the latest verdict to work with for each \r\nlet EmailPostDeliveryFiltered = materialize( \r\n EmailPostDeliveryEvents \r\n | where Timestamp between (toscalar(minTime) .. datetime_add('day', 7, toscalar(maxTime))) \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") or Action has_any (\"Redelivery\",\"Reprocessed\") \r\n | extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n | summarize arg_max(Timestamp, *) by Key \r\n | project Action,ActionType,ActionResult,ThreatTypes,NetworkMessageId \r\n); \r\n// Optional - get all admin submissions for malware or phish, so we can also count these in the miss bucket. \r\nlet CloudAppEventsFiltered = materialize( \r\n CloudAppEvents \r\n | where Timestamp between (toscalar(minTime) .. datetime_add('day', 7, toscalar(maxTime)))\r\n | where ActionType == \"AdminSubmissionSubmitted\" \r\n | extend SubmissionType = tostring(parse_json(RawEventData).SubmissionType) \r\n | extend NetworkMessageId = tostring(parse_json(RawEventData).ObjectId) \r\n | where SubmissionType in (\"1\", \"2\") \r\n | project SubmissionType,NetworkMessageId \r\n); \r\n// get the number of threats caught in mailflow \r\nlet Mal_Phish_Mailflow = toscalar( \r\n EmailEventsThreats \r\n | summarize count() \r\n); \r\n// get the number of threats caught in mailflow which turned out to be false positives (FPs) so we can correct the calculation \r\nlet FP_ZAP = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ThreatTypes !contains \"Phish\" and ThreatTypes !contains \"Malware\" and Action has_any (\"Redelivery\",\"Reprocessed\") \r\n | join kind=leftsemi (EmailEventsThreats) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// get the number of threats successfully cleaned up post delivery, ignoring where administrative policy stopped action \r\nlet FN_ZAP_Successful = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") and ActionResult in (\"Success\",\"AdminPolicy\") \r\n | join kind=leftsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// get the number of threats unsuccessfully cleaned up post delivery. \r\nlet FN_ZAP_Unsuccessful = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") and ActionResult !in (\"Success\",\"AdminPolicy\") \r\n | join kind=leftsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// join the administrative submissions to clean mailflow to find the additional miss \r\nlet FN_Admin_Submissions = toscalar( \r\n CloudAppEventsFiltered \r\n | join kind=rightsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n ); \r\n // print each result, and run the calculation to work out effectiveness at time of delivery and post delivery. \r\n\r\nprint StatisticName=\"Effectiveness Post Delivery\", Value=abs(round(((toreal(toscalar(FN_Admin_Submissions))+toreal(toscalar(FN_ZAP_Unsuccessful)))/(toreal(toscalar(Mal_Phish_Mailflow))+toreal(toscalar(FN_ZAP_Successful))+toreal(toscalar(FN_ZAP_Unsuccessful))+toreal(toscalar(FN_Admin_Submissions))-toreal(toscalar(FP_ZAP)))*100-100),2))", + "size": 1, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "tileSettings": { + "showBorder": false, + "titleContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Value", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "graphSettings": { + "type": 0, + "topContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Value", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "statSettings": { + "valueField": "Value", + "valueAggregation": "None", + "colorSettings": { + "type": "thresholds", + "mode": "foreground", + "heatmapPalette": "greenRed", + "thresholdsGrid": [ + { + "operator": ">", + "thresholdValue": "95", + "representation": "green" + }, + { + "operator": "<=", + "thresholdValue": "95", + "representation": "orange" + }, + { + "operator": "<=", + "thresholdValue": "90", + "representation": "red" + } + ] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "numberFormatSettings": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "tagText": "Phish / Malware Effectiveness - Post Delivery", + "valueFontStyle": "superLarge", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 5", + "id": "62de2a91-a809-48ec-a111-e697d556b2b3" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the percentage of emails released from quarantine out of the total ammount of quarantined emails\r\nlet Quarantine_Releases = toscalar(EmailPostDeliveryEvents\r\n| where Action == \"Quarantine release\"\r\n| join kind=leftouter (EmailEvents | where DeliveryLocation == \"Quarantine\") on NetworkMessageId\r\n| summarize count());\r\nlet Quarantined_Mailflow = toscalar(EmailEvents | where DeliveryLocation == \"Quarantine\"\r\n| summarize count());\r\nprint\r\nQuarantine_Releases = toreal(Quarantine_Releases),\r\nQuarantined_Mailflow = toreal(Quarantined_Mailflow),\r\nRelease_Percentage = abs(round(((toreal(Quarantine_Releases)/toreal(Quarantined_Mailflow))*100),2))", + "size": 1, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "tileSettings": { + "titleContent": { + "columnMatch": "Release_Percentage", + "formatter": 12, + "formatOptions": { + "palette": "none" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + "showBorder": true, + "sortCriteriaField": "Release_Percentage", + "size": "auto" + }, + "graphSettings": { + "type": 0, + "topContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Value", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "statSettings": { + "valueField": "Release_Percentage", + "valueAggregation": "None", + "colorSettings": { + "type": "thresholds", + "mode": "foreground", + "heatmapPalette": "greenRed", + "thresholdsGrid": [ + { + "operator": "<", + "thresholdValue": "5", + "representation": "green" + }, + { + "operator": ">", + "thresholdValue": "5", + "representation": "redDark" + } + ] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "numberFormatSettings": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "tagText": "Quarantine Release Percentage", + "valueFontStyle": "superLarge", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 1", + "id": "858ac1a4-8828-45e9-968c-d3cfc1216c64" + } + ] + }, + "name": "TopNr", + "id": "1369c97e-848b-475a-b447-3a435cb7a1f1" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "**Effectiveness visually represents the protection given by Defender for Office 365 against phishing and malware in email messages.**
\r\nWe consider messages that your users report, as well as decisions that are made after delivery." + }, + "name": "text - 9", + "styleSettings": { + "margin": "1px" + }, + "id": "25e2e19e-aefb-4e37-b28f-b4138d63e109" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows the number behind the effectiveness of phish and malware false positives including post delivery events but without edge data detections.\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\n\r\n// Get all mailflow detected as clean at time of delivery \r\nlet EmailEventsClean = materialize( \r\n EmailEvents \r\n | where Timestamp between (toscalar(minTime) .. toscalar(maxTime)) and EmailDirection == \"Inbound\" \r\n // | where ThreatTypes !contains \"Phish\" and ThreatTypes !contains \"Malware\" // Streaming-SIEM branch disabled for Advanced Hunting current-state semantics.\r\n // this alteration is due to the threat types being updated directly within advanced hunting.\r\n | where DeliveryLocation != \"Quarantine\" // Advanced Hunting current-state branch.\r\n | project NetworkMessageId,ThreatTypes \r\n); \r\n// Get all mailflow detected as phish or malware at time of delivery \r\nlet EmailEventsThreats = materialize( \r\n EmailEvents \r\n | where Timestamp between (toscalar(minTime) .. toscalar(maxTime)) and EmailDirection == \"Inbound\" \r\n | where ThreatTypes contains \"Phish\" or ThreatTypes contains \"Malware\" \r\n | extend MDO_detection = parse_json(DetectionMethods) \r\n | extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n | extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n | project NetworkMessageId,FirstDetection,FirstSubcategory,MDO_detection,ThreatTypes \r\n); \r\n// Get all post delivery ZAP / Redelivery events, and arg_max them to ensure we have the latest verdict to work with for each \r\nlet EmailPostDeliveryFiltered = materialize( \r\n EmailPostDeliveryEvents \r\n | where Timestamp between (toscalar(minTime) .. datetime_add('day', 7, toscalar(maxTime))) \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") or Action has_any (\"Redelivery\",\"Reprocessed\") \r\n | extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n | summarize arg_max(Timestamp, *) by Key \r\n | project Action,ActionType,ActionResult,ThreatTypes,NetworkMessageId \r\n); \r\n// Optional - get all admin submissions for malware or phish, so we can also count these in the miss bucket. \r\nlet CloudAppEventsFiltered = materialize( \r\n CloudAppEvents \r\n | where Timestamp between (toscalar(minTime) .. datetime_add('day', 7, toscalar(maxTime)))\r\n | where ActionType == \"AdminSubmissionSubmitted\" \r\n | extend SubmissionType = tostring(parse_json(RawEventData).SubmissionType) \r\n | extend NetworkMessageId = tostring(parse_json(RawEventData).ObjectId) \r\n | where SubmissionType in (\"1\", \"2\") \r\n | project SubmissionType,NetworkMessageId \r\n); \r\n// get the number of threats caught in mailflow \r\nlet Mal_Phish_Mailflow = toscalar( \r\n EmailEventsThreats \r\n | summarize count() \r\n); \r\n// get the number of threats caught in mailflow which turned out to be false positives (FPs) so we can correct the calculation \r\nlet FP_ZAP = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ThreatTypes !contains \"Phish\" and ThreatTypes !contains \"Malware\" and Action has_any (\"Redelivery\",\"Reprocessed\") \r\n | join kind=leftsemi (EmailEventsThreats) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// get the number of threats successfully cleaned up post delivery, ignoring where administrative policy stopped action \r\nlet FN_ZAP_Successful = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") and ActionResult in (\"Success\",\"AdminPolicy\") \r\n | join kind=leftsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// get the number of threats unsuccessfully cleaned up post delivery. \r\nlet FN_ZAP_Unsuccessful = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") and ActionResult !in (\"Success\",\"AdminPolicy\") \r\n | join kind=leftsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// join the administrative submissions to clean mailflow to find the additional miss \r\nlet FN_Admin_Submissions = toscalar( \r\n CloudAppEventsFiltered \r\n | join kind=rightsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n ); \r\n // print each result, and run the calculation to work out effectiveness at time of delivery and post delivery. \r\nunion withsource=Table \r\n (print StatisticName=\"Mal/Phish Mailflow totals - Minus FPs\", Value=toreal(Mal_Phish_Mailflow) - toreal(FP_ZAP)), \r\n (print StatisticName=\"Admin Mal/Phish FNs Submitted\", Value=toreal(FN_Admin_Submissions)), \r\n (print StatisticName=\"Mal/Phish FPs Reverse Zapped\", Value=toreal(FP_ZAP)), \r\n (print StatisticName=\"Mal / Phish Successfully Zapped\", Value=toreal(FN_ZAP_Successful)), \r\n (print StatisticName=\"Mal / Phish UN-Successfully Zapped\", Value=toreal(FN_ZAP_Unsuccessful)), \r\n (print StatisticName=\"Effectiveness Post Delivery (%)\", Value=abs(round(((toreal(FN_Admin_Submissions)+toreal(FN_ZAP_Unsuccessful))/(toreal(Mal_Phish_Mailflow)+toreal(FN_ZAP_Successful)+toreal(FN_ZAP_Unsuccessful)+toreal(FN_Admin_Submissions)-toreal(FP_ZAP))*100-100),2))), \r\n (print StatisticName=\"Effectiveness Pre-Delivery (%)\", Value=abs(round(((toreal(FN_Admin_Submissions)+toreal(FN_ZAP_Unsuccessful)+toreal(FN_ZAP_Successful))/(toreal(Mal_Phish_Mailflow)+toreal(FN_ZAP_Successful)+toreal(FN_ZAP_Unsuccessful)+toreal(FN_Admin_Submissions)-toreal(FP_ZAP))*100-100),2))) \r\n| project StatisticName, Value", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Value", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "tileSettings": { + "showBorder": false, + "titleContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Value", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "graphSettings": { + "type": 2, + "topContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Value", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + }, + "nodeIdField": "StatisticName", + "sourceIdField": "Value", + "targetIdField": "Value", + "graphOrientation": 3, + "showOrientationToggles": false, + "nodeSize": null, + "staticNodeSize": 100, + "colorSettings": null, + "hivesMargin": 5, + "edgeColorSettings": null + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 7", + "id": "9e09ff94-8092-49c7-860f-341049e1398c" + } + ] + }, + "customWidth": "50", + "name": "Effectiveness Nr", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "31081a73-9a54-4668-9e26-ad7347f1e06e" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "**Quarantine release rate by detection technology.** \r\n
\r\nFor each detector, the share of its quarantined mail that was later released (Release % = released / quarantined). A high rate can indicate false positives worth reviewing." + }, + "name": "text - 1", + "styleSettings": { + "margin": "1px" + }, + "id": "e9848043-03dd-4ada-9e73-238067463f74" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Per detection technology: the share of its quarantined emails later released from quarantine (a high rate can indicate false positives). Top 7 by release rate; detectors with <10 quarantined excluded so the rate is meaningful.\r\nEmailEvents\r\n| where DeliveryLocation == \"Quarantine\"\r\n| extend MDO_detection = parse_json(DetectionMethods)\r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0]))\r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\")\r\n| where FirstSubcategory contains \"Malware\" or FirstSubcategory contains \"Phish\"\r\n| join kind=leftouter (\r\n EmailPostDeliveryEvents\r\n | where Action == \"Quarantine release\"\r\n | distinct NetworkMessageId\r\n | extend ReleasedFlag = \"yes\"\r\n ) on NetworkMessageId\r\n| summarize Quarantined = dcount(NetworkMessageId), Released = dcountif(NetworkMessageId, ReleasedFlag == \"yes\") by FirstSubcategory\r\n| where Quarantined >= 10 and Released > 0\r\n| extend ReleaseRate = round(Released * 100.0 / Quarantined, 2)\r\n| project ['Detection Technology']=FirstSubcategory, ['Quarantined Emails']=Quarantined, ['Released']=Released, ['Release %']=ReleaseRate\r\n| order by ['Release %'] desc\r\n| take 7", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Quarantined Emails", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Released", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Release %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 2", + "id": "1bbae9d1-d6f8-446a-817c-8fdc2df83d4c" + } + ] + }, + "customWidth": "50", + "name": "Quarantine Overview Relese", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "36fd8f20-ece7-4889-9fb1-f5b85b97b45a" + } + ] + }, + "customWidth": "100", + "name": "group - Exec Protection Insights", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "1d8e22e0-22f7-453e-aed2-9e56ace1363a" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Protection details\r\n
\r\n\r\nThis Overview provides an executive summary of your Microsoft Defender for Office 365 email security posture: the volume of mail processed, threats detected and filtered (phishing, malware, spam), overall protection effectiveness, and the mix of threats targeting your organization. Use it as a starting point, then drill into the dedicated tabs for detailed investigation." + }, + "name": "text - 13", + "id": "24cf577c-e12a-4747-95a7-1c19bee17397" + }, + { + "type": 9, + "content": { + "version": "KqlParameterItem/1.0", + "parameters": [ + { + "id": "5c0f0101-0a11-4b22-9c33-000000000101", + "version": "KqlParameterItem/1.0", + "name": "ProtectionView", + "label": "Protection view", + "type": 2, + "isRequired": true, + "typeSettings": { + "additionalResourceOptions": [], + "showDefault": false + }, + "jsonData": "[{ \"value\": \"Table\", \"label\": \"Summary table\", \"selected\": true }, { \"value\": \"Tiles\", \"label\": \"Detailed tiles\" }]", + "value": "Tiles" + } + ], + "style": "pills" + }, + "name": "Protection view selector", + "id": "5c0f0102-0a11-4b22-9c33-000000000102" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let base = materialize(EmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| summarize arg_max(Timestamp, ThreatTypes, DeliveryAction, OrgLevelPolicy, OrgLevelAction, UserLevelAction) by Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress));\r\nlet agg = materialize(base | summarize\r\n Total = count(),\r\n Filtered = countif(isnotempty(ThreatTypes) and DeliveryAction != \"Delivered\" and OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")),\r\n FMal = countif(ThreatTypes has \"Malware\" and OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")),\r\n FPhish = countif(ThreatTypes has \"Phish\" and not(ThreatTypes has \"Malware\") and DeliveryAction != \"Delivered\" and OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")),\r\n FSpam = countif(ThreatTypes == \"Spam\" and DeliveryAction != \"Delivered\" and OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")),\r\n Deliv = countif(isnotempty(ThreatTypes) and DeliveryAction == \"Delivered\" and (isnotempty(OrgLevelAction) or isnotempty(UserLevelAction))),\r\n Blocked = countif(isempty(ThreatTypes) and DeliveryAction != \"Delivered\" and (isnotempty(OrgLevelAction) or isnotempty(UserLevelAction))),\r\n Clean = countif(isempty(ThreatTypes) and DeliveryAction == \"Delivered\"));\r\nlet pd = materialize(EmailPostDeliveryEvents | where ActionResult == \"Success\" | summarize MalZap = countif(ActionType == \"Malware ZAP\"), PhishZap = countif(ActionType == \"Phish ZAP\"), SpamZap = countif(ActionType == \"Spam ZAP\"));\r\nlet sub = materialize(CloudAppEvents | extend R = tostring(parse_json(RawEventData).RecordType), SCT = tostring(parse_json(RawEventData).SubmissionContentType) | where R == \"29\" | summarize Adm = countif(ActionType == \"AdminSubmissionSubmitted\" and SCT == \"Mail\"), Usr = countif(ActionType == \"UserSubmission\"));\r\nlet Total = toscalar(agg | project Total);\r\nlet Filtered = toscalar(agg | project Filtered);\r\nlet FMal = toscalar(agg | project FMal);\r\nlet FPhish = toscalar(agg | project FPhish);\r\nlet FSpam = toscalar(agg | project FSpam);\r\nlet Deliv = toscalar(agg | project Deliv);\r\nlet Blocked = toscalar(agg | project Blocked);\r\nlet Clean = toscalar(agg | project Clean);\r\nlet MalZap = toscalar(pd | project MalZap);\r\nlet PhishZap = toscalar(pd | project PhishZap);\r\nlet SpamZap = toscalar(pd | project SpamZap);\r\nlet Adm = toscalar(sub | project Adm);\r\nlet Usr = toscalar(sub | project Usr);\r\nunion\r\n (print o = 1, Name = \"Total Inbound Emails\", Count = Total),\r\n (print o = 2, Name = \"    Filtering Totals\", Count = Filtered),\r\n (print o = 3, Name = \"        Filtered as Malware\", Count = FMal),\r\n (print o = 4, Name = \"        Filtered as Phish\", Count = FPhish),\r\n (print o = 5, Name = \"        Filtered as Spam\", Count = FSpam),\r\n (print o = 6, Name = \"    Delivered with Detection\", Count = Deliv),\r\n (print o = 7, Name = \"    User/Admin Blocked\", Count = Blocked),\r\n (print o = 8, Name = \"    Clean Emails\", Count = Clean),\r\n (print o = 9, Name = \"Post-Delivery ZAP Removals\", Count = MalZap + PhishZap + SpamZap),\r\n (print o = 10, Name = \"    Removed by Malware ZAP\", Count = MalZap),\r\n (print o = 11, Name = \"    Removed by Phish ZAP\", Count = PhishZap),\r\n (print o = 12, Name = \"    Removed by Spam ZAP\", Count = SpamZap),\r\n (print o = 13, Name = \"User/Admin Reported\", Count = Adm + Usr),\r\n (print o = 14, Name = \"    Reported by Admins\", Count = Adm),\r\n (print o = 15, Name = \"    Reported by Users\", Count = Usr)\r\n| sort by o asc\r\n| extend [\"% of Inbound\"] = round(Count * 100.0 / Total, 1)\r\n| project Name, Count, [\"% of Inbound\"]", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Name", + "formatter": 1, + "formatOptions": { + "customColumnWidthSetting": "3fr" + } + }, + { + "columnMatch": "Count", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "3fr" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "% of Inbound", + "formatter": 3, + "formatOptions": { + "palette": "green", + "min": 0, + "max": 100, + "customColumnWidthSetting": "2fr" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "ProtectionView", + "comparison": "isEqualTo", + "value": "Table" + }, + "name": "query - option 1 grid", + "id": "5c0f0005-0a11-4b22-9c33-000000000005" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "title": "Total Emails", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| summarize Count = count()\r\n| extend Details = \"Total Inbound Emails\";", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Count", + "formatter": 4, + "formatOptions": { + "palette": "greenRed" + } + } + ] + }, + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1, + "formatOptions": { + "compositeBarSettings": { + "labelText": "" + } + } + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "blue", + "compositeBarSettings": { + "labelText": "" + } + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "chartSettings": { + "xAxis": "Count", + "createOtherGroup": 0 + }, + "mapSettings": { + "locInfo": "LatLong", + "sizeSettings": "Count", + "sizeAggregation": "Sum", + "legendMetric": "Count", + "legendAggregation": "Sum", + "itemColorSettings": { + "type": "heatmap", + "colorAggregation": "Sum", + "nodeColorField": "Count", + "heatmapPalette": "greenRed" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 1", + "id": "84e8d60b-7937-46f5-b2f4-a1a4adf06c9f" + } + ] + }, + "name": "Total Inbound", + "id": "1aeed046-9ea5-4583-b966-722847997fc7" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "title": "Filtering Totals", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where isnotempty(ThreatTypes) and EmailDirection == \"Inbound\" and DeliveryAction != 'Delivered'\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| summarize Count = count()\r\n| extend Details = \"Filtering Totals\";", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1, + "formatOptions": { + "compositeBarSettings": { + "labelText": "" + } + } + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "redDark", + "compositeBarSettings": { + "labelText": "" + } + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 1", + "id": "bae9a200-589f-4ca6-a3cf-f1110f644c49" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Total emails detected as Malware\r\nEmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| where ThreatTypes has ('Malware') and EmailDirection == \"Inbound\"\r\n| summarize Count= count()\r\n| extend Details = \"Emails Filtered as Malware\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "red" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 4", + "id": "0984d05b-fd2c-48e1-835f-41afc5a2385a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Total emails detected as Phish\r\nEmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| where ThreatTypes has \"Phish\" and not(ThreatTypes has \"Malware\") and EmailDirection == \"Inbound\" and DeliveryAction != 'Delivered'\r\n| summarize Count= count()\r\n| extend Details = \"Emails Filtered as Phish\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "orange" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 4", + "id": "ced2d054-76d1-40df-a412-0bc86a6c3336" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Total emails by detected as Spam\r\nEmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| where ThreatTypes == 'Spam' and EmailDirection == \"Inbound\" and DeliveryAction != 'Delivered'\r\n| summarize Count= count()\r\n| extend Details = \"Emails Filtered as Spam\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "yellow" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 4", + "id": "14456a0d-f5ac-46a0-a007-c72c7c40c58f" + } + ] + }, + "customWidth": "50", + "name": "group - 9", + "id": "d4e69885-f1b2-4c2b-85c2-188a6708dc4b" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "title": " ", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and DeliveryAction == 'Delivered'\r\n| where isnotempty(OrgLevelAction) or isnotempty(UserLevelAction)\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| summarize Count= count()\r\n| extend Details = \"Delivered with Detection\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "red" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "394d1ed4-7089-4291-bc80-f9948e3be6a9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\" and isempty(ThreatTypes) \r\n| where isnotempty(OrgLevelAction) or isnotempty(UserLevelAction)\r\n| where DeliveryAction != 'Delivered'\r\n| summarize Count= count()\r\n| extend Details = \"User/Admin Blocked\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "gray" + }, + "tooltipFormat": { + "tooltip": "Emails blocked from being delivered because of User or Admin overriddes" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "c29a2268-67d1-4958-a9a3-696384075987" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailEvents\r\n| where isempty(ThreatTypes) and EmailDirection == \"Inbound\" and DeliveryAction == 'Delivered'\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| summarize Count= count()\r\n| extend Details = \"Clean Emails\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "gray" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "89a02ac7-971c-4672-bf5d-64709c479536" + } + ] + }, + "customWidth": "50", + "name": "group - 8", + "id": "761e74d4-279e-465f-ba47-5eeec4cf05d2" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "title": "Post-Delivery ZAP Removals", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailPostDeliveryEvents\r\n| where ActionResult == \"Success\"\r\n| where ActionType == \"Malware ZAP\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Removed by Malware ZAP\"\r\n", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "red" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "b06666bc-6ec0-49e7-a332-77e278d2320f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailPostDeliveryEvents\r\n| where ActionResult == \"Success\"\r\n| where ActionType == \"Phish ZAP\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Removed by Phish ZAP\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "orange" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "6fbac01b-0c42-46dc-8ca8-68e285593a45" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "EmailPostDeliveryEvents\r\n| where ActionResult == \"Success\"\r\n| where ActionType == \"Spam ZAP\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Removed by Spam ZAP\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 1, + "palette": "yellow" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33.3", + "name": "query - 3", + "id": "7bd27a3b-be13-4ca0-9964-0f872f826b45" + } + ] + }, + "name": "Post Delivery", + "id": "4d20339e-5215-4edf-99d6-728cac183d16" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails reported by user and total emails reported by Admins as false positive or false negative detection\r\nCloudAppEvents\r\n| extend Record= (parse_json(RawEventData)).RecordType\r\n| extend SubmissionState = (parse_json(RawEventData)).SubmissionState,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Reported by Admins\"", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "palette": "none" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 3", + "id": "7490fa3a-e287-4fc3-b025-8772b9edb601" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails reported by user and total emails reported by Admins as false positive or false negative detection\r\nCloudAppEvents\r\n| extend Record= (parse_json(RawEventData)).RecordType\r\n| extend SubmissionState = (parse_json(RawEventData)).SubmissionState\r\n| where Record == 29 and ActionType == \"UserSubmission\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Reported by Users\"\r\n", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "palette": "none" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full", + "styleSettings": { + "borderStyle": "rounded", + "backgroundColor": "colorGray100" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 2", + "id": "7af222dc-fd74-40ec-8ab7-741e179c07bf" + } + ] + }, + "name": "Reported", + "id": "8151e242-1c30-4550-ae9c-83f159e1a456" + } + ] + }, + "conditionalVisibility": { + "parameterName": "ProtectionView", + "comparison": "isEqualTo", + "value": "Tiles" + }, + "name": "Protection - Tiles view", + "id": "5c0f0103-0a11-4b22-9c33-000000000103" + }, + { + "type": 1, + "content": { + "json": "## Most Attacked Users
\r\n\r\n**The users most targeted by inbound email threats across all threat types (malware, phishing, and spam) in the selected period. Concentrated targeting of a few individuals is a strong signal of deliberate campaigns.**

**Recommended action:** Prioritise these users for security awareness training, tighter protection policies (for example the Strict preset), and closer monitoring - they are your highest-risk people." + }, + "name": "exec vap banner", + "id": "1fe431fb-cc96-4e81-b164-3a1a3823ebeb" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query surfaces the users most targeted by inbound email threats across all threat types (malware, phishing, spam) for the selected period, so SecOps can prioritise the highest-risk individuals. Similar to a \"Most Attacked People\" view.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| where isnotempty(ThreatTypes)\r\n| summarize\r\n ['Total Threats'] = count(),\r\n Malware = countif(ThreatTypes has \"Malware\"),\r\n Phish = countif(ThreatTypes has \"Phish\"),\r\n Spam = countif(ThreatTypes has \"Spam\"),\r\n ['Last Seen'] = max(Timestamp)\r\n by ['User']=RecipientEmailAddress\r\n| top 10 by ['Total Threats']\r\n| project ['User'], ['Total Threats'], Malware, Phish, Spam, ['Last Seen']", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Malware", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "145px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Phish", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "145px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Spam", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "145px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Total Threats", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "145px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "exec vap table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "2dfd91b1-b8d3-4a72-aaf4-a30a1886bed7" + }, + { + "type": 1, + "content": { + "json": "## Detection trend over time - grouped by {Granularity}\r\n**Represents total emails, total detections, total user submissions and admin email submissions over time summarizing the data per {Granularity} interval**" + }, + "name": "text - 14", + "id": "ddbbdaef-b374-42a8-821c-7fcd7ee53ba9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails, total detections, total user, and admin email submissions over time summarizing the data daily\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet scaffold = range Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran;\r\nlet baseQuery = materialize(EmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where isnotempty(Timestamp));\r\nlet sub = materialize(CloudAppEvents\r\n| extend Record = (parse_json(RawEventData)).RecordType, SubmissionContentType = tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29);\r\nlet zapbase = EmailPostDeliveryEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ActionResult == \"Success\"\r\n| where ActionType == \"Phish ZAP\" or ActionType == \"Malware ZAP\" or ActionType == \"Spam ZAP\";\r\nunion\r\n(scaffold | join kind=leftouter (baseQuery | where EmailDirection == \"Inbound\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Inbound Emails\"),\r\n(scaffold | join kind=leftouter (baseQuery | where ThreatTypes has ('Phish') | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Emails Detected as Phish\"),\r\n(scaffold | join kind=leftouter (baseQuery | where ThreatTypes has ('Malware') | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Emails Detected as Malware\"),\r\n(scaffold | join kind=leftouter (baseQuery | where ThreatTypes has ('Spam') | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Emails Detected as Spam\"),\r\n(scaffold | join kind=leftouter (baseQuery | where EmailDirection == \"Intra-org\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Intra-org Emails\"),\r\n(scaffold | join kind=leftouter (baseQuery | where EmailDirection == \"Outbound\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Outbound Emails\"),\r\n(scaffold | join kind=leftouter (baseQuery | where isnotempty(ThreatTypes) | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Emails with Threat\"),\r\n(scaffold | join kind=leftouter (sub | where ActionType == \"UserSubmission\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Emails Reported by Users\"),\r\n(scaffold | join kind=leftouter (zapbase | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Emails Removed by ZAP\"),\r\n(scaffold | join kind=leftouter (sub | where ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType == \"Mail\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Emails Reported by Admins\")", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp", + "seriesLabelSettings": [ + { + "seriesName": "Total Inbound Emails", + "label": "Inbound Emails", + "color": "green" + }, + { + "seriesName": "Total Emails with Threat", + "label": "Emails with Threat", + "color": "redDark" + }, + { + "seriesName": "Emails Detected as Phish", + "label": "Emails with Phish", + "color": "redBright" + }, + { + "seriesName": "Emails Detected as Malware", + "label": "Emails with Malware", + "color": "red" + }, + { + "seriesName": "Total Intra-org Emails", + "label": "Intra-org Emails", + "color": "greenDark" + }, + { + "seriesName": "Emails Detected as Spam", + "label": "Emails with Spam", + "color": "gray" + }, + { + "seriesName": "Total Outbound Emails", + "label": "Outbound Emails", + "color": "greenDarkDark" + }, + { + "seriesName": "Total Emails Removed by ZAP", + "label": "Emails ZAP-d", + "color": "orangeDark" + }, + { + "seriesName": "Total Emails Reported by Users", + "label": "User Reported Emails", + "color": "lightBlue" + }, + { + "seriesName": "Total Emails Reported by Admins", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 1", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "bcbefa48-f553-4290-acff-2691caf898ea" + }, + { + "type": 1, + "content": { + "json": "## Bad traffic (%) - Inbound Emails - grouped by {Granularity}\r\n**This represents bad traffic (% of emails with threats) compared to total inbound emails, summarized per {Granularity} interval over time.**" + }, + "name": "text - 15", + "id": "30761bcc-b1a5-45e2-8c0a-22388fbbf16c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises bad traffic (% of emails with threats) compared to total inbound emails over time summarising the data daily.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalEmailCount = count(),\r\n BadEmailCount = countif(isnotempty(ThreatTypes)) by bin(Timestamp, {Granularity})\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(BadEmailCount / todouble(TotalEmailCount) * 100, 2))\r\n| project Timestamp, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 0, + "aggregation": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 4", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "508036a8-d969-44c2-b2d2-c62d99999197" + } + ] + }, + "customWidth": "100", + "name": "group - Exec Protection Details", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "e6edeeeb-dcde-41d0-88c7-97ef773403b1" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Collaboration Protection Posture\r\n
\r\n\r\nMicrosoft Defender for Office 365 protects Microsoft Teams and collaboration, not only email. This snapshot shows Teams threat activity for the period.

**Recommended action:** Review the dedicated **Teams & Collaboration** tab for impersonation, malicious URLs, risky senders and file threats in Teams." + }, + "name": "exec collab banner", + "id": "3d78a6aa-51d4-4cab-93d1-26dff86fd667" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Headline Microsoft Teams / collaboration protection metrics for the executive summary, with per-interval sparklines so the collaboration threat trend is visible at a glance. Messages and URLs are counted per distinct Teams message.\r\nlet gran = {Granularity};\r\nlet me = materialize(MessageEvents);\r\nlet cae = materialize(CloudAppEvents | where ActionType == \"TeamsImpersonationDetected\");\r\nlet mui = materialize(MessageUrlInfo);\r\nlet uce = materialize(UrlClickEvents | where Workload == \"Teams\" and ActionType in (\"ClickBlocked\",\"ClickBlockedByTenantPolicy\"));\r\nlet fmc = materialize(FileMaliciousContentInfo | where Workload == \"MicrosoftTeams\");\r\nunion\r\n(me | summarize Count = dcount(TeamsMessageId) | extend Details = \"Teams Messages Scanned\", Ord = 1, Trend = toscalar(me | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(me | where isnotempty(ThreatTypes) | summarize Count = count() | extend Details = \"Teams Threat Messages\", Ord = 2, Trend = toscalar(me | where isnotempty(ThreatTypes) | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(cae | summarize Count = count() | extend Details = \"Teams Impersonation Detections\", Ord = 3, Trend = toscalar(cae | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(mui | summarize Count = dcount(TeamsMessageId) | extend Details = \"URLs Shared in Teams\", Ord = 4, Trend = toscalar(mui | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(uce | summarize Count = count() | extend Details = \"Malicious Clicks Blocked\", Ord = 5, Trend = toscalar(uce | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(fmc | summarize Count = count() | extend Details = \"Teams Files Scanned\", Ord = 6, Trend = toscalar(fmc | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(fmc | where isnotempty(ThreatTypes) | summarize Count = count() | extend Details = \"Malicious Teams Files\", Ord = 7, Trend = toscalar(fmc | where isnotempty(ThreatTypes) | make-series S = count() default = 0 on Timestamp step gran | project S))\r\n| sort by Ord asc\r\n| project Details, Count, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21 + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "exec collab tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3175aee5-56d2-4cb1-b1c3-75be683e6ffb" + } + ] + }, + "customWidth": "100", + "name": "group - Exec Collaboration Posture", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "39b0921f-fcef-49f4-8d52-0dcd1f33045b" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Emerging Threats\r\n
\r\n\r\n

With more sophisticated adversaries and new threats emerging frequently and prevalently, it's critical to be able to quickly identify and react to these threats.

\r\n\r\n[

🛡️Activity Profile: Email threat landscape

](https://security.microsoft.com/threatanalytics3/f186e4b0-28df-499a-901e-c64768b6d0dc/overview?filters=tags%253DPhishing)\r\n[

🛡️Activity Profile: Automated business email impersonation campaign uses parallel aging report and payroll diversion lures

](https://security.microsoft.com/threatanalytics3/3eb53378-892d-4695-a497-25d0a54181ee)\r\n[

🛡️Tool Profile: StealC

](https://security.microsoft.com/threatanalytics3/4d837c12-1db4-49c8-8466-219198d40b9b)\r\n[

🛡️OSINT Profile: UNC1151/Ghostwriter phishing campaign targeting Gmail accounts

](https://security.microsoft.com/threatanalytics3/b1a7e5e7-4b43-4758-8805-f714a131161a)\r\n[

🛡️Activity Profile: Encrypted message campaign targets real estate/financial sectors

](https://security.microsoft.com/threatanalytics3/651d669a-4721-42ab-bb96-509e94b5bfd9)\r\n\r\n
\r\n\r\nView all\r\n \r\n\r\n" + }, + "name": "text - 10", + "styleSettings": { + "margin": "0", + "padding": "0" + }, + "id": "0c781e85-af9a-41a6-9cf7-b3bb9a09d5d0" + } + ] + }, + "customWidth": "100", + "name": "group - Exec Emerging Threats", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "4f8886d3-882a-4c14-ab7f-a37bd302e32f" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Microsoft 365 Secure Email Gateway Performance\r\n
\r\n\r\n

Using multiple vendor email security products can offer diverse detections. However, our comprehensive end-to-end approach—spanning prevention, detection, posture, investigation, response, and user training—delivers a unified and effective defense that matches or exceeds the efficacy of siloed Secure Email Gateway solutions.

\r\n\r\n[

Learn more

](https://www.microsoft.com/en-us/security/blog/2026/06/15/microsoft-defender-email-security-benchmarking-key-insights-from-one-year-of-data/) \r\n\r\n
\r\n

High-severity email threats missed per 1,000 users protected - February–April 2026 (Microsoft Defender email security benchmarking)

" + }, + "name": "text - 12", + "id": "94c804f9-2860-4768-be59-fb31a4ff22d7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "datatable(Index:int, Name:string, Value:int)\r\n[\r\n 1, \"Defender for Office 365\", 194,\r\n 2, \"Mimecast\", 478,\r\n 3, \"ProofPoint\", 483,\r\n 4, \"HornetSecurity\", 813,\r\n 5, \"TrendMicro\", 1151,\r\n 6, \"IronPort\", 1274,\r\n 7, \"Barracuda\", 1585,\r\n 8, \"FireEye\", 2107\r\n]\r\n| project [\"Email security solution\"] = Name, [\"High-severity threats missed / 1K users\"] = Value\r\n| order by [\"High-severity threats missed / 1K users\"] asc\r\n", + "size": 0, + "timeContext": { + "durationMs": 86400000 + }, + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Email security solution", + "formatter": 1, + "formatOptions": { + "customColumnWidthSetting": "40%" + } + }, + { + "columnMatch": "High-severity threats missed / 1K users", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "min": 0, + "max": 2107, + "customColumnWidthSetting": "60%" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "useGrouping": true + } + } + } + ], + "rowLimit": 10, + "sortBy": [ + { + "itemKey": "High-severity threats missed / 1K users", + "sortOrder": 1 + } + ] + } + }, + "name": "query - 11", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e54fd5bd-17e2-40dc-897d-8a3bb21116ff" + } + ] + }, + "customWidth": "100", + "name": "group - Exec SEG Performance", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "1f3a7e2b-0a1f-48ba-9da3-e7531d500938" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "id": "ab3756d3-3f60-4024-9376-0f1a7d47ac13", + "type": 1, + "name": "text - 18", + "content": { + "json": "\r\n\r\n\r\n\r\n
Stay Current\r\n
\r\n\r\n
\r\n\r\n- **Threat Analytics (Defender XDR)** — live, tenant-specific threat intelligence and recommended actions: aka.ms/threatanalytics\r\n- **Microsoft Security Blog** — campaign write-ups and threat research: microsoft.com/security/blog\r\n- **Microsoft Defender for Office 365 Tech Community blog** — product updates and reporting guidance: Tech Community\r\n- **Latest features in Microsoft Defender for Office 365** — What's new in Microsoft Defender for Office 365 \r\n- **Share reporting feedback**: aka.ms/mdoreportingfeedback\r\n" + } + } + ] + }, + "customWidth": "100", + "name": "group - Exec Stay Current", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "5e22c565-cd2e-41f3-8d5a-0735af67c93f" + } + ], + "exportParameters": true + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "1" + }, + "name": "Detection Overview", + "styleSettings": { + "margin": "0", + "padding": "0" + }, + "id": "3f2cc277-9eb3-486d-a1f8-9fa5374a3d80" + }, + { + "type": 1, + "content": { + "json": "# Malware detection insights\r\n\r\n---\r\n\r\nThis tab provides insights into email message **detections** by Microsoft Defender for Office 365 where the message contained a **malware threat** (such as viruses, spyware, or ransomware) within its **URLs** or **attachments**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "text - 13", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "81f28ffc-b69e-4960-a61c-cac17a012ed6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//KPI summary of inbound email malware detections for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet mal = EmailEvents | where EmailDirection == \"Inbound\" | where ThreatTypes has \"Malware\";\r\nlet inbox = mal | where DeliveryLocation has \"Inbox\";\r\nlet malTrend = toscalar(mal | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet inboxTrend = toscalar(inbox | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(mal | summarize count()), Details = \"Malware Emails\", Ord = 1, Trend = malTrend),\r\n(print Count = toscalar(mal | summarize dcount(RecipientEmailAddress)), Details = \"Users Targeted\", Ord = 2, Trend = malTrend),\r\n(print Count = toscalar(mal | summarize dcount(SenderFromDomain)), Details = \"Sender Domains\", Ord = 3, Trend = malTrend),\r\n(print Count = toscalar(inbox | summarize count()), Details = \"Delivered to Inbox\", Ord = 4, Trend = inboxTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "malware kpi strip", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "20c06dd3-5025-4b2b-960e-ff012f5d2343" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Malware Detection Trends, Threat Classes, and Malware Names\r\n
\r\n\r\nThis section consolidates key visuals that track and explain malware detections in inbound email as identified by Microsoft Defender for Office 365 focusing on per-{Granularity} trend, threat classes and Malware types. \r\n

**Recommended action:** If malware volume spikes, confirm Safe Attachments (Block mode) is enabled for all users and investigate the top malware families below." + }, + "name": "text - 14", + "id": "1f09c6ec-b2de-4aa9-bd8e-81d11c92ebd4" + }, + { + "type": 1, + "content": { + "json": "### Malware Detection Trend\r\n**This visual displays a per-{Granularity} trend of email malware detections identified by Microsoft Defender for Office 365. The area chart summarises the number of messages flagged for malware threats.**" + }, + "name": "text - Malware Trend header", + "id": "e90b714f-de84-4571-9a60-b3b2f3bd09dd" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents \r\n| where ThreatTypes has \"Malware\" \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize MalwareDetections = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, MalwareDetections = coalesce(MalwareDetections, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "MalwareDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 0", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "350d0aa3-c093-4105-a150-c20111ac2912" + }, + { + "type": 1, + "content": { + "json": "### Malware Detection Trend - Advanced Threats\r\n**Not all threats are going to be easily recognisable, that's why Microsoft Defender for Office 365 has advanced threat detection methods, that use virtual sandbox environments to detonate URLs and Files. These virtual sandbox technologies look for known patterns, such as a recognisable login page in a URL, or a file accessing command and control infrastructure. This visual displays a per-{Granularity} trend of Malware detections of these advanced threats**" + }, + "name": "text - Malware Advanced Threats header", + "id": "12e07248-ada4-41d9-99cc-824eb65cff79" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections over time summarizing the data daily by Malware detection technologies/controls used for detecting unknown-unique malware.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Malware'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand MalwareMethod = ParsedMethods.Malware\r\n| where MalwareMethod in ('File detonation','URL detonation')\r\n| summarize Count = count() by MalwareMethod = tostring(MalwareMethod), Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct MalwareMethod | extend d = 1) on d | project Timestamp, MalwareMethod\r\n| join kind=leftouter (agg) on Timestamp, MalwareMethod\r\n| project Timestamp, MalwareMethod, Count = coalesce(Count, 0)\r\n| sort by MalwareMethod asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "File detonation", + "color": "redDark" + }, + { + "seriesName": "URL detonation", + "color": "orangeDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 9", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "ebcb6f29-02be-4dd0-b792-cd99285c29d4" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by Threat Classification\r\n**Summary of email messages detected by Microsoft Defender for Office 365 as malware, grouped by type of malware (Adware, Downloader, HackTool, Ransomware, Remote access trojan, Spyware).**" + }, + "customWidth": "33", + "name": "text - 15", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5638fc51-0830-4675-87d4-82f03df17bbf" + }, + { + "type": 1, + "content": { + "json": "### Top Attacked Users by Malware Threat Classification\r\n**Displays the recipient most frequently targeted for each malware type (Adware, Downloader, HackTool, Ransomware, Remote access trojan, Spyware) in inbound email detections.**" + }, + "customWidth": "33", + "name": "text - 15 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d2e3903b-4984-40da-a437-3d6a2b121e23" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by Threat Name\r\n**Summarises email messages flagged by Microsoft Defender for Office 365, grouped by specific malware names detected in URLs or attachments.**" + }, + "customWidth": "33", + "name": "text - 15 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6c0bebcf-9838-4385-ab3a-30db6c994284" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by threat classification of the malware threat in the message.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where ThreatTypes has 'Malware' and ThreatClassification has_any(\"Adware\",\"Downloader\",\"HackTool\",\"Ransomware\",\"Remote access trojan\",\"Spyware\")\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Count = count(Key) by ThreatClassification\r\n| sort by Count desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "query - 11", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "acb98530-8e3a-4383-b42f-8fd74b1c3fbe" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Malware detections in emails summarizing by various Threat classes showing the top attacked user for each threat classification type.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where ThreatTypes has \"Malware\" and EmailDirection == \"Inbound\" and ThreatClassification has_any(\"Adware\",\"Downloader\",\"HackTool\",\"Ransomware\",\"Remote access trojan\",\"Spyware\")\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize EmailCount=count() by ThreatClassification, RecipientEmailAddress\r\n| summarize Count = arg_max(EmailCount, RecipientEmailAddress) by ThreatClassification\r\n| sort by Count desc\r\n| project ['Threat Classification'] = ThreatClassification, ['Top Recipient'] = RecipientEmailAddress, ['Emails'] = Count", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "TopEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "statSettings": { + "valueField": "RecipientEmailAddress", + "valueAggregation": "None", + "colorSettings": { + "type": "static", + "mode": "background", + "heatmapPalette": "greenRed", + "thresholdsGrid": [] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "tagText": "", + "valueFontStyle": "auto" + }, + "chartSettings": { + "xAxis": "RecipientEmailAddress" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 5 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d9b46c97-91ce-4d64-aca6-3126ac49c0ff" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by ThreatNames of the malware detected.\r\nEmailEvents \r\n| where isnotempty(ThreatNames) and ThreatTypes has \"Malware\" \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| mv-expand ThreatName = split(ThreatNames, \",\") to typeof(string)\r\n| where isnotempty(ThreatName)\r\n| distinct Key, ThreatName\r\n| summarize Count = count() by ThreatName\r\n| top 15 by Count\r\n| project ['Threat Name'] = ThreatName, Count", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Count", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "xAxis": "ThreatNames", + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 3", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b9a4b34f-f54f-4d6e-bb20-81925d0f5540" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "group - 3", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "82853a93-e11f-4e4a-80f4-733850a1d3ff" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Malware Detections by Delivery Location, Detection Technology and Sender Infrastructure Insights\r\n
\r\n\r\nThis section consolidates key visuals that track and explain malware detections delivery locations, detection technologies used for detections, sender infrastructure insights in inbound email identified by Microsoft Defender for Office 365 as Malware. \r\n

**Recommended action:** For sender IPs or countries you do not do business with, consider connection filtering or geo-based rules; verify the detection technologies catching these are enabled." + }, + "name": "banner - Malware Delivery Detection Sender", + "id": "cba6403d-e2b1-4fe8-af52-57e5c2aa8e54" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by delivery location\r\n**Visualizes counts (per {Granularity}) of malware detections of inbound emails by delivery location: Quarantine or Failed (rejected with or without NDR)**" + }, + "name": "text - Malware Delivery Location header", + "id": "95be7f48-40eb-4154-91d8-20f7033f2ff5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections over time summarizing the data daily by Delivery Location\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Malware' and EmailDirection == 'Inbound'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalMalwareDetections=count(), Quarantine=countif(DeliveryLocation == 'Quarantine'), Failed=countif(DeliveryLocation == 'Failed') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, TotalMalwareDetections=coalesce(TotalMalwareDetections,0), Quarantine=coalesce(Quarantine,0), Failed=coalesce(Failed,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "TotalMalwareDetections", + "color": "blue" + }, + { + "seriesName": "Quarantine", + "color": "orangeDark" + }, + { + "seriesName": "Failed", + "color": "redDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 10", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b2c19e58-2123-490b-9631-c0b238c582e6" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by Detection Technology\r\n**Visualizes counts (per {Granularity}) of Malware detections of inbound emails by various Microsoft Defender for Office 365 detection technologies.**" + }, + "name": "text - Malware Detection Technology header", + "id": "f3c2691e-4f32-4109-9524-8a11719e4425" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections over time summarizing the data daily by various Malware detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Malware'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand MalwareMethod = ParsedMethods.Malware\r\n| summarize Count = count() by MalwareMethod = tostring(MalwareMethod), Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct MalwareMethod | extend d = 1) on d | project Timestamp, MalwareMethod\r\n| join kind=leftouter (agg) on Timestamp, MalwareMethod\r\n| project Timestamp, MalwareMethod, Count = coalesce(Count, 0)\r\n| sort by MalwareMethod asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 8", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f00c1ce0-e55e-44c0-8bf0-4af662ccef89" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by various Malware detection technologies/controls in Microsoft Defender for Office 365.\r\nEmailEvents \r\n| where DetectionMethods has 'Malware'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand MalwareMethod = ParsedMethods.Malware\r\n| summarize Count = count() by MalwareMethod = tostring(MalwareMethod)\r\n| sort by Count desc\r\n| project ['Detection Technology'] = MalwareMethod, ['Detections'] = Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "34", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 2", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "590880a9-1cf7-44ae-b4de-2f65bc700b5d" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by SenderIPv4 Geo Location\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Malware, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" + }, + "name": "text - Malware Geo Location header", + "id": "19d78b48-af58-4bee-abfe-57efb1eba125" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by email sender IP address (SenderIPv4).\r\nEmailEvents \r\n| where ThreatTypes has 'Malware' and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_", + "size": 0, + "showAnalytics": true, + "title": "Malware Detections-Sender Heatmap (IPv4)", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "map", + "gridSettings": { + "sortBy": [ + { + "itemKey": "count_", + "sortOrder": 2 + } + ] + }, + "sortBy": [ + { + "itemKey": "count_", + "sortOrder": 2 + } + ], + "mapSettings": { + "locInfo": "LatLong", + "locInfoColumn": "GeoInfo", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "none" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 1", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8cb46ec0-ac2a-41d1-bf8a-0b8585d1fefc" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where ThreatTypes has 'Malware' and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Malware Emails'] = count_\r\n| sort by ['Malware Emails'] desc\r\n\r\n\r\n", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Malware Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "mapSettings": { + "locInfo": "LatLong", + "locInfoColumn": "GeoInfo", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "heatmap", + "heatmapPalette": "red" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - 1 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b6a0355a-2b8f-48a5-8edc-58f4f7f8180a" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "Malware-Detectiontech-Deliverylocation-SendingInfra", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "2692cb5e-825c-45c1-bd3a-096b55e8d760" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Malware Detections Top attacked users and top senders\r\n
\r\n\r\nThis section consolidates key visuals that track and explain malware detections in inbound email as identified by Microsoft Defender for Office 365 focusing on top attacked users and top senders. \r\n

**Recommended action:** Apply the Strict preset security policy to the most-attacked users and consider adding persistent malicious sender domains to the Tenant Allow/Block List." + }, + "name": "banner - Malware Top Users Senders", + "id": "bc5b37a4-71e4-4a2f-b0ba-b3dd87333391" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections top attacked users\r\n**Displays the top 10 recipient email addresses that received inbound emails flagged as Malware. These users may be at higher risk and should be prioritised for targeted cybersecurity awareness training. Training should cover the specific threat types and techniques they are exposed to, and reinforce best practices for promptly reporting any suspicious messages that might bypass security controls and reach their inbox.**" + }, + "customWidth": "100", + "name": "text - Malware Top Users header", + "id": "cb87a026-ad03-45cc-887e-ab460490d9a5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails with Malware detections summarizing the data by the top 15 recipient email address (RecipientEmailAddress).\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),MalwareEmailCount = countif(ThreatTypes has \"Malware\") by RecipientEmailAddress\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(MalwareEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| where MalwareEmailCount !=0\r\n| top 15 by MalwareEmailCount\r\n| project ['Recipient'] = RecipientEmailAddress, ['Malware Emails'] = MalwareEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Malware Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - Malware Top Recipients", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e7ffef62-f85e-4188-8ab9-d90a5c666c30" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains with Malware Detections (Inbound)\r\n**Displays the top 10 sender domains sending inbound emails detected as Malware. Helps identify external sources most frequently associated with malicious content for prioritised threat monitoring and mitigation.**" + }, + "customWidth": "100", + "name": "text - Malware Top Senders header", + "id": "93390807-25b2-4bea-9648-98e821da8ec6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections summarizing the data by the top 15 email sender P2 domain (SenderFromDomain). Adding additional insights for total inbound emails and bad traffic percentage for each sender domain.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount = count(), MalwareEmailCount = countif(ThreatTypes has \"Malware\") by SenderFromDomain\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(MalwareEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| where MalwareEmailCount !=0\r\n| top 15 by MalwareEmailCount\r\n| project ['Sender Domain'] = SenderFromDomain, ['Malware Emails'] = MalwareEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Malware Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal", + "useGrouping": false + } + } + }, + { + "columnMatch": "BadEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "query - Malware Top Sender Domains", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "eaa45734-2df2-4a5e-b35b-1295e00cb46f" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "2" + }, + "name": "MalwareTopAttackedUser-TopSenders", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "4e0900ab-e7e4-4cf1-93a4-7e86bca20782" + }, + { + "type": 1, + "content": { + "json": "# Phishing Detection Insights\r\n\r\n---\r\nThis tab provides insights into email message **detections** by Microsoft Defender for Office 365 where the message contained a **Phishing threat** within its **email content**, **URLs**, or **attachments**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "text - 24", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "fe82d665-fa9e-4fc2-9ba9-7e2eabb9a04b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//KPI summary of inbound email phishing detections for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet ph = EmailEvents | where EmailDirection == \"Inbound\" | where ThreatTypes has \"Phish\";\r\nlet inbox = ph | where DeliveryLocation has \"Inbox\";\r\nlet phTrend = toscalar(ph | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet inboxTrend = toscalar(inbox | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(ph | summarize count()), Details = \"Phish Emails\", Ord = 1, Trend = phTrend),\r\n(print Count = toscalar(ph | summarize dcount(RecipientEmailAddress)), Details = \"Users Targeted\", Ord = 2, Trend = phTrend),\r\n(print Count = toscalar(ph | summarize dcount(SenderFromDomain)), Details = \"Sender Domains\", Ord = 3, Trend = phTrend),\r\n(print Count = toscalar(inbox | summarize count()), Details = \"Delivered to Inbox\", Ord = 4, Trend = inboxTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "phish kpi strip", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5debf0b8-4384-485b-8a7f-71ead592718a" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Phishing Detection Trend, LLM Content Analysis, Advanced Threats, and Threat Classes\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Phish detections in inbound email as identified by Microsoft Defender for Office 365 focusing on per-{Granularity} trends, advanced threat detections, LLM-based content analysis, and threat classes.

**Recommended action:** Review the LLM-classified phishing themes; enable Safe Links and impersonation protection, and prioritise awareness training on the dominant lure types." + }, + "name": "text - Phish Section1 Banner", + "id": "ce5e489f-c83b-4bc8-9e63-b08dfb5ef31f" + }, + { + "type": 1, + "content": { + "json": "### Phish Detection Trend
\r\n\r\n**This visual displays a per-{Granularity} trend of email Phish detections identified by Microsoft Defender for Office 365. The area chart summarises the number of messages flagged for Phish threats.**" + }, + "name": "text - Phish Trend Header", + "id": "429ef4d2-61a9-40d0-940f-2212ddce22ce" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections over time summarizing the data daily.\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has \"Phish\"\r\n| summarize PhishDetections = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, PhishDetections = coalesce(PhishDetections, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "PhishDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b0d170ec-331c-4ad0-8ce6-258704cc5345" + }, + { + "type": 1, + "content": { + "json": "### Phish Detection Trend - Advanced Threats
\r\n\r\n**Not all threats are easily recognizable, which is why Microsoft Defender for Office 365 uses advanced detection methods, including virtual sandbox environments to detonate URLs and files. These virtual sandbox technologies look for known patterns, such as a recognisable login page in a URL, or a file accessing command and control infrastructure. This visual displays a per-{Granularity} trend of Phish detections of these advanced threats.**" + }, + "name": "text - Phish AdvThreats Header", + "id": "425476e0-066a-42ee-afb9-5dabc612a3c8" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections over time summarizing the data daily by Phish detection technologies/controls used for detecting unknown-unique phish.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| project Timestamp, RecipientEmailAddress, NetworkMessageId, DT=parse_json(DetectionMethods)\r\n| evaluate bag_unpack(DT)\r\n| summarize [\"File detonation\"]=countif(Phish has 'File detonation' and Phish !has 'File detonation reputation'), [\"URL detonation\"]=countif(Phish has 'URL detonation' and Phish !has 'URL detonation reputation') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, [\"File detonation\"]=coalesce([\"File detonation\"],0), [\"URL detonation\"]=coalesce([\"URL detonation\"],0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "URL detonation", + "color": "orangeDark" + }, + { + "seriesName": "File detonation", + "color": "redDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish AdvThreats Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6b62347a-b162-49e6-891c-07697af22dd9" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - LLM content analysis
\r\n\r\n**Microsoft Defender for Office 365 uses Language AI for Phish and Business Email Compromise (BEC) detection. These models are progressively learning from thousands of real-world phishing attempts and analyzing all messages classified as phish. Furthermore, it incorporates advanced Machine Learning and Natural Language Processing (NLP) techniques to read, process, and understand email content the way a human analyst might, yet in a fraction of the time and at a large scale. [Learn more](https://techcommunity.microsoft.com/blog/microsoftdefenderforoffice365blog/microsoft-defender-for-office-365s-language-ai-for-phish-enhancing-email-securit/4410446)**" + }, + "customWidth": "50", + "name": "text - Phish LLM Content Header", + "id": "c23460b1-e025-4f6c-b2d5-3f78c0c9afc6" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - LLM Threat Classifications
\r\n\r\n**Microsoft Defender for Office 365 uses purpose-built Large Language Models (LLM) at scale to provide AI-powered email and collaboration security. Our solution now parses language to understand and identify attacker intent and classifies threats at machine speed – keeping malicious emails out of your inbox and giving security operations (SOC) teams a new level of insight into adversary techniques. [Learn more](https://techcommunity.microsoft.com/blog/microsoftdefenderforoffice365blog/microsoft-ignite-redefining-email-security-with-llms-to-tackle-a-new-era-of-soci/4302421)**" + }, + "customWidth": "50", + "name": "text - Phish LLM ThreatClass Header", + "id": "1d723c26-501f-4385-9331-957ab7ae5019" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails detected as Phish by LLM content analysis detection technology in Microsoft Defender for Office 365. \r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has 'Phish' and DetectionMethods contains \"LLM content analysis\"\r\n| summarize count()\r\n| sort by count_ desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "statSettings": { + "valueAggregation": "None", + "colorSettings": { + "type": "thresholds", + "mode": "foreground", + "thresholdsGrid": [ + { + "operator": ">", + "thresholdValue": "0", + "representation": "red" + }, + { + "operator": "<=", + "thresholdValue": "0", + "representation": "red" + } + ] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "tagText": "", + "valueFontStyle": "auto", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish LLM Content Count", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "86a301c5-2bc0-436a-982c-861beee7c9ab" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by intent of the message.\r\n// Microsoft Defender for Office 365 LLM analysis is analyzing email messages to understand the intent of the messages. These threat classifications are then used in filtering decisions.\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has 'Phish' and ThreatClassification has_any(\"Business intelligence\",\"Contact establishment\",\"Gift card\",\"Invoice\",\"Payroll\",\"PII gathering\",\"Task\")\r\n| summarize count() by ThreatClassification\r\n| sort by count_ desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish LLM ThreatClass Pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d547b730-f174-4f78-8998-02f24453304e" + }, + { + "type": 1, + "content": { + "json": "### Top Attacked Users by LLM Threat classes (Phish)
\r\n\r\n**Displays recipients most frequently targeted by inbound phishing emails, grouped by threat classification (e.g., Gift Card, Invoice, Payroll). Helps identify users at higher risk for phishing attacks. These users may be at higher risk and should be prioritised for targeted cybersecurity awareness training. Training should cover the specific threat types and techniques they are exposed to, and reinforce best practices for promptly reporting any suspicious messages that might bypass security controls and reach their inbox.**" + }, + "customWidth": "100", + "name": "text - Phish LLM TopUsers Header", + "id": "4ba9d9eb-d88d-4e5d-ba58-a740559677f7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Phish detections in emails summarizing by various Threat classes showing the top attacked user for each threat classification type.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has \"Phish\" and EmailDirection == \"Inbound\" and ThreatClassification has_any(\"Business intelligence\",\"Contact establishment\",\"Gift card\",\"Invoice\",\"Payroll\",\"PII gathering\",\"Task\")\r\n| summarize EmailCount=count() by ThreatClassification, RecipientEmailAddress\r\n| summarize Emails = arg_max(EmailCount, RecipientEmailAddress) by ThreatClassification\r\n| sort by Emails desc\r\n| project ['Threat Classification'] = ThreatClassification, ['Top Recipient'] = RecipientEmailAddress, ['Emails'] = Emails", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "80px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish LLM TopUsers", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "51599ab2-db69-4195-b4e9-2828729ec35b" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "group - 5", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "25c47f6a-3525-435e-90cf-357f02fb2fed" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Phish Detections by Delivery location, Detection technology and Sender infrastructure insights\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Phish detections delivery locations, detection technologies used for detections, sender infrastructure insights in inbound email identified by Microsoft Defender for Office 365 as Phish.

**Recommended action:** Verify anti-phishing and Safe Links policies cover these delivery paths; consider blocking sender infrastructure from regions you do not operate in, where appropriate." + }, + "name": "text - Phish Section2 Banner", + "id": "6876063e-6a4f-48ea-829d-4486922783dd" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections by delivery location
\r\n\r\n**Visualizes counts (per {Granularity}) of Phish detections of inbound emails by various delivery locations: Quarantine, Junk folder or Failed (rejected with or without NDR)**" + }, + "name": "text - Phish DeliveryLoc Header", + "id": "b5045aab-1b4b-4d35-af41-a6315d36e864" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections over time summarizing the data daily by Delivery Location.\r\n//The comment in the query excludes deliveries to the SecOps Mailboxes and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\" and EmailDirection == \"Inbound\"\r\n| summarize TotalPhishDetections=count(), Quarantine=countif(DeliveryLocation == \"Quarantine\"), Junkfolder=countif(DeliveryLocation == \"Junk folder\"), Inbox=countif(DeliveryLocation == \"Inbox/folder\"), Failed=countif(DeliveryLocation == \"Failed\"), Dropped=countif(DeliveryLocation == \"Dropped\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, TotalPhishDetections=coalesce(TotalPhishDetections,0), Quarantine=coalesce(Quarantine,0), Junkfolder=coalesce(Junkfolder,0), Inbox=coalesce(Inbox,0), Failed=coalesce(Failed,0), Dropped=coalesce(Dropped,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Quarantine", + "color": "greenDark" + }, + { + "seriesName": "Failed", + "color": "green" + }, + { + "seriesName": "Dropped", + "color": "green" + }, + { + "seriesName": "Junk folder", + "color": "orangeDark" + }, + { + "seriesName": "Inbox", + "color": "redBright" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish DeliveryLoc Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e839848c-d176-4251-bbb4-1c2e1103ed2d" + }, + { + "type": 1, + "content": { + "json": "### Phish detections by Detection Technology
\r\n\r\n**Visualizes counts (per {Granularity}) of Phish detections of inbound emails by various Microsoft Defender for Office 365 detection technologies.**" + }, + "name": "text - Phish DetTech Header", + "id": "149bf1b3-80cc-4e82-ae5d-ddee0f6b0cd9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections over time summarizing the data daily by various Phish Detection technologies/controls in Microsoft Defender for Office 365.\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "createOtherGroup": 15 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish DetTech Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b0b16329-e1a6-4138-871e-76d57a60b978" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarized by individual Phish detection technology/control in Microsoft Defender for Office 365.\r\n//Each detection technology is counted individually via mv-expand over DetectionMethods.Phish (matching the sibling trend line chart), so a message flagged by multiple techniques counts once per technique.\r\n//The where clause excludes deliveries to the SecOps Mailbox and by the Phish Simulation system.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details\r\n| sort by Count desc\r\n| project ['Detection Technology'] = Details, ['Detections'] = Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish DetTech Pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5270ba04-599f-4940-805b-687f7475bc70" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections by SenderIPv4 Geo Location
\r\n\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Phish, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" + }, + "name": "text - Phish Geo Header", + "id": "ddd0c12f-1bb1-4d7d-afb4-f28bcfcd7c4b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by email sender IP address (SenderIPv4).\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has \"Phish\" and isnotempty(SenderIPv4)\r\n| summarize count() by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "map", + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "none" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish Geo Map", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "85ea7223-7d77-43f5-b0d9-e0de7c898758" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where ThreatTypes has 'Phish' and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Phish Emails'] = count_\r\n| sort by ['Phish Emails'] desc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Phish Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "heatmap", + "heatmapPalette": "red" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish Country Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f561209b-15a6-442e-af10-63e375088209" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "group - 25- Phish delivery locations-detecion tech-sender infra", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "10f3e3eb-b330-4955-952e-01eff69405e9" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Phish Detections Top attacked users and top senders\r\n
\r\n\r\nThis section consolidates key visuals that track and explain phish detections in inbound email as identified by Microsoft Defender for Office 365 focusing on top attacked users and top senders.

**Recommended action:** Enroll the most-targeted users in security awareness training and consider blocking persistent phishing sender domains." + }, + "name": "text - Phish Section3 Banner", + "id": "f46ed4a8-e2b5-4ccd-ae38-efc571bfc791" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections top attacked users\r\n**Displays the top 10 recipient email addresses that received inbound emails flagged as Phish. These users may be at higher risk and should be prioritised for targeted cybersecurity awareness training. Training should cover the specific threat types and techniques they are exposed to, and reinforce best practices for promptly reporting any suspicious messages that might bypass security controls and reach their inbox.**" + }, + "customWidth": "100", + "name": "text - Phish TopUsers Header", + "id": "96d9b543-070a-42d4-bbed-3f5cf79ca7ce" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails with Phish detections summarizing the data by the top 15 recipient email address (RecipientEmailAddress).\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),PhishEmailCount = countif(ThreatTypes has \"Phish\") by RecipientEmailAddress\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(PhishEmailCount / todouble(TotalEmailCount) * 100, 2))\r\n| where PhishEmailCount !=0\r\n| top 15 by PhishEmailCount\r\n| project ['Recipient'] = RecipientEmailAddress, ['Phish Emails'] = PhishEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Phish Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish TopRecipients Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "25100115-78d3-4144-b44e-613b44f02484" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains with Phish Detections (Inbound)\r\n**Displays the top 10 sender domains sending inbound emails detected as Phish. Helps identify external sources most frequently associated with malicious content for prioritised threat monitoring and mitigation.**" + }, + "customWidth": "100", + "name": "text - Phish TopSenders Header", + "id": "e7fcb7fe-4bca-4153-a9b0-8ded135b1c64" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by the top 15 email sender P2 domain (SenderFromDomain), now including the Phish confidence split (High/Normal) and the aggregated phish detection methods seen per domain. Adding additional insights for total inbound emails and bad traffic percentage for each sender domain.\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where EmailDirection == \"Inbound\"\r\n| extend PhishConf = tostring(parse_json(ConfidenceLevel).Phish)\r\n| extend PhishMethods = parse_json(DetectionMethods).Phish\r\n| summarize TotalEmailCount = count(),\r\n PhishEmailCount = countif(ThreatTypes has \"Phish\"),\r\n Phish_High = countif(ThreatTypes has \"Phish\" and PhishConf == \"High\"),\r\n Phish_Normal = countif(ThreatTypes has \"Phish\" and PhishConf == \"Normal\"),\r\n PhishMethodSet = make_set_if(PhishMethods, ThreatTypes has \"Phish\") by SenderFromDomain\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(PhishEmailCount / todouble(TotalEmailCount) * 100, 2))\r\n| where PhishEmailCount != 0\r\n| top 15 by PhishEmailCount\r\n| mv-apply S = PhishMethodSet on ( mv-expand m = S to typeof(string) | summarize Methods = make_set(m) )\r\n| project ['Sender Domain'] = SenderFromDomain, ['Phish Emails'] = PhishEmailCount, ['Phish (High)'] = Phish_High, ['Phish (Normal)'] = Phish_Normal, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound, ['Detection Methods'] = strcat_array(Methods, \", \")", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Phish Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish (High)", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish (Normal)", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "BadEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "query - Phish TopSenders Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "717bfce8-b5d4-4900-99db-4ba0c503591d" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "3" + }, + "name": "group - 26-PhishDetectionsTopattackedusers-topsenders", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "553afca2-caa1-45b1-bec0-dca426b5be46" + }, + { + "type": 1, + "content": { + "json": "# Spam Detection Insights\r\n\r\n---\r\nThis tab provides insights into email message **detections** by Microsoft Defender for Office 365 where the message contained a **Spam threat** within its **email content**, **URLs**, or **attachments**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "4" + }, + "name": "text - Spam Tab Intro", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a693a05a-a772-4ac4-9863-07ad0d1b7092" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//KPI summary of inbound email spam detections for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet sp = EmailEvents | where EmailDirection == \"Inbound\" | where ThreatTypes has \"Spam\";\r\nlet junk = sp | where DeliveryLocation has \"Junk\";\r\nlet spTrend = toscalar(sp | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet junkTrend = toscalar(junk | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(sp | summarize count()), Details = \"Spam Emails\", Ord = 1, Trend = spTrend),\r\n(print Count = toscalar(sp | summarize dcount(RecipientEmailAddress)), Details = \"Users Targeted\", Ord = 2, Trend = spTrend),\r\n(print Count = toscalar(sp | summarize dcount(SenderFromDomain)), Details = \"Sender Domains\", Ord = 3, Trend = spTrend),\r\n(print Count = toscalar(junk | summarize count()), Details = \"Sent to Junk\", Ord = 4, Trend = junkTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "4" + }, + "name": "spam kpi strip", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "cadd5331-1db8-4ac8-bc99-42cd5227ee51" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Spam Detection Effectiveness and Trends\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Spam detections in inbound email as identified by Microsoft Defender for Office 365 focusing on Effectiveness and per-{Granularity} trend. For effectiveness, we consider messages reported by your admins and decisions made post-delivery.

**Recommended action:** If legitimate mail is marked as spam, review the Spam and Bulk thresholds; if spam is leaking through, tighten them." + }, + "name": "text - Spam Section1 Banner", + "id": "1093f3b6-cea7-4f54-9029-f9aadd79ca9f" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query calculates the effectiveness of spam detections without edge data.\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\n// baseQuery _FN_Admin_Submissions_SPM\r\nlet _FN_Admin_Submissions_SPM = toscalar(\r\nCloudAppEvents\r\n| where Timestamp between (minTime .. maxTime)\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType)\r\n| extend NetworkMessageId = tostring((parse_json(RawEventData)).ObjectId)\r\n| where SubmissionType in (\"0\")\r\n| summarize count()\r\n);\r\n// baseQuery _FN_ZAP_Successful_Spam\r\nlet _FN_ZAP_Successful_Spam = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and ActionType == \"Spam ZAP\" and ActionResult == \"Success\" and Timestamp between (minTime .. maxTime)\r\n| summarize count()\r\n //Take all our Spam ZAP, and count how many messages we missed and successfully cleaned up.\r\n);\r\n// baseQuery _FN_ZAP_Unsuccessful_Spam\r\nlet _FN_ZAP_Unsuccessful_Spam = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and ActionType == \"Spam ZAP\" and ActionResult != \"Success\" and Timestamp between (minTime .. maxTime)\r\n| summarize count()\r\n//Take all our Spam ZAP, and count how many messages we failed to clean up due to error or users/admins/API vendors getting to the message first.\r\n);\r\n// baseQuery _SPAM_ZAP_FP\r\nlet _SPAM_ZAP_FP = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and Action has_any (\"Redelivery\",\"Reprocessed\") and Timestamp between (minTime .. maxTime)\r\n| join kind=leftsemi (\r\n EmailEvents\r\n | where Timestamp between (minTime ..maxTime )\r\n | where ThreatTypes contains \"Spam\"\r\n | project NetworkMessageId, ThreatTypes)\r\n on NetworkMessageId\r\n| summarize count()\r\n// count all the FPs which were originally Spam, and when we TT'd them were not so we can subtract that from our mailfow catch, and therefore the total true bad.\r\n);\r\n// baseQuery _Spam_Mailflow\r\nlet _Spam_Mailflow = toscalar(\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and ThreatTypes == \"Spam\" and Timestamp between (minTime .. maxTime)\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count()\r\n// Get all the mailflow detected as SPM, then count all the NMIDs (not distinct)\r\n);\r\nprint\r\nEffectiveness_PostDelivery = abs(round(((toreal(toscalar(_FN_Admin_Submissions_SPM))+toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)))/(toreal(toscalar(_Spam_Mailflow))+toreal(toscalar(_FN_ZAP_Successful_Spam))+toreal(toscalar(_FN_ZAP_Unsuccessful_Spam))+toreal(toscalar(_FN_Admin_Submissions_SPM))-toreal(toscalar(_SPAM_ZAP_FP)))*100-100),2))", + "size": 1, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "statSettings": { + "valueAggregation": "None", + "colorSettings": { + "type": "thresholds", + "mode": "foreground", + "heatmapPalette": "greenRed", + "thresholdsGrid": [ + { + "operator": ">", + "thresholdValue": "95", + "representation": "green" + }, + { + "operator": "<=", + "thresholdValue": "95", + "representation": "orange" + }, + { + "operator": "<=", + "thresholdValue": "90", + "representation": "red" + } + ] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "numberFormatSettings": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "tagText": "Spam Effectiveness (without Edge data)", + "valueFontStyle": "superLarge", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Effectiveness Stat", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "036851c1-489e-4fda-8059-850c161578b3" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\n// baseQuery _FN_Admin_Submissions_SPM\r\nlet _FN_Admin_Submissions_SPM = toscalar(\r\nCloudAppEvents\r\n| where Timestamp between (minTime .. maxTime)\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType)\r\n| extend NetworkMessageId = tostring((parse_json(RawEventData)).ObjectId)\r\n| where SubmissionType in (\"0\")\r\n| summarize count()\r\n);\r\n// baseQuery _FN_ZAP_Successful_Spam\r\nlet _FN_ZAP_Successful_Spam = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and ActionType == \"Spam ZAP\" and ActionResult == \"Success\" and Timestamp between (minTime .. maxTime)\r\n| summarize count()\r\n //Take all our Spam ZAP, and count how many messages we missed and successfully cleaned up.\r\n);\r\n// baseQuery _FN_ZAP_Unsuccessful_Spam\r\nlet _FN_ZAP_Unsuccessful_Spam = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and ActionType == \"Spam ZAP\" and ActionResult != \"Success\" and Timestamp between (minTime .. maxTime)\r\n| summarize count()\r\n//Take all our Spam ZAP, and count how many messages we failed to clean up due to error or users/admins/API vendors getting to the message first.\r\n);\r\n// baseQuery _SPAM_ZAP_FP\r\nlet _SPAM_ZAP_FP = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and Action has_any (\"Redelivery\",\"Reprocessed\") and Timestamp between (minTime .. maxTime)\r\n| join kind=leftsemi (\r\n EmailEvents\r\n | where Timestamp between (minTime ..maxTime )\r\n | where ThreatTypes contains \"Spam\"\r\n | project NetworkMessageId, ThreatTypes)\r\n on NetworkMessageId\r\n| summarize count()\r\n// count all the FPs which were originally Spam, and when we TT'd them were not so we can subtract that from our mailfow catch, and therefore the total true bad.\r\n);\r\n// baseQuery _Spam_Mailflow\r\nlet _Spam_Mailflow = toscalar(\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and ThreatTypes == \"Spam\" and Timestamp between (minTime .. maxTime)\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count()\r\n// Get all the mailflow detected as SPM, then count all the NMIDs (not distinct)\r\n);\r\nprint StatisticName=\"Spam Mailflow Minus FPs\", Value=toreal((toscalar(_Spam_Mailflow)) - toreal(toscalar(_SPAM_ZAP_FP)))\r\n| union (print StatisticName=\"Spam Admin FNs Submitted\", Value=toreal(toscalar(_FN_Admin_Submissions_SPM)))\r\n| union (print StatisticName=\"Spam FPs Reverse Zapped\", Value=toreal(toscalar(_SPAM_ZAP_FP)))\r\n| union (print StatisticName=\"Spam Zapped Successfully\", Value=toreal(toscalar(_FN_ZAP_Successful_Spam)))\r\n| union (print StatisticName=\"Spam NotZapped\", Value=toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)))\r\n| union (print StatisticName=\"Spam Effectiveness Post Delivery %\", Value=abs(round(((toreal(toscalar(_FN_Admin_Submissions_SPM)) + toreal(toscalar(_FN_ZAP_Unsuccessful_Spam))) / (toreal(toscalar(_Spam_Mailflow)) + toreal(toscalar(_FN_ZAP_Successful_Spam)) + toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)) + toreal(toscalar(_FN_Admin_Submissions_SPM)) - toreal(toscalar(_SPAM_ZAP_FP)))) * 100 - 100, 2)))\r\n| union (print StatisticName=\"Spam Effectiveness Pre-Delivery %\", Value=abs(round(((toreal(toscalar(_FN_Admin_Submissions_SPM)) + toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)) + (toscalar(_FN_ZAP_Successful_Spam))) / (toreal(toscalar(_Spam_Mailflow)) + toreal(toscalar(_FN_ZAP_Successful_Spam)) + toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)) + toreal(toscalar(_FN_Admin_Submissions_SPM)) - toreal(toscalar(_SPAM_ZAP_FP)))) * 100 - 100, 2 )))\r\n| project ['Statistic'] = StatisticName, Value", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "tileSettings": { + "showBorder": false, + "titleContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Value", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Value", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 2 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Effectiveness Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8d456ea2-f04a-4d71-95c6-fbaad8c2d2f2" + } + ] + }, + "customWidth": "100", + "name": "Spam Effectiveness", + "id": "82812b88-e7f7-4be0-9d13-8e7a7d8c0c4e" + }, + { + "type": 1, + "content": { + "json": "### Spam Detection Trend
\r\n\r\n**This visual displays a per-{Granularity} trend of email Spam detections identified by Microsoft Defender for Office 365. The area chart summarises the number of messages flagged for Spam threats.**" + }, + "name": "text - Spam Trend Header", + "id": "b5574a88-430b-4cca-a76e-9a0b07e9da2e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where ThreatTypes has \"Spam\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, SpamDetections = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "SpamDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "09b7d330-1683-45c4-ac0e-8141580d13b5" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "4" + }, + "name": "group - 6-Spam-detections-trend", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "25273f47-8201-4565-8815-1d059ee8abb6" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Spam Detections by Delivery location, Detection technology, Sender infrastructure and Bulk insights\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Spam detections delivery locations, detection technologies used for detections, sender infrastructure and Bulk insights in inbound email identified by Microsoft Defender for Office 365 as Spam.

**Recommended action:** Raise the Bulk Complaint Level (BCL) threshold for noisy sender domains and consider blocking high-volume, low-value bulk senders where appropriate." + }, + "name": "text - Spam Section2 Banner", + "id": "b82f442b-a3a0-44f7-82df-2fd4a9594992" + }, + { + "type": 1, + "content": { + "json": "### Spam Detections by delivery location
\r\n\r\n**Visualizes counts (per {Granularity}) of Spam detections of inbound emails by various delivery locations Quarantine, Junk folder or Failed (rejected with or without NDR)**" + }, + "name": "text - Spam DeliveryLoc Header", + "id": "a6326d97-56cc-45fb-8019-e0c3346968f2" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections over time summarizing the data daily by Delivery Location.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Spam\" and EmailDirection == \"Inbound\"\r\n| summarize TotalSpamDetections=count(), Quarantine=countif(DeliveryLocation == \"Quarantine\"), Junkfolder=countif(DeliveryLocation == \"Junk folder\"), Inbox=countif(DeliveryLocation == \"Inbox/folder\"), Failed=countif(DeliveryLocation == \"Failed\"), Dropped=countif(DeliveryLocation == \"Dropped\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, TotalSpamDetections=coalesce(TotalSpamDetections,0), Quarantine=coalesce(Quarantine,0), Junkfolder=coalesce(Junkfolder,0), Inbox=coalesce(Inbox,0), Failed=coalesce(Failed,0), Dropped=coalesce(Dropped,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "TotalSpamDetections", + "color": "blue" + }, + { + "seriesName": "Quarantine", + "color": "greenDark" + }, + { + "seriesName": "Junkfolder", + "color": "orangeDark" + }, + { + "seriesName": "Inbox", + "color": "redBright" + }, + { + "seriesName": "Failed", + "color": "red" + }, + { + "seriesName": "Dropped", + "color": "redDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam DeliveryLoc Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "97f89032-34e3-40ff-bb88-42d195aea095" + }, + { + "type": 1, + "content": { + "json": "### Spam Detections Detection Technology
\r\n\r\n**Visualizes counts (per {Granularity}) of Spam detections of inbound emails by various Microsoft Defender for Office 365 detection technologies.**" + }, + "name": "text - Spam DetTech Header", + "id": "935ea90d-8430-49d5-b942-3a7b319a603e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections over time summarizing the data daily by various Spam Detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where DetectionMethods has \"Spam\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| mv-expand Details = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam DetTech Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f31ec0d1-04e1-4b2b-9b98-27289ca34b84" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections summarized by individual Spam detection technology/control in Microsoft Defender for Office 365.\r\n//Each technique is counted individually via mv-expand over DetectionMethods.Spam (matching the sibling trend line chart), so a message flagged by multiple techniques counts once per technique.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Spam\"\r\n| mv-expand Details = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details\r\n| sort by Count desc\r\n| project ['Detection Technology'] = Details, ['Detections'] = Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam DetTech Pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "95e40479-f0bc-41ff-8191-634b606d3632" + }, + { + "type": 1, + "content": { + "json": "### Spam Detections by SenderIPv4 Geo Location
\r\n\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Spam, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" + }, + "name": "text - Spam Geo Header", + "id": "614d1c3f-df6a-4659-b170-7b466c66d66f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections summarizing the data by email sender IP address (SenderIPv4).\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where ThreatTypes has \"Spam\" and isnotempty(SenderIPv4)\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_ ", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "map", + "mapSettings": { + "locInfo": "LatLong", + "locInfoColumn": "SenderIPv4", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "none" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Geo Map", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5519d715-dc79-45f8-8ed5-a63a253c45e3" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spam detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where ThreatTypes has 'Spam' and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Spam Emails'] = count_\r\n| sort by ['Spam Emails'] desc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spam Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "mapSettings": { + "locInfo": "LatLong", + "locInfoColumn": "SenderIPv4", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "heatmap", + "heatmapPalette": "red" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Country Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5078dc24-e8be-4943-98fc-6527968e1e3d" + }, + { + "type": 1, + "content": { + "json": "### Spam Detections Bulk Insights
\r\n\r\n**Displays the distribution of inbound emails across different Bulk Complaint Levels together with Top 10 domains sending Bulk email (grey mail). Helps identify patterns in bulk email complaints and assess potential spam or unwanted message trends.**" + }, + "name": "text - Spam Bulk Header", + "id": "cd7b3cbe-a6c1-422c-ab37-4afc26002d5d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails which has any Bulk complaint level. It is summarizing the data by the various Bulk Complaint levels to understand how many messages are detected with each Bulk Complaint level.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\" and isnotnull(BulkComplaintLevel)\r\n| summarize count() by BulkComplaintLevel\r\n| sort by BulkComplaintLevel desc\r\n| project ['Bulk Complaint Level'] = BulkComplaintLevel, Emails=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "blueDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Bulk By Level", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "021c022b-aa67-427d-9e1a-688af7aed5d4" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails which has any Bulk complaint level. It is summarizing the data by the various Bulk Complaint levels and SenderFromDomain of the email sender. It provides insights how many messages are detected with each Bulk Complaint level for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\" and isnotnull(BulkComplaintLevel)\r\n| summarize count() by BulkComplaintLevel, SenderFromDomain\r\n| top 10 by count_ desc\r\n| project ['Sender Domain'] = SenderFromDomain, ['Bulk Complaint Level'] = BulkComplaintLevel, Emails=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Spam Bulk By Domain", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b1835e0f-f9ad-44c3-bba4-cf9a9546d09a" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "4" + }, + "name": "group - 28-Spam-Delivery location-Detection technology-Sender infrastructure insights", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "307d3d03-93ae-4c8f-b68b-f833ee7d38e8" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n\r\n
Spam Detections Top attacked users and top senders\r\n
\r\n\r\nThis section consolidates key visuals that track and explain spam detections in inbound email as identified by Microsoft Defender for Office 365 focusing on top attacked users and top senders.

**Recommended action:** Review the most-affected users and the top spam sender domains as possible block-list candidates." + }, + "name": "text - Spam Section3 Banner", + "id": "4c34ed7b-86da-4ee1-8a69-f96c213a4340" + }, + { + "type": 1, + "content": { + "json": "### Spam Detections top attacked users
\r\n\r\n**Displays the top 10 recipient email addresses that received inbound emails flagged as Spam. These users may be at higher risk and should be prioritised for targeted cybersecurity awareness training. Training should cover the specific threat types and techniques they are exposed to, and reinforce best practices for promptly reporting any suspicious messages that might bypass security controls and reach their inbox.**" + }, + "customWidth": "100", + "name": "text - Spam TopUsers Header", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "be708ad5-51fd-4a54-b1bc-f912e12b4a01" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails with Spam detections summarizing the data by the top 15 recipient email address (RecipientEmailAddress).\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where EmailDirection ==\"Inbound\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),SpamEmailCount = countif(ThreatTypes has \"Spam\") by RecipientEmailAddress\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(SpamEmailCount / todouble(TotalEmailCount)* 100, 2))\r\n| where SpamEmailCount !=0\r\n| top 15 by SpamEmailCount\r\n| project ['Recipient'] = RecipientEmailAddress, ['Spam Emails'] = SpamEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spam Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "40ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal", + "useGrouping": false + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam TopRecipients Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6e7b357d-6792-41c5-83fc-efae31afe2ee" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains with Spam Detections (Inbound)
\r\n\r\n**Displays the top 10 sender domains sending inbound emails detected as Spam. Helps identify external sources most frequently associated with spam content for prioritised monitoring and mitigation.**" + }, + "customWidth": "100", + "name": "text - Spam TopSenders Header", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1d1bdb8d-9619-488b-935a-3791ad73f096" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total inbound emails with Spam detections summarizing the data by the top 15 email sender P2 domain (SenderFromDomain). Adding additional insights for total inbound emails and bad traffic percentage for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where EmailDirection == \"Inbound\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount = count(),\r\n SpamEmailCount = countif(ThreatTypes has \"Spam\") by SenderFromDomain\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(SpamEmailCount / todouble(TotalEmailCount) * 100, 2))\r\n| where SpamEmailCount !=0\r\n| top 15 by SpamEmailCount\r\n| project ['Sender Domain'] = SenderFromDomain, ['Spam Emails'] = SpamEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spam Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "40ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Spam TopSenders Table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "253efada-ca89-49c5-b1e3-e42ac005b938" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "4" + }, + "name": "group - 29-Spam Detections Top attacked users and top senders", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "d4cc057f-c9b7-40b9-85d3-52f90767d1f5" + }, + { + "type": 1, + "content": { + "json": "# Email Impersonation & BEC Insights\r\n\r\n---\r\nThis tab focuses on the highest-value email threat class: **impersonation and Business Email Compromise (BEC)**. It brings together impersonation and spoof detections, sender authentication (DMARC, DKIM, SPF, CompAuth), supply-chain and partner-compromise correlation, and first-contact / new-vendor senders - the signals that precede targeted financial and credential attacks. It is the email-side companion to the impersonation insights on the **Teams & Collaboration** tab." + }, + "name": "text - impersonation bec description", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "id": "fda8ccd5-fafc-457a-a6a2-05b504be1023" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//KPI summary of inbound email impersonation and spoof (BEC) detections for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet bec = EmailEvents | where EmailDirection == \"Inbound\" | where DetectionMethods has \"Impersonation\" or DetectionMethods has \"Spoof\";\r\nlet inbox = bec | where DeliveryLocation has \"Inbox\";\r\nlet becTrend = toscalar(bec | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet inboxTrend = toscalar(inbox | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(bec | summarize count()), Details = \"Impersonation / Spoof Emails\", Ord = 1, Trend = becTrend),\r\n(print Count = toscalar(bec | summarize dcount(RecipientEmailAddress)), Details = \"Users Targeted\", Ord = 2, Trend = becTrend),\r\n(print Count = toscalar(bec | summarize dcount(SenderFromDomain)), Details = \"Spoofed Sender Domains\", Ord = 3, Trend = becTrend),\r\n(print Count = toscalar(inbox | summarize count()), Details = \"Delivered to Inbox\", Ord = 4, Trend = inboxTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "name": "bec kpi strip", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "91fdd28f-31c4-4f94-b60a-12cd97d44ddf" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Phish Detections Business Email Compromise (BEC) detections\r\n
\r\n\r\nThis section consolidates key visuals that track and explain phish detections in inbound email as identified by Microsoft Defender for Office 365 focusing on Business Email Compromise (BEC) detections Impersonation and Spoof.

**Recommended action:** Enable mailbox intelligence and impersonation protection for frequently-impersonated users and domains; consider adding confirmed look-alike domains to the Tenant Block List." + }, + "name": "text - Phish BEC Banner", + "id": "e3b2232c-8056-4913-a652-64f70e228750" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Impersonation detections Trend\r\n**Displays counts (per {Granularity}) of inbound emails flagged for Business Email Compromise (BEC) using Impersonation detection methods by Microsoft Defender for Office 365. Helps track impersonation attack patterns over time.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Imp Trend Header", + "id": "e95667df-3bcd-4023-9e8f-99ed05bc4bf0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Impersonation detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has 'Impersonation'\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ImpersonationDetections = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "ImpersonationDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Imp Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "61fa166d-f300-42a6-a324-de18b3fdf4c1" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Impersonation detections by Detection Technology\r\n**Visualizes counts (per {Granularity}) of Phish detections of inbound emails by various Microsoft Defender for Office 365 detection technologies used for detecting Impersonations.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Imp Tech Header", + "id": "09e1a866-f344-4a92-a3bd-8c3c3c5d598d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Impersonation detections over time summarizing the data daily by various Impersonation Detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where Details has \"Impersonation\"\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Imp Tech Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6cd5662f-13b4-4a9b-afe7-0a6343e3ab5c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish - Business Email Compromise (BEC) - Impersonation detections summarized by individual detection technology/control in Microsoft Defender for Office 365.\r\n//Each technique is counted individually via mv-expand over DetectionMethods.Phish (matching the sibling trend line chart), so a message flagged by multiple techniques counts once per technique.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where Details has \"Impersonation\"\r\n| summarize Count = count() by Details\r\n| sort by Count desc\r\n| project ['Detection Technology'] = Details, ['Detections'] = Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "graphSettings": { + "type": 0 + }, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Imp Tech Pie", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "73499618-e842-440e-a555-cd8849093884" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Impersonation detections by SenderIPv4 Geo Location\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Phish - Impersonation, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Imp Geo Header", + "id": "189a1ac1-f275-4697-880b-7ffae1e5d263" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Impersonation detections summarizing the data by email sender IP address (SenderIPv4).\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Impersonation\" and isnotempty(SenderIPv4)\r\n//| project Timestamp, EmailDirection, SenderFromAddress, AdditionalFields, SenderIPv4 \r\n| summarize count()by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_ ", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "map", + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "none" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish BEC Imp Geo Map", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "574b61ad-ec2d-4517-93c5-d0e9bd14f2e9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where DetectionMethods has \"Impersonation\" and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Impersonation Emails'] = count_\r\n| sort by ['Impersonation Emails'] desc", + "size": 0, + "showAnalytics": true, + "title": "Impersonation Detections-Sender Heatmap (IPv4)", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Impersonation Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "heatmap", + "heatmapPalette": "red" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish BEC Imp Country", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e53b7dbc-4683-4309-b879-c7be68599159" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Spoof detections Trend\r\n**Displays counts (per {Granularity}) of inbound emails flagged for Business Email Compromise (BEC) using Spoof detection methods by Microsoft Defender for Office 365. Helps track Spoofing based attack patterns over time.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Spoof Trend Header", + "id": "8db0f1b0-49bf-43a2-9f9f-164eb9530629" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Spoof detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has 'Spoof'\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, SpoofDetections = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "SpoofDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Spoof Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "9a308cd9-bf05-4287-b0d5-54636d081a82" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Spoof detections Trend by Detection Technology\r\n**Visualizes counts (per {Granularity}) of Phish detections of inbound emails by various Microsoft Defender for Office 365 detection technologies used for detecting Spoofing.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Spoof Tech Header", + "id": "28c9c15d-d22f-4412-9efc-868b95082668" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Spoof detections over time summarizing the data daily by various Spoof Detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where Details has \"Spoof\"\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "yAxis": [ + "Count" + ], + "seriesLabelSettings": [ + { + "seriesName": "[\"Spoof external domain\"]", + "color": "redDark" + }, + { + "seriesName": "[\"Spoof intra-org\"]", + "color": "orangeDark" + }, + { + "seriesName": "[\"Spoof DMARC\"]", + "color": "yellowDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Spoof Tech Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1a1328fc-5404-4dff-99ed-3a30082a4cbe" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish - Business Email Compromise (BEC) - Spoof detections summarized by individual detection technology/control in Microsoft Defender for Office 365.\r\n//Each technique is counted individually via mv-expand over DetectionMethods.Phish (matching the sibling trend line chart), so a message flagged by multiple techniques counts once per technique.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where Details has \"Spoof\"\r\n| summarize Count = count() by Details\r\n| sort by Count desc\r\n| project ['Detection Technology'] = Details, ['Detections'] = Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish BEC Spoof Tech Pie", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "f7df9892-85b4-49c3-8739-873b745183a3" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections - Spoof detections by SenderIPv4 Geo Location\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Phish - Spoofing, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" + }, + "customWidth": "100", + "name": "text - Phish BEC Spoof Geo Header", + "id": "3c83e7f0-5391-4b1a-bb5b-de0d17488efd" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Spoof detections summarizing the data by email sender IP address (SenderIPv4).\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Spoof\" and isnotempty(SenderIPv4)\r\n//| project Timestamp, EmailDirection, SenderFromAddress, AdditionalFields, SenderIPv4 \r\n| summarize count()by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_ ", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "map", + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "none" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish BEC Spoof Geo Map", + "styleSettings": { + "margin": "15px", + "padding": "15px" + }, + "id": "122d860c-ab0d-475e-b29e-2955020680c7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where DetectionMethods has \"Spoof\" and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Spoof Emails'] = count_\r\n| sort by ['Spoof Emails'] desc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spoof Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "mapSettings": { + "locInfo": "LatLong", + "latitude": "Latitude", + "longitude": "Longitude", + "sizeSettings": "count_", + "sizeAggregation": "Sum", + "labelSettings": "SenderIPv4", + "legendMetric": "count_", + "legendAggregation": "Sum", + "itemColorSettings": { + "nodeColorField": "count_", + "colorAggregation": "Sum", + "type": "heatmap", + "heatmapPalette": "red" + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish BEC Spoof Country", + "styleSettings": { + "margin": "15px", + "padding": "15px" + }, + "id": "9d0111bc-8d01-4a99-9009-645dc02c3bed" + }, + { + "type": 1, + "content": { + "json": "### Supply-Chain & Partner Risk (Possible Partner Compromise)\r\n**Correlates the external domains your organization emails most with inbound emails from those same domains that carried threats. A trusted partner or supplier domain suddenly sending threats is a strong signal that the partner may be compromised - a common supply-chain and business email compromise (BEC) vector.**

**Recommended action:** Verify any flagged partner through a trusted channel before acting on their recent messages, alert them to a possible compromise, and consider tightening inbound policy for that domain until confirmed clean." + }, + "customWidth": "100", + "name": "text - Phish Partner Compromise Header", + "id": "2c62c576-3b05-4663-ae2e-4f961d7409c6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises top outbound recipient domains by outbound email volume and shows total number of inbound emails with Threats from the same domains (as inbound senders) \r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Outbound\"\r\n| project RecipientDomain = tostring(split(RecipientEmailAddress, \"@\")[1])\r\n| summarize count() by RecipientDomain\r\n| project OutboundCount=count_, RecipientDomain, SenderFromDomain=RecipientDomain\r\n| join (EmailEvents | where EmailDirection == \"Inbound\" and isempty(ThreatTypes)==false) on SenderFromDomain\r\n| summarize max(OutboundCount),count() by SenderFromDomain\r\n| project SenderFromDomain, OutboundEmails=max_OutboundCount, IncomingEmailsWithThreats=count_\r\n| extend Bad_Traffic_Percentage = todouble(round(IncomingEmailsWithThreats / todouble(OutboundEmails) * 100, 2))\r\n| top 15 by OutboundEmails\r\n| project ['Sender Domain'] = SenderFromDomain, ['Outbound Emails'] = OutboundEmails, ['Inbound w/ Threats'] = IncomingEmailsWithThreats, ['Bad Traffic %'] = Bad_Traffic_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Outbound Emails", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Inbound w/ Threats", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "60ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish Partner Compromise", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1aaa047c-1108-4288-833e-61ca35b5495a" + }, + { + "type": 1, + "content": { + "json": "### Top Recipients Targeted by Impersonation / BEC\r\n**Lists the recipients most frequently targeted by impersonation and Business Email Compromise (BEC) attempts, showing the number of impersonation emails, how many distinct senders were involved, the top spoofed sender domains, and how many of those messages were delivered to the inbox. Helps identify high-risk users (often executives or finance staff) who may need extra protection or awareness.**" + }, + "customWidth": "100", + "name": "text - impersonation targets", + "id": "b1e7c2a4-9f3d-4a6b-8c12-7d5e9f0a1b23" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top recipients targeted by impersonation / BEC, with distinct senders, spoofed domains and how many landed in the inbox.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| where OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")\r\n| where DetectionMethods has \"Impersonation\"\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize ImpersonationEmails = count(),\r\n DistinctSenders = dcount(SenderFromAddress),\r\n TopSpoofedDomains = make_set(SenderFromDomain, 5),\r\n DeliveredToInbox = countif(DeliveryLocation has \"Inbox\")\r\n by RecipientEmailAddress\r\n| top 20 by ImpersonationEmails\r\n| project ['Recipient'] = RecipientEmailAddress, ['Impersonation Emails'] = ImpersonationEmails, ['Distinct Senders'] = DistinctSenders, ['Top Spoofed Domains'] = strcat_array(TopSpoofedDomains, \", \"), ['Delivered to Inbox'] = DeliveredToInbox", + "size": 0, + "title": "Top Recipients Targeted by Impersonation / BEC", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "showAnalytics": true, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Impersonation Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "name": "newviz - impersonation targets", + "id": "afe28369-af82-47ae-846d-179bd86b660e" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "name": "group - 7 - Phish-BEC-Insights", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "b7971cd9-d086-47c7-8f66-50956b9c56c3" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Phish Detections Sender Authentication details (DMARC, DKIM, SPF, CompAuth)\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Sender Authentication checks details in inbound email by Microsoft Defender for Office 365 focusing on the various Sender Authentication standards: DMARC, DKIM, SPF, CompAuth.

**Recommended action:** For domains failing DMARC/DKIM/SPF, verify your own outbound authentication is published and enforced (p=reject), and treat persistent external spoofers as possible block candidates." + }, + "name": "text - Phish Section5 Banner", + "id": "90d7a338-d943-4398-b788-bfd4f93007d4" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections Sender Authentication Trend (DMARC, DKIM, SPF, CompAuth)\r\n**Shows counts (per {Granularity}) of sender authentication check outcomes (DMARC, DKIM, SPF, CompAuth) performed by Microsoft Defender for Office 365 on inbound emails. Useful for monitoring authentication success and failure patterns over time to identify anomalies or potential phishing risks.**" + }, + "customWidth": "100", + "name": "text - Phish SenderAuth Trend Header", + "id": "4a0ab90e-55dd-4fa6-82c3-0edc57ce0966" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spoof- DMARC fails summarizing the data daily.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend DMARCFail = (tostring(parse_json(AuthenticationDetails).DMARC) == \"fail\") \r\n| summarize DMARCFail = sum(DMARCFail) by bin (Timestamp,{Granularity})", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "DMARCFail", + "color": "orangeDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish Auth DMARC Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "79920d30-01d4-4412-b994-853e50c9d7d8" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spoof- DKIM fails summarizing the data daily.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend DKIMFail = (tostring(parse_json(AuthenticationDetails).DKIM) == \"fail\") \r\n| summarize DKIMFail = sum(DKIMFail) by bin (Timestamp,{Granularity})", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "DKIMFail", + "color": "yellowDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish Auth DKIM Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "bf09ffd4-eee0-42f7-a507-1cf54d9c365a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spoof- SPF fails summarizing the data daily.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend SPFFail = (tostring(parse_json(AuthenticationDetails).SPF) == \"fail\") \r\n| summarize SPFFail = sum(SPFFail) by bin (Timestamp,{Granularity})", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "SPFFail", + "color": "purpleDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish Auth SPF Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "4d66fe13-9904-45cf-8783-f3ee984f3a66" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spoof- Composite Authentication fails summarizing the data daily.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend CompAuthFail = (tostring(parse_json(AuthenticationDetails).CompAuth) == \"fail\") \r\n| summarize CompAuthFail = sum(CompAuthFail) by bin (Timestamp,{Granularity})", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "CompAuthFail", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - Phish Auth CompAuth Trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "0968b828-23fe-4fa2-a5ea-8ab39362457f" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections Top Sender Domains with DMARC Failures (Inbound)\r\n**Displays the top 10 sender domains (P1 and P2) for inbound emails where Spoof-DMARC detection triggered. Includes total inbound email volume and calculates DMARC fail traffic percentage per domain to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "text - Phish Auth DMARC Domains Header", + "id": "24d4689a-eb6d-49f5-85a8-fcadca409f7a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Spoof-DMARC fails detections summarizing the data by the top 10 email sender P2 domain (SenderFromDomain) and sender P1 domain (SenderMailFromDomain). Adding additional insights for total inbound emails and DMARC fail traffic percentage for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalEmailCount = count(),\r\n DMARCFailCount = countif(set_has_element(parse_json(DetectionMethods).Phish, \"Spoof DMARC\")) by P1Sender=SenderMailFromDomain, P2Sender=SenderFromDomain\r\n| extend DMARCFail_Traffic_Percentage = todouble(round(DMARCFailCount / todouble(TotalEmailCount) * 100, 2))\r\n| where DMARCFailCount !=0\r\n| top 10 by DMARCFailCount\r\n| project ['P1 Sender'] = P1Sender, ['P2 Sender'] = P2Sender, ['DMARC Failures'] = DMARCFailCount, ['Total Inbound'] = TotalEmailCount, ['DMARC Fail %'] = DMARCFail_Traffic_Percentage", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "DMARCFail", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "DMARC Fail %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "40ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish Auth DMARC Domains", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "642814ad-9d24-4be9-ae10-3578e89da05b" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections Top Sender Domains with Spoof External Domain Detections (Inbound)\r\n**Displays the top 10 sender domains (P1 and P2) for inbound emails flagged for Spoof External Domain detection. Includes total inbound email volume and calculates spoof traffic percentage per domain to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "text - Phish Auth SpoofExt Domains Header", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "993fdc34-354b-412e-be39-facbde4f4f0e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish-Spoof-external domain detections summarizing the data by the top 10 email sender P2 domain (SenderFromDomain) and sender P1 domain (SenderMailFromDomain). Adding additional insights for total inbound emails and Spoof external domain detection traffic percentage for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalEmailCount = count(),\r\n SpoofExternalCount = countif(set_has_element(parse_json(DetectionMethods).Phish, \"Spoof external domain\")) by P1Sender=SenderMailFromDomain, P2Sender=SenderFromDomain\r\n| extend SpoofExternal_Traffic_Percentage = todouble(round(SpoofExternalCount / todouble(TotalEmailCount) * 100, 2))\r\n| where SpoofExternalCount !=0\r\n| top 10 by SpoofExternalCount\r\n| project ['P1 Sender'] = P1Sender, ['P2 Sender'] = P2Sender, ['Spoof External'] = SpoofExternalCount, ['Total Inbound'] = TotalEmailCount, ['Spoof External %'] = SpoofExternal_Traffic_Percentage", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spoof External", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spoof External %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "40ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "SpoofExternalFail", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true, + "sortBy": [ + { + "itemKey": "Spoof External %", + "sortOrder": 2 + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish Auth SpoofExt Domains", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "69ca3799-d2d5-4896-b3a5-1eeba46f0b46" + }, + { + "type": 1, + "content": { + "json": "### Phish Detections Top Sender Domains with Spoof Internal Domain Detections (Inbound)\r\n**Displays the top 10 sender domains (P1 and P2) for inbound emails flagged for Spoof Internal Domain detection. Includes total inbound email volume and calculates spoof traffic percentage per domain to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "text - Phish Auth SpoofInt Domains Header", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3fa33c5d-0eba-471f-b47f-0c12c1f770d6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phish-Spoof-internal domain detections summarizing the data by the top 10 email sender P2 domain (SenderFromDomain) and sender P1 domain (SenderMailFromDomain). Adding additional insights for total inbound emails and Spoof internal domain detection traffic percentage for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalEmailCount = count(),\r\n SpoofInternalCount = countif(set_has_element(parse_json(DetectionMethods).Phish, \"Spoof intra-org\")) by P1Sender=SenderMailFromDomain, P2Sender=SenderFromDomain\r\n| extend SpoofInternal_Traffic_Percentage = todouble(round(SpoofInternalCount / todouble(TotalEmailCount) * 100, 2))\r\n| where SpoofInternalCount !=0\r\n| top 10 by SpoofInternalCount\r\n| project ['P1 Sender'] = P1Sender, ['P2 Sender'] = P2Sender, ['Spoof Internal'] = SpoofInternalCount, ['Total Inbound'] = TotalEmailCount, ['Spoof Internal %'] = SpoofInternal_Traffic_Percentage", + "size": 3, + "showAnalytics": true, + "title": "Top 10 Spoof intra-org detections by Sender domain (P1/P2)", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spoof Internal", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spoof Internal %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "40ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "SpoofIntraorgFail", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - Phish Auth SpoofInt Domains", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "ae0c65c7-68ea-4d50-b177-1effeaf1c045" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "name": "group - 8-Phish-SenderAuth", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "8077779a-4da8-46be-8032-626bd8c36dbd" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
First-Contact & New-Vendor Senders\r\n
\r\n\r\nExternal email senders and domains seen for the first time in the selected period. New/first-contact relationships - especially ones already carrying threats - are a common precursor to phishing, business email compromise (BEC), and supply-chain attacks.

**Recommended action:** Treat brand-new domains sending threats as high-priority review; verify any that claim to be a known brand or partner before trusting their messages." + }, + "name": "phish fc banner", + "id": "05b83435-c7ed-48a3-919e-388b2e599726" + }, + { + "type": 1, + "content": { + "json": "### First-contact external senders
\r\n\r\n**External email senders ordered by when they were first seen in the period (most recent first). In tenants with longer history this highlights genuinely new senders.**" + }, + "customWidth": "100", + "name": "phish fc senders header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "c57dffb4-dfdb-4a1e-93be-16fa9e856a0d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists external email senders seen for the first time in the selected period (most recent first), surfacing new/first-contact senders. In tenants with longer history this highlights genuinely new relationships - a common precursor to BEC and supply-chain attacks.\r\n// TIP: to hide your own accepted domains, uncomment the ExcludeDomains line and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"fabrikam.com\"]);\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| extend SenderDomain = tostring(split(SenderFromAddress, \"@\")[1])\r\n| where isnotempty(SenderFromAddress)\r\n//| where SenderDomain !in~ (ExcludeDomains)\r\n| summarize FirstSeen=min(Timestamp), Messages=count(), ThreatMessages=countif(isnotempty(ThreatTypes)) by SenderFromAddress, SenderDomain\r\n| top 20 by FirstSeen desc\r\n| project ['Sender']=SenderFromAddress, ['Sender Domain']=SenderDomain, ['First Seen']=FirstSeen, Messages, ['Threat Messages']=ThreatMessages", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "phish fc senders table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d1ceb0ac-2dad-49af-b416-a3376a7b8513" + }, + { + "type": 1, + "content": { + "json": "### New sender domains carrying threats
\r\n\r\n**External sender domains seen for the first time in the period that already carried threats, most-recent first. A brand-new domain sending threats to your users is a strong early-warning signal.**" + }, + "customWidth": "100", + "name": "phish fc domains header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "bd29bbe4-cde2-499c-a1d0-e2cc51f7733d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists external sender domains seen for the first time in the selected period that already carried threats, ranked by most-recently first seen. A brand-new domain sending threats to your users is a strong early-warning signal for phishing and BEC.\r\n// TIP: to hide your own accepted domains, uncomment the ExcludeDomains line and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"fabrikam.com\"]);\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| extend SenderDomain = tostring(split(SenderFromAddress, \"@\")[1])\r\n| where isnotempty(SenderDomain)\r\n//| where SenderDomain !in~ (ExcludeDomains)\r\n| summarize FirstSeen=min(Timestamp), LastSeen=max(Timestamp), Messages=count(), Senders=dcount(SenderFromAddress), Recipients=dcount(RecipientEmailAddress), ThreatMessages=countif(isnotempty(ThreatTypes)) by SenderDomain\r\n| where ThreatMessages > 0\r\n| top 20 by FirstSeen desc\r\n| project ['Sender Domain']=SenderDomain, ['First Seen']=FirstSeen, Messages, Senders, Recipients, ['Threat Messages']=ThreatMessages, ['Last Seen']=LastSeen", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Senders", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Recipients", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "phish fc domains table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "7da952d5-5ae2-4b2e-a5cf-c78b11bda4f8" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "15" + }, + "customWidth": "100", + "name": "group - Phish First Contact", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "90e5248a-2c35-48f3-869c-c45c631c6fbf" + }, + { + "type": 1, + "content": { + "json": "# URL Detections and URL Click Insights\r\n\r\n---\r\nThis tab provides insights into **URL-based detections** in email messages and details about URL clicks performed by end users on URLs identified as **malicious**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "5" + }, + "name": "text - 24 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "2156430d-fec6-48bb-a9a8-3166182f6993" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//KPI summary of URL threat protection (Safe Links clicks and URLs seen in email) for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet clicks = UrlClickEvents;\r\nlet blocked = clicks | where ActionType in (\"ClickBlocked\",\"ClickBlockedByTenantPolicy\");\r\nlet allowed = clicks | where ActionType == \"ClickAllowed\";\r\nlet blockedTrend = toscalar(blocked | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet allowedTrend = toscalar(allowed | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet usersTrend = toscalar(clicks | make-series Trend = dcount(AccountUpn) default = 0 on Timestamp step gran | project Trend);\r\nlet urlsTrend = toscalar(EmailUrlInfo | make-series Trend = dcount(Url) default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(blocked | summarize count()), Details = \"Malicious Clicks Blocked\", Ord = 1, Trend = blockedTrend),\r\n(print Count = toscalar(allowed | summarize count()), Details = \"Clicks Allowed Through\", Ord = 2, Trend = allowedTrend),\r\n(print Count = toscalar(clicks | summarize dcount(AccountUpn)), Details = \"Users Clicking Links\", Ord = 3, Trend = usersTrend),\r\n(print Count = toscalar(EmailUrlInfo | summarize dcount(Url)), Details = \"Distinct URLs in Email\", Ord = 4, Trend = urlsTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "5" + }, + "name": "url kpi strip", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d5e2326a-a5dd-4217-bb75-0e337d75d306" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Insights on URL-Based Threat Detections\r\n
\r\n\r\nThis section consolidates key visuals that track and explain URL based threat detections in inbound email as identified by Microsoft Defender for Office 365 focusing on per-{Granularity} trends of URL-based threat detections, QR code detections, and URL scans activity by locations.

**Recommended action:** Confirm Safe Links is enabled for email and Teams; investigate QR-code and URL detection spikes for emerging campaigns." + }, + "name": "text - 13 - Copy", + "id": "ed3468e7-1936-45fd-9168-93010a662302" + }, + { + "type": 1, + "content": { + "json": "### Trend of URL-Based Malware Threat Detections
\r\n\r\n**This visual displays a per-{Granularity} trend of emails with URL based Malware threat detections identified by Microsoft Defender for Office 365. The line chart summarises the number of messages flagged for malware threats.**" + }, + "name": "text - 13 - Copy - Copy", + "id": "77e7bbac-d752-478b-bce9-06bb1bd12bfe" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Malware detections over time summarizing the data daily by various Malware URL threat based detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Malware'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand MalwareMethod = ParsedMethods.Malware\r\n| where MalwareMethod contains \"URL\"\r\n| summarize Count = count() by MalwareMethod = tostring(MalwareMethod), Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct MalwareMethod | extend d = 1) on d | project Timestamp, MalwareMethod\r\n| join kind=leftouter (agg) on Timestamp, MalwareMethod\r\n| project Timestamp, MalwareMethod, Count = coalesce(Count, 0)\r\n| sort by MalwareMethod asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 8 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "79ef5e7b-57a6-4519-9899-18fd8cae5e68" + }, + { + "type": 1, + "content": { + "json": "### Trend of URL-Based Phish Threat Detections
\r\n\r\n**This visual displays a per-{Granularity} trend of emails with URL based Phish threat detections identified by Microsoft Defender for Office 365. The line chart summarises the number of messages flagged for Phish threats.**" + }, + "name": "text - 13 - Copy - Copy - Copy", + "id": "48923812-5440-4f47-8881-273f14cbfb8e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total emails with Phishing detections over time summarizing the data daily by various Phishing URL threat based detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Phish'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand PhishMethod = ParsedMethods.Phish\r\n| where PhishMethod contains \"URL\"\r\n| summarize Count = count() by PhishMethod = tostring(PhishMethod), Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct PhishMethod | extend d = 1) on d | project Timestamp, PhishMethod\r\n| join kind=leftouter (agg) on Timestamp, PhishMethod\r\n| project Timestamp, PhishMethod, Count = coalesce(Count, 0)\r\n| sort by PhishMethod asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 8 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b983b361-6c2e-47d5-b2c5-edd9caa6a55d" + }, + { + "type": 1, + "content": { + "json": "### Trend (per {Granularity}) of QR Code-Based Threat Detections
\r\n\r\n**Displays counts (per {Granularity}) of inbound emails containing QR codes flagged for Phish, Malware, or Spam via URL-based detection methods. Helps track QR code abuse patterns over time.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3d8b75e1-6e1d-44eb-b1fc-78d3db7feb71" + }, + { + "type": 1, + "content": { + "json": "### URL Scan activity by Location (per {Granularity})
\r\n\r\n**Displays counts (per {Granularity}) of URLs scanned from various locations within emails (e.g., body, attachments, QR codes). Helps identify where malicious URLs are most commonly embedded.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b275b28c-e441-4c19-9055-256d5d45c69c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where EmailDirection == \"Inbound\" \r\n| where DetectionMethods has \"Url\"\r\n| join EmailUrlInfo on NetworkMessageId\r\n| where UrlLocation == \"QRCode\"\r\n| summarize [\"Phish QR Detection\"]=countif(parse_json(DetectionMethods).Phish has \"URL\"), [\"Malware QR Detection\"]=countif(parse_json(DetectionMethods).Malware has \"URL\"), [\"Spam QR Detection\"]=countif(parse_json(DetectionMethods).Spam has \"URL\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, [\"Phish QR Detection\"]=coalesce([\"Phish QR Detection\"],0), [\"Malware QR Detection\"]=coalesce([\"Malware QR Detection\"],0), [\"Spam QR Detection\"]=coalesce([\"Spam QR Detection\"],0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "graphSettings": { + "type": 0 + }, + "chartSettings": { + "xAxis": "Timestamp", + "xSettings": { + "dateFormatSettings": { + "formatName": "shortDatePattern", + "showUtcTime": false + } + } + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 6", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6c2a7724-d3c2-42b2-b8da-7acbcd0666c6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises where URL's have been scanned identified from various locations in emails\r\nEmailUrlInfo\r\n| summarize count() by UrlLocation", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 5", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5640dbd5-4085-4f2a-8fb9-e4112233e99e" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "5" + }, + "name": "group - 9-URL detections", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "b572d79b-17a0-48ac-9a43-4f20324cf998" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Insights on URL Click-Based Threat Detections\r\n
\r\n\r\nThis section consolidates key visuals that track and explain URL click based threat detections in emails as identified by Microsoft Defender for Office 365 focusing on per-{Granularity} trend of blocked URL clicks, time-of-click URL scans by workload, malicious clicks allowed, top clicks on malicious URLs, and more.

**Recommended action:** For blocked-click spikes, verify Safe Links is set to not allow click-through; investigate workloads with high click-through activity." + }, + "name": "text - 13 - Copy - Copy", + "id": "6d37617e-911e-4ce6-a10d-4749486738ea" + }, + { + "type": 1, + "content": { + "json": "### Trend (per {Granularity}) of Blocked URL Click Events
\r\n\r\n**Shows the count (per {Granularity}) of blocked URL click attempts and click attempts on URLs with detections, grouped by threat types (e.g., Phish, Malware, Spam). Helps track user interaction with malicious links over time across various threat types.**" + }, + "name": "text - 13 - Copy - Copy - Copy", + "id": "9e477950-bedc-4cc0-9863-df07d124806c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// Generates a time-series analysis for blocked URL click events from the 'UrlClickEvents' table\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(UrlClickEvents\r\n| where isnotempty(ActionType)\r\n| where ActionType has_any(\"ClickBlocked\")\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, BlockedClicks = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "BlockedClicks", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "query - 4", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "366e80d9-f6ed-43af-91e5-3d04cdcf692d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of click attempts on URL's with detections split by the different threat types identified\r\nUrlClickEvents\r\n| where isnotempty(ThreatTypes)\r\n| summarize count() by ThreatTypes", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "query - 4", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a356eac3-62c2-4fc9-a4d9-3b05b13848df" + }, + { + "type": 1, + "content": { + "json": "### Trend (per {Granularity}) of URL Click Actions by Type
\r\n\r\n**Displays counts (per {Granularity}) of URL click events categorised by action type: Blocked, Allowed, Pending Verdict, Error Page, and Clicked Through. Helps identify risky user behaviour and policy gaps.**" + }, + "customWidth": "66", + "name": "text - 13 - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a91fe7a6-f507-48f7-bbcc-61dc4f998ba6" + }, + { + "type": 1, + "content": { + "json": "### URL Clicks by Workload
\r\n\r\n**Displays counts (per {Granularity}) of URL click events grouped by Workload (e.g., Outlook, Teams, Copilot, Office Apps: Word, Excel, PowerPoint) Helps identify which applications are most frequently used for URL interactions and potential risk exposure.**" + }, + "customWidth": "33", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "ce05fa08-6e68-4c02-a0bf-2be6cdfae935" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises different URL click event types by action (e.g., blocked, allowed, pending verdict, error pages, and clicked through), summarizing the data daily\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(UrlClickEvents\r\n| where isnotempty(ActionType)\r\n| summarize ClickBlocked=countif(ActionType has_any(\"ClickBlocked\")), ClickAllowed=countif(ActionType has_any(\"ClickAllowed\")), PendingVerdict=countif(ActionType has_any(\"UrlScanInProgress\")), ErrorPage=countif(ActionType has_any(\"UrlErrorPage\")), ClickedThrough=countif(IsClickedThrough == true) by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ClickBlocked=coalesce(ClickBlocked,0), ClickAllowed=coalesce(ClickAllowed,0), PendingVerdict=coalesce(PendingVerdict,0), ErrorPage=coalesce(ErrorPage,0), ClickedThrough=coalesce(ClickedThrough,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "query - 1", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a12b4c78-7d18-4adc-86e0-54395d6a996a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises where URL clicks scanned by the Workload the click happened from\r\nUrlClickEvents\r\n| summarize count() by Workload", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "query - 5 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3237cd55-1d5c-41a9-a8f2-1d46c61a709e" + }, + { + "type": 1, + "content": { + "json": "### Blocked URL Clicks by Workload (per {Granularity})
\r\n\r\n**Displays counts (per {Granularity}) of blocked URL click attempts grouped by Workload (Email, Teams, Office, Microsoft 365 Copilot). Helps identify which platforms are most exposed to malicious link interactions and where user awareness or policy enforcement should be strengthened.**" + }, + "customWidth": "66", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1f209a83-3d50-4bb8-9a79-a365a50a4142" + }, + { + "type": 1, + "content": { + "json": "### Click-Through Activity on Detected URLs by Workload
\r\n\r\n**Displays counts of click‑through actions on URLs already identified with detections, grouped by Workload where the click happened. Helps identify clients/platforms where users are most likely to proceed to risky URLs and prioritise awareness training or policy tuning for those workloads**" + }, + "customWidth": "33", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "33592db8-0ff5-4d8e-bd8f-0201b81a4584" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises blocked URL click event types by Workload (e.g., Email, Teams, Office, Microsoft 365 Copilot), summarizing the data daily\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(UrlClickEvents\r\n| where ActionType ==\"ClickBlocked\"\r\n| summarize Teams=countif(Workload==\"Teams\"), Office=countif(Workload==\"Office\"), Email=countif(Workload==\"Email\"), Copilot=countif(Workload==\"Copilot\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, Teams=coalesce(Teams,0), Office=coalesce(Office,0), Email=coalesce(Email,0), Copilot=coalesce(Copilot,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "query - 3", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "80241767-0f69-4e2e-9889-3bf1f48e4f02" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of click-through activities on URL's with detections split by the source client\r\nUrlClickEvents \r\n| where IsClickedThrough !=\"0\"\r\n| where isnotempty(ThreatTypes) \r\n| summarize count() by Workload", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "query - 2", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "fde29b46-2896-4bfc-bb61-09436696d738" + }, + { + "type": 1, + "content": { + "json": "### Top clicks on Malicious URLs
\r\n\r\n**Displays the top 20 URLs associated with detections that registered the highest number of clicks. Includes ThreatTypes, ActionType, and Workload to provide context on the nature of the threat and where user interaction occurred.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "22bda63a-626c-47de-9a76-ad665ef87862" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows the top 20 URL's that have a detection associated with the most ammount of clicks registered \r\nUrlClickEvents\r\n| where ThreatTypes !=\"\"\r\n| summarize count() by Url, ThreatTypes, ActionType, Workload\r\n| top 20 by count_\r\n| project ['URL']=Url, ['Threat Types']=ThreatTypes, ['Action Type']=ActionType, Workload, ['Click Count']=count_", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Click Count", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 10 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a044fd4e-7be6-4a11-974c-b54e417c2a81" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "5" + }, + "name": "group - 31-URL clicks", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "75e543f6-08c0-42ed-9869-ecd61b721d34" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Top Risky Users Clicking on URLs with Threats\r\n
\r\n\r\nThis section consolidates key visuals that track and identify users who have clicked on malicious URLs detected by Microsoft Defender for Office 365.

**Recommended action:** Enroll these users in security awareness training and verify Safe Links policy coverage for their mailboxes." + }, + "name": "text - 13 - Copy - Copy - Copy", + "id": "19487811-a94b-4537-877e-61ac7e287c21" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Users Clicking on URLs with Malware Threat
\r\n\r\n**Displays the top 10 user accounts with the highest number of click attempts on URLs flagged as Malware. Helps identify individuals at greater risk and prioritise targeted security awareness training.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "78e10621-0e98-44c4-8399-810c19f138c2" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top 10 users with click attempts on URL's with malware detections\r\nUrlClickEvents\r\n| summarize TotalClickCount=count(),MalwareClickCount = countif(ThreatTypes has \"Malware\") by AccountUpn\r\n| extend Bad_Click_Percentage = todouble(round(MalwareClickCount / todouble(TotalClickCount) *100, 2))\r\n| where MalwareClickCount !=0\r\n| sort by MalwareClickCount desc\r\n| top 15 by MalwareClickCount\r\n| project ['User']=AccountUpn, ['Malware Clicks']=MalwareClickCount, ['Total Clicks']=TotalClickCount, ['Bad Click %']=Bad_Click_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Malware Clicks", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "25ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Clicks", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Click %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "25ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "MalwareEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "TotalEmailCount", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad_Traffic_Percentage_Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 18 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a7ae8a75-ca7f-49be-8cad-d1451a3bd396" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Users Clicking on URLs with Phish Threat
\r\n\r\n**Displays the top 10 user accounts with the highest number of click attempts on URLs flagged as Phish. Helps identify individuals at greater risk and prioritise targeted security awareness training.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "90d9a0c3-970a-4998-be62-3b3b84bb0f37" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top 10 users with click attempts on URL's with Phish detections\r\nUrlClickEvents\r\n| summarize TotalClickCount=count(),PhishClickCount = countif(ThreatTypes has \"Phish\") by AccountUpn\r\n| extend Bad_Click_Percentage = todouble(round(PhishClickCount / todouble(TotalClickCount) *100, 2))\r\n| where PhishClickCount !=0\r\n| sort by PhishClickCount desc\r\n| top 15 by PhishClickCount\r\n| project ['User']=AccountUpn, ['Phish Clicks']=PhishClickCount, ['Total Clicks']=TotalClickCount, ['Bad Click %']=Bad_Click_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Phish Clicks", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "25ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Clicks", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Click %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "25ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "MalwareClickCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "MalwareEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "TotalEmailCount", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad_Traffic_Percentage_Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 18 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d46877d9-03af-463a-b406-bb4c601dffeb" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Users Clicking on URLs with Spam Threat
\r\n\r\n**Displays the top 10 user accounts with the highest number of click attempts on URLs flagged as Spam. Helps identify individuals at greater risk and prioritise targeted security awareness training.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "dc66e020-0932-4346-8e20-6a2dc78de7a9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top 10 users with click attempts on URL's with Spam detections\r\nUrlClickEvents\r\n| summarize TotalClickCount=count(),SpamClickCount = countif(ThreatTypes has \"Spam\") by AccountUpn\r\n| extend Bad_Click_Percentage = todouble(round(SpamClickCount / todouble(TotalClickCount) *100, 2))\r\n| where SpamClickCount !=0\r\n| sort by SpamClickCount desc\r\n| top 15 by SpamClickCount\r\n| project ['User']=AccountUpn, ['Spam Clicks']=SpamClickCount, ['Total Clicks']=TotalClickCount, ['Bad Click %']=Bad_Click_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Spam Clicks", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "25ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Clicks", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Click %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "25ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "PhishClickCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "MalwareClickCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "MalwareEmailCount", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "TotalEmailCount", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad_Traffic_Percentage_Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "count_", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "50ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 18 - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "734ee45e-4dff-4ca1-b17d-02389086b17b" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "5" + }, + "name": "group - 32-Top clickers", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "ee6c3413-28be-49a1-a89d-bf5fce7acfa4" + }, + { + "type": 1, + "content": { + "json": "# Microsoft Teams Collaboration Protection\r\n\r\n---\r\nAs email defenses mature, attackers are shifting into **Microsoft Teams**, where messages bypass secure email gateways and carry the implicit trust of a colleague chat. Microsoft Threat Intelligence reports Teams-based phishing and voice phishing (vishing) rising steadily through 2026, most often as **IT help desk or technical-support impersonation** from external or newly-created tenants, used to steer users toward remote-access tools and credential theft.\r\n\r\nThis tab shows **Microsoft Defender for Office 365** protection for Microsoft Teams: threat detections and impersonation, suspicious external senders, malicious URLs and clicks, malicious files, post-delivery ZAP removals, and user and admin submissions across chats and channels.\r\n\r\n**Recommended action:** Treat unsolicited external help desk or IT support contact as suspicious. Restrict inbound chat from unmanaged and consumer tenants, allowlist trusted external domains, remove or restrict remote-support tools such as Quick Assist where they are not required, and enforce phishing-resistant MFA for all users (Conditional Access with authentication strength), prioritizing privileged and administrator accounts first.\r\n\r\n[

Disrupting threats targeting Microsoft Teams

](https://www.microsoft.com/en-us/security/blog/2025/10/07/disrupting-threats-targeting-microsoft-teams/)[

Cross-tenant helpdesk impersonation to data exfiltration: a human-operated intrusion playbook

](https://www.microsoft.com/en-us/security/blog/2026/04/18/crosstenant-helpdesk-impersonation-data-exfiltration-human-operated-intrusion-playbook/)[

Help on the line: how a Microsoft Teams support call led to compromise

](https://www.microsoft.com/en-us/security/blog/2026/03/16/help-on-the-line-how-a-microsoft-teams-support-call-led-to-compromise/)[

Email threat landscape: Q2 2026 trends and insights

](https://www.microsoft.com/en-us/security/blog/2026/07/23/email-threat-landscape-q2-2026-trends-and-insights/)" + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "text - teams description", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5c0f0100-0a11-4b22-9c33-000000000100" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Headline Microsoft Teams protection metrics for the selected period, with per-interval sparklines. Messages are de-duplicated to the latest record per Teams message.\r\nlet gran = {Granularity};\r\nlet msgs = materialize(MessageEvents | summarize arg_max(Timestamp, *) by TeamsMessageId);\r\nlet zap = materialize(MessagePostDeliveryEvents);\r\nunion\r\n(msgs | summarize Count = count() | extend Details = \"Teams Messages Scanned\", Ord = 1, Trend = toscalar(msgs | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where isnotempty(ThreatTypes) | summarize Count = count() | extend Details = \"Messages with Threats\", Ord = 2, Trend = toscalar(msgs | where isnotempty(ThreatTypes) | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where ThreatTypes has \"Phish\" | summarize Count = count() | extend Details = \"Phish Detections\", Ord = 3, Trend = toscalar(msgs | where ThreatTypes has \"Phish\" | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where ThreatTypes has \"Malware\" | summarize Count = count() | extend Details = \"Malware Detections\", Ord = 4, Trend = toscalar(msgs | where ThreatTypes has \"Malware\" | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where ThreatTypes has \"Spam\" | summarize Count = count() | extend Details = \"Spam Detections\", Ord = 5, Trend = toscalar(msgs | where ThreatTypes has \"Spam\" | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where SafetyTip == \"URLMessageWarning\" | summarize Count = count() | extend Details = \"Messages with URL Warning\", Ord = 6, Trend = toscalar(msgs | where SafetyTip == \"URLMessageWarning\" | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(zap | summarize Count = count() | extend Details = \"Post-Delivery ZAP Actions\", Ord = 7, Trend = toscalar(zap | make-series S = count() default = 0 on Timestamp step gran | project S))\r\n| sort by Ord asc\r\n| project Details, Count, Trend", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21 + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams kpi tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b2c476ca-4141-43b4-9d4e-98470aa432fc", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + } + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Microsoft Teams - Collaboration Protection Overview\r\n
\r\n\r\nMicrosoft Defender for Office 365 extends its protection to **Microsoft Teams**, detecting malicious messages, URLs, and files shared through chats and channels. This tab summarizes Teams message detections, link-safety warnings, post-delivery ZAP, file scanning, and user/admin submissions.

*Scope note: the Teams message tables surface metadata for external-conversation messages plus internal messages that contain URLs, so counts reflect that scope rather than the full volume of Teams messages.*" + }, + "name": "teams overview banner", + "id": "2f71360f-1673-480f-8361-5afc83aee67d" + }, + { + "type": 1, + "content": { + "json": "### Teams threat detections over time
\r\n\r\n**Volume (per selected interval) of Microsoft Teams messages detected with a threat by Microsoft Defender for Office 365. Spikes may indicate a targeted Teams-based campaign.**" + }, + "customWidth": "100", + "name": "teams trend header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "0ac71d4e-8ecb-4d17-9fd3-10754007ec07" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the number of Microsoft Teams messages detected with a threat over time, de-duplicated to the latest record per message and summarized per selected interval.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(MessageEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(MessageEvents | summarize max(Timestamp));\r\nlet agg = materialize(MessageEvents | where isnotempty(ThreatTypes) | summarize arg_max(Timestamp, *) by TeamsMessageId | summarize ThreatDetections = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ThreatDetections = coalesce(ThreatDetections, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "xAxis": "Timestamp", + "seriesLabelSettings": [ + { + "seriesName": "ThreatDetections", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams detection trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "937f3bc6-21f5-4f4c-ab72-78f08f32c5bd" + }, + { + "type": 1, + "content": { + "json": "### Threat type breakdown
\r\n\r\n**Split of Microsoft Teams threat detections across Phish, Malware, and Spam.**" + }, + "customWidth": "50", + "name": "teams threat pie header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "645a39ae-843a-47db-8016-6082ef37744d" + }, + { + "type": 1, + "content": { + "json": "### Thread exposure
\r\n\r\n**De-duplicated Microsoft Teams messages split by whether the conversation includes external participants.**" + }, + "customWidth": "50", + "name": "teams thread header", + "id": "a1a48f9a-8593-4ab5-8824-5998c643e844" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query breaks down Microsoft Teams threat detections by threat type for the selected period, de-duplicated to the latest record per message. A message flagged for more than one threat type is counted under each, so the split can exceed the distinct message count.\r\nlet msgs = MessageEvents | where isnotempty(ThreatTypes) | summarize arg_max(Timestamp, *) by TeamsMessageId;\r\nunion\r\n(msgs | where ThreatTypes has \"Phish\" | summarize Count = count() | extend ThreatType = \"Phish\"),\r\n(msgs | where ThreatTypes has \"Malware\" | summarize Count = count() | extend ThreatType = \"Malware\"),\r\n(msgs | where ThreatTypes has \"Spam\" | summarize Count = count() | extend ThreatType = \"Spam\")\r\n| project ThreatType, Count", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams threat type pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "029b4ecc-cd95-4385-a251-8ab194add8f4" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows de-duplicated Microsoft Teams messages split by whether the thread includes external participants.\r\nMessageEvents\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| extend Thread = iif(IsExternalThread == true, \"External Thread\", \"Internal Thread\")\r\n| summarize Count = count() by Thread", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams thread pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1581f447-9b3e-4857-84b8-e78b5df65ac5" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Overview", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "283f36b2-5c54-4afe-9a87-33d4796bd5b7" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Teams Calls and Vishing (Voice Phishing)\r\n
\r\n\r\n**Voice phishing (vishing) over Microsoft Teams is the fastest-growing collaboration threat of 2026. Attackers impersonate IT help desk or support and call users directly, often after a chat lure, to talk them into granting remote access or entering credentials. Because a target must be online to answer, malicious calls cluster in working hours. This section surfaces Teams call activity, when calls happen, and callers using support or brand-impersonation identities.**

*Interim data source: Teams call activity is currently read from Microsoft Defender for Cloud Apps call telemetry (CloudAppEvents). The existing V4 logic retains this source while the dedicated CallActivityEvents implementation is evaluated separately.*

**Recommended action:** Treat unsolicited help desk or support calls as suspicious. Confirm any request through a known internal channel, and never grant remote access such as Quick Assist on the strength of an inbound Teams call. Restrict inbound calls and chat from unmanaged and consumer tenants." + }, + "customWidth": "100", + "name": "teams calls banner", + "id": "9815bdc9-9e10-4e84-9164-783092b4ccb0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Teams call and vishing headline metrics for the selected period, with per-interval sparklines. Interim source: Defender for Cloud Apps call telemetry (CloudAppEvents / CallParticipantDetail).\r\nlet gran = {Granularity};\r\nlet calls = materialize(CloudAppEvents | where ActionType == \"CallParticipantDetail\" | extend R = parse_json(RawEventData) | extend CallId = tostring(R.CallId), UId = tolower(tostring(R.UserId)));\r\nlet susp = calls | extend Local = tostring(split(UId, \"@\")[0]), Dom = tostring(split(UId, \"@\")[1]) | where Local matches regex @\"(?i)help ?desk|helpdesk|it ?support|service ?desk|sys ?admin|administrator|security|microsoft|google|apple|amazon|paypal|support|update|verif|account|password|mfa|maintenance\" or Dom endswith \".onmicrosoft.com\";\r\nlet reported = CloudAppEvents | where ActionType == \"CallReported\";\r\nunion\r\n(calls | summarize Count = dcount(CallId) | extend Details = \"Teams Calls\", Ord = 1, Trend = toscalar(calls | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(susp | summarize Count = dcount(UId) | extend Details = \"Impersonation-style Callers\", Ord = 2, Trend = toscalar(susp | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(reported | summarize Count = count() | extend Details = \"Reported Suspicious Calls\", Ord = 3, Trend = toscalar(reported | make-series S = count() default = 0 on Timestamp step gran | project S))\r\n| sort by Ord asc\r\n| project Details, Count, Trend", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21 + }, + "showBorder": true, + "size": "auto" + }, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams calls kpi", + "id": "be8946d9-1eae-405c-b8df-cee2242cb44d" + }, + { + "type": 1, + "content": { + "json": "### Teams call activity over time
\r\n**Distinct Microsoft Teams calls per selected interval. A sudden rise, or calls outside normal working hours, can indicate a vishing campaign in progress.**" + }, + "customWidth": "100", + "name": "teams calls trend header", + "id": "1b49c98f-e5d9-457c-b058-a195e89eac0e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Distinct Teams calls per interval (interim source: CloudAppEvents / CallParticipantDetail).\r\nCloudAppEvents\r\n| where ActionType == \"CallParticipantDetail\"\r\n| extend R = parse_json(RawEventData)\r\n| extend CallId = tostring(R.CallId)\r\n| summarize ['Teams Calls'] = dcount(CallId) by Timestamp = bin(Timestamp, {Granularity})\r\n| sort by Timestamp asc", + "size": 0, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "xAxis": "Timestamp", + "seriesLabelSettings": [ + { + "seriesName": "Teams Calls", + "color": "blueDark" + } + ] + }, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams calls trend", + "id": "7538b3ca-b96d-421a-9cdc-69b8aef4b185" + }, + { + "type": 1, + "content": { + "json": "### When calls happen (hour of day, UTC)
\r\n**Microsoft Teams calls by the hour of day they started (UTC), listed 00:00 through 23:00. The bar length is the number of calls that started in that hour across the selected period. Vishing calls cluster in working hours because the target must be online to answer, with the heaviest malicious-call activity between 14:00 and 20:00 UTC, Monday to Friday, according to Microsoft Threat Intelligence. Use this to baseline normal call timing and spot unusual off-hours spikes.**" + }, + "customWidth": "100", + "name": "teams calls hour header", + "id": "6bc095e9-fe0d-4f6f-81bd-f3374d758229" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Teams calls by start hour of day (UTC), all 24 hours 00:00..23:00 in order (interim source: CloudAppEvents / CallParticipantDetail).\r\nlet data = CloudAppEvents\r\n| where ActionType == \"CallParticipantDetail\"\r\n| extend R = parse_json(RawEventData)\r\n| extend JoinTime = todatetime(R.JoinTime), CallId = tostring(R.CallId)\r\n| where isnotempty(JoinTime) and isnotempty(CallId)\r\n| summarize CallStart = min(JoinTime) by CallId\r\n| extend HourUTC = hourofday(CallStart)\r\n| summarize Calls = count() by HourUTC;\r\nrange HourUTC from 0 to 23 step 1\r\n| join kind=leftouter (data) on HourUTC\r\n| extend Calls = coalesce(Calls, 0)\r\n| extend HourLabel = strcat(iif(HourUTC < 10, strcat(\"0\", tostring(HourUTC)), tostring(HourUTC)), \":00\")\r\n| order by HourUTC asc\r\n| project ['Hour of Day (UTC)'] = HourLabel, ['Teams Calls'] = Calls", + "size": 0, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Teams Calls", + "formatter": 3, + "formatOptions": { + "palette": "blueDark", + "customColumnWidthSetting": "360px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams calls hour", + "id": "c36a9909-5570-4fe7-8efc-1b9b4745713a" + }, + { + "type": 1, + "content": { + "json": "### Suspicious callers (support and helpdesk impersonation)
\r\n**Teams call participants whose display name or address looks like IT support, help desk, or a well-known brand (for example \"Microsoft IT support\", \"Help Desk\", \"Office 365 Support\"), or who dial in from a throwaway `.onmicrosoft.com` tenant. Origin shows whether the caller is external, an external throwaway tenant, or inside your own tenant. External and throwaway-tenant callers are the primary vishing risk; own-tenant matches are frequently a legitimate internal help desk and should be confirmed rather than assumed malicious.**

**Recommended action:** Prioritise External and `.onmicrosoft` callers, confirm none are legitimate, and warn the users they called. Genuine IT support does not cold-call staff over Teams to request remote access." + }, + "customWidth": "100", + "name": "teams calls susp header", + "id": "aa420b5f-efd2-4da5-ab41-192031f62ed1" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Suspicious Teams callers by impersonation-style DISPLAY NAME or address (Attendees[].DisplayName / UPN), with Origin from the org's own accepted (EmailEvents inbound) domains - no tenant-id anchor. Interim source: CloudAppEvents / CallParticipantDetail.\r\nlet suspRegex = @\"(?i)help ?desk|helpdesk|it ?support|service ?desk|sys ?admin|administrator|security|microsoft|google|apple|amazon|paypal|support|update|verif|account|password|mfa|maintenance\";\r\nlet ownDomains = toscalar(EmailEvents | where EmailDirection == \"Inbound\" | extend RD = tolower(tostring(split(RecipientEmailAddress, \"@\")[1])) | where isnotempty(RD) | summarize make_set(RD, 200));\r\nlet calls = CloudAppEvents\r\n| where ActionType == \"CallParticipantDetail\"\r\n| extend R = parse_json(RawEventData)\r\n| extend CallId = tostring(R.CallId), JoinTime = todatetime(R.JoinTime), Attendees = R.Attendees\r\n| where isnotempty(CallId);\r\nlet callAtt = calls | summarize Attendees = take_any(Attendees), JoinTime = min(JoinTime) by CallId;\r\ncallAtt\r\n| mv-expand Att = Attendees\r\n| extend Caller = tolower(tostring(Att.UPN)), CallerName = tostring(Att.DisplayName)\r\n| extend CallerDom = tostring(split(Caller, \"@\")[1])\r\n| where isnotempty(Caller)\r\n| extend SuspName = CallerName matches regex suspRegex or Caller matches regex suspRegex\r\n| where SuspName or CallerDom endswith \".onmicrosoft.com\"\r\n| extend Origin = case(CallerDom endswith \".onmicrosoft.com\", \"External (.onmicrosoft throwaway)\", set_has_element(ownDomains, CallerDom), \"Own tenant\", \"External\")\r\n| summarize CallsPlaced = dcount(CallId), FirstSeen = min(JoinTime), LastSeen = max(JoinTime) by CallerName, Caller, Origin\r\n| extend OriginRank = case(Origin == \"External (.onmicrosoft throwaway)\", 0, Origin == \"External\", 1, 2)\r\n| sort by OriginRank asc, CallsPlaced desc\r\n| take 10\r\n| project ['Caller Display Name'] = CallerName, ['Caller Address'] = Caller, ['Origin'] = Origin, ['Calls Placed'] = CallsPlaced, ['First Seen'] = FirstSeen, ['Last Seen'] = LastSeen", + "size": 0, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Calls Placed", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams calls susp table", + "id": "d1c4df7b-db07-4c4c-bc71-dfd8623cd704" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Calls and Vishing", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "1d133411-9b5c-4ede-8502-68b3b02262e4" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Teams Impersonation & Identity Deception\r\n
\r\n\r\nMicrosoft Defender for Office 365 flags Teams messages where a sender impersonates a brand, a specific person, or a trusted domain. Impersonation is the entry point for most Teams social-engineering: attackers pose as IT, executives, or Microsoft to build trust before delivering a malicious link or request. These visuals expose who is being impersonated, who is being targeted, and the infrastructure (display names, look-alike domains, and URLs) behind the campaigns so you can hunt IOCs and coach at-risk users.

**Recommended action:** Treat the impersonated display names and look-alike domains below as IOCs to hunt, and prioritize the Microsoft Defender alert *Microsoft Teams chat initiated by a suspicious external user*. Teach users that a Teams display name is not proof of identity: verify the real sender domain, and confirm any help desk, executive, or Microsoft support request through a known internal channel before acting." + }, + "name": "teams imp banner", + "id": "7ff04ff3-9f2d-4a49-8383-2b542d78fe9b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nunion\r\n(imp | summarize Count=count() | extend Details=\"Impersonation Detections\", Ord=1),\r\n(imp | summarize Count=dcount(FakeSenderAddress) | extend Details=\"Distinct Fake Senders\", Ord=2),\r\n(imp | summarize Count=dcount(TargetUser) | extend Details=\"Targeted Users\", Ord=3),\r\n(imp | summarize Count=dcount(ImpersonationType) | extend Details=\"Impersonation Types\", Ord=4)\r\n| sort by Ord asc | project Count, Details", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e37f94d5-9bcc-432e-aa66-25831603c228" + }, + { + "type": 1, + "content": { + "json": "### Impersonation over time, by type
\r\n\r\n**Trend of Brand, User, and Domain impersonation detections. A spike in a single type often marks the start of a targeted campaign.**" + }, + "customWidth": "100", + "name": "teams imp trend header", + "id": "09907f5b-5c20-4a7e-86d3-c89153c4df98" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp | summarize Count=count() by ImpersonationType, Timestamp=bin(Timestamp, {Granularity}) | sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp trend", + "id": "757204b1-e900-4217-a2ff-2224a033fdcc" + }, + { + "type": 1, + "content": { + "json": "### Suspicious external senders (impersonation and throwaway tenants)
\r\n**External Microsoft Teams senders flagged as likely impersonation: throwaway `.onmicrosoft.com` tenants and/or help desk, IT support, security, admin, or account/update-themed display names. Attackers rotate through many such identities (for example numbered `ithelpdesk@...` addresses) from newly-created or consumer tenants to pose as internal support, frequently before the Defender impersonation detector assigns a verdict. This heuristic complements that detector.**

**Recommended action:** Review high threat-rate senders, block the sending domains, and remind users that genuine IT support does not cold-contact them from an external tenant; verify any such request through a known internal channel." + }, + "customWidth": "100", + "name": "teams susp senders header", + "id": "5df4af86-49e9-4fc7-b6ad-76d3ef3f7da6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//External Teams senders flagged as likely impersonation: throwaway .onmicrosoft.com tenants and/or help desk / IT / admin / update-themed display names, ranked by messages carrying a threat.\r\nMessageEvents\r\n| where IsExternalThread == true\r\n| extend SenderDomain = tolower(tostring(split(SenderEmailAddress, \"@\")[1]))\r\n| extend IsOnMicrosoft = SenderDomain endswith \".onmicrosoft.com\"\r\n| extend SuspName = SenderDisplayName matches regex @\"(?i)help ?desk|helpdesk|it ?support|service ?desk|it team|administrator|sys ?admin|security|microsoft|maintenance|support|update|verif|account|password|mfa\"\r\n| where IsOnMicrosoft or SuspName\r\n| summarize TeamsMessages = count(), ThreatMessages = countif(isnotempty(ThreatTypes)), FirstSeen = min(Timestamp), LastSeen = max(Timestamp) by SenderDisplayName, SenderEmailAddress, SenderDomain, IsOnMicrosoft, SuspName\r\n| extend WhyFlagged = case(IsOnMicrosoft and SuspName, \"Throwaway .onmicrosoft tenant + helpdesk-style name\", IsOnMicrosoft, \"Throwaway .onmicrosoft tenant\", \"Helpdesk / IT-style display name\")\r\n| extend ThreatPct = round(todouble(ThreatMessages) * 100 / TeamsMessages, 1)\r\n| project ['Sender Display Name']=SenderDisplayName, ['Sender Address']=SenderEmailAddress, ['Why Flagged']=WhyFlagged, ['Teams Messages']=TeamsMessages, ['Threat Messages']=ThreatMessages, ['Threat %']=ThreatPct, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen\r\n| sort by ['Threat Messages'] desc, ['Teams Messages'] desc\r\n| take 10", + "size": 0, + "title": "", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Teams Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Threat %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 100 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "showAnalytics": true, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams susp senders table", + "id": "dd1d79d8-f591-4aae-bd44-6ad23a3e0ae4" + }, + { + "type": 1, + "content": { + "json": "### Who is being targeted
\r\n\r\n**Internal users receiving the most impersonation attempts. Concentrated targeting of a few users is a strong signal of a deliberate campaign - prioritize these users for security awareness training.**" + }, + "customWidth": "100", + "name": "teams imp targets header", + "id": "43112ad1-ebc9-42fb-9ebd-0dbaa862ed45" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp | summarize Detections=count(), ['Distinct Fake Senders']=dcount(FakeSenderAddress), Types=make_set(ImpersonationType,3), ['Last Seen']=max(Timestamp) by ['Targeted User']=TargetUser | top 10 by Detections", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp targets", + "id": "cc4b3f98-bfcb-4741-9abb-9ff099eb946f" + }, + { + "type": 1, + "content": { + "json": "### Impersonating senders
\r\n\r\n**The identities behind the impersonation, grouped by fake display name, sender domain, and type. Attackers rotate through many sending addresses under a single display name - Distinct Sender Addresses exposes that rotation, and a high count is itself a strong bulk-campaign signal. Use First/Last Seen to scope the campaign window.**" + }, + "customWidth": "100", + "name": "teams imp senders header", + "id": "99859796-7b69-42e7-a27a-541e0ba86cb2" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the identities behind Teams impersonation, grouped by the fake display name, sender domain, and impersonation type. Attackers rotate through many sending addresses under one display name, so Distinct Sender Addresses reveals bulk campaigns that per-address ranking would hide.\r\nlet imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp\r\n| summarize Detections=count(), SenderAddresses=dcount(FakeSenderAddress), Targets=dcount(TargetUser), FirstSeen=min(Timestamp), LastSeen=max(Timestamp) by FakeDisplayName, FakeSenderDomain, ImpersonationType\r\n| top 10 by Detections\r\n| project ['Fake Display Name']=FakeDisplayName, ['Sender Domain']=FakeSenderDomain, ['Impersonation Type']=ImpersonationType, ['Distinct Sender Addresses']=SenderAddresses, Detections, ['Targeted Users']=Targets, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Distinct Sender Addresses", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp senders", + "id": "209439a0-5be3-4e41-abe9-695552730dc8" + }, + { + "type": 1, + "content": { + "json": "### Display names abused
\r\n\r\n**The identities attackers pretend to be (for example \"IT HelpDesk\", \"Microsoft Support\"). These are the trust anchors of the social-engineering lure.**" + }, + "customWidth": "100", + "name": "teams imp names header", + "id": "e645578b-7a52-4d38-9d83-f5c500bbfe1a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp | summarize Detections=count(), ['Targeted Users']=dcount(TargetUser), ['Distinct Senders']=dcount(FakeSenderAddress) by ['Fake Display Name']=FakeDisplayName | top 10 by Detections", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Distinct Senders", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp names", + "id": "d723d72b-4e7c-431b-ae7b-980879c8bd75" + }, + { + "type": 1, + "content": { + "json": "### Look-alike sender domains
\r\n\r\n**Sending domains used for impersonation - watch for typosquats (for example rnicrosoft.com for m→rn). Add confirmed domains to your Tenant Allow/Block List.**" + }, + "customWidth": "100", + "name": "teams imp domains header", + "id": "98040a5a-bbd5-4c95-b976-5630ce48b282" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp | summarize Detections=count(), ['Targeted Users']=dcount(TargetUser), ['Display Names Used']=dcount(FakeDisplayName) by ['Sender Domain']=FakeSenderDomain | top 10 by Detections", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Display Names Used", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp domains", + "id": "94b9fa45-c889-46a7-8b80-92e5d280ad3b" + }, + { + "type": 1, + "content": { + "json": "### URL IOCs from impersonation messages
\r\n\r\n**URL domains that appeared in messages sent by impersonating senders. Threat actors deliberately mix legitimate domains (for example microsoft.com or google.com) with their malicious ones to make the lure look trustworthy, so treat this as a review list - not a blocklist. Investigate the unfamiliar or look-alike domains and block only those you confirm malicious; never block a well-known legitimate domain from this list.**" + }, + "customWidth": "100", + "name": "teams imp ioc header", + "id": "d5f4886c-7c7e-4c6f-94ca-569cabda5ede" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists URL domains that appeared in messages sent by impersonating senders, with a breakdown of how many carried Malware, Phish, or Spam verdicts. Threat actors mix legitimate and malicious domains in a single lure, so review the unfamiliar or look-alike domains and block only confirmed-malicious ones.\r\nlet imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ChatThreadId = tostring(RD.ChatThreadId);\r\nlet impThreads = imp | distinct ChatThreadId;\r\nlet impMsgs = MessageEvents\r\n | where ThreadId in (impThreads)\r\n | summarize arg_max(Timestamp, *) by TeamsMessageId\r\n | project TeamsMessageId, ThreatTypes;\r\nMessageUrlInfo\r\n| where isnotempty(UrlDomain)\r\n| join kind=inner (impMsgs) on TeamsMessageId\r\n| summarize ['URL Count']=count(), Messages=dcount(TeamsMessageId), Malware=countif(ThreatTypes has \"Malware\"), Phish=countif(ThreatTypes has \"Phish\"), Spam=countif(ThreatTypes has \"Spam\") by ['URL Domain']=UrlDomain\r\n| top 10 by ['URL Count']", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "URL Count", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Malware", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Phish", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Spam", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams imp ioc", + "id": "958ac65c-d56d-4a80-ba83-2ab33e8b1e2e" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Impersonation", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "c49582db-6318-423f-b806-91cbeb625ea2" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Malicious URLs and Link Warnings in Teams\r\n
\r\n\r\nTracks URLs shared through Microsoft Teams, messages that triggered a Microsoft Defender for Office 365 URL safety-tip warning, and the outcome of Teams URL clicks (allowed versus blocked) captured in UrlClickEvents.

**Recommended action:** Enable Safe Links for Microsoft Teams so links are checked at click time, and prioritize *User clicked a malicious link in Teams chat* alerts for investigation. Treat a blocked click as an attempted compromise: check whether the user went on to share credentials or run a file, and reset credentials where warranted." + }, + "name": "teams url banner", + "id": "e3ec4d65-8d1f-4303-bd8f-eb1ae521da41" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query surfaces Microsoft Teams URL-sharing and link-warning metrics for the selected period. URL-warning messages carry the Microsoft Defender for Office 365 URL safety tip.\r\nlet msgs = materialize(MessageEvents | summarize arg_max(Timestamp, *) by TeamsMessageId);\r\nunion\r\n(msgs | where SafetyTip == \"URLMessageWarning\" | summarize Count = count() | extend Details = \"Messages with URL Warning\", Ord = 1),\r\n(MessageUrlInfo | summarize Count = count() | extend Details = \"URLs Shared in Messages\", Ord = 2),\r\n(MessageUrlInfo | summarize Count = dcount(TeamsMessageId) | extend Details = \"Messages Containing URLs\", Ord = 3),\r\n(MessageUrlInfo | summarize Count = dcount(UrlDomain) | extend Details = \"Distinct URL Domains\", Ord = 4)\r\n| sort by Ord asc\r\n| project Count, Details", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams url tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b71382c7-c0f7-4f9d-9d21-e0a8bf9504ff" + }, + { + "type": 1, + "content": { + "json": "### Teams URL click outcomes over time
\r\n\r\n**Allowed versus blocked Microsoft Teams URL clicks (per selected interval) from UrlClickEvents where the click happened in the Teams workload.**" + }, + "customWidth": "66", + "name": "teams click trend header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "30818e0d-6c4b-4868-896a-ac48cb3cef86" + }, + { + "type": 1, + "content": { + "json": "### Click outcomes
\r\n\r\n**Distribution of Microsoft Teams URL click actions by type.**" + }, + "customWidth": "33", + "name": "teams click pie header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "5a882138-2241-4527-80b8-9983c5807050" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Microsoft Teams URL click outcomes over time (allowed vs blocked) using the UrlClickEvents workload filter, summarizing the data per selected interval.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(UrlClickEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(UrlClickEvents | summarize max(Timestamp));\r\nlet agg = materialize(UrlClickEvents\r\n| where Workload == \"Teams\"\r\n| summarize ClickAllowed = countif(ActionType has \"ClickAllowed\"), ClickBlocked = countif(ActionType has \"ClickBlocked\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ClickAllowed = coalesce(ClickAllowed, 0), ClickBlocked = coalesce(ClickBlocked, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "teams click trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "7a2f5559-1e3e-412a-addf-c3bf6be98502" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows Microsoft Teams URL click outcomes by action type for the selected period.\r\nUrlClickEvents\r\n| where Workload == \"Teams\"\r\n| where isnotempty(ActionType)\r\n| summarize Count = count() by ActionType", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "teams click pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "889c6bb3-438b-4575-84f2-084c1b5fd1f4" + }, + { + "type": 1, + "content": { + "json": "### Top domains shared in Teams messages
\r\n\r\n**The 10 most-shared URL domains in Microsoft Teams messages, with the number of messages each appeared in.**" + }, + "customWidth": "100", + "name": "teams top domains header", + "id": "dcb8c87c-087e-4d69-b7b7-0329296293ff" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 URL domains shared in Microsoft Teams messages by volume for the selected period.\r\nMessageUrlInfo\r\n| where isnotempty(UrlDomain)\r\n| summarize UrlCount = count(), Messages = dcount(TeamsMessageId) by UrlDomain\r\n| top 10 by UrlCount\r\n| project ['URL Domain']=UrlDomain, ['URLs Shared']=UrlCount, ['Messages']=Messages", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "URLs Shared", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams top domains table", + "id": "7561adb0-1fbe-41ce-a924-a27bcd4c5c12" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Malicious URLs", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "6d47c309-be9e-4b21-940e-7c7b282e5dc2" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Targeted Users & Risky Senders\r\n
\r\n\r\nIdentifies who is most targeted in Microsoft Teams, and profiles the external senders and domains behind risky messages - URL safety-tip warnings, first-contact senders, threat-carrying domains, and low-reputation link infrastructure - so you can spot anomalous senders before they succeed.

**Recommended action:** Prioritize the most-targeted users for phishing-resistant MFA and awareness coaching, and treat first-contact external senders and low-reputation domains as IOCs. Restrict inbound chat from unmanaged and consumer tenants, and allowlist only trusted external domains so unsolicited outsiders cannot start a conversation." + }, + "name": "teams risky banner", + "id": "0aa13d73-2e13-487c-a7c4-d90464a554d4" + }, + { + "type": 1, + "content": { + "json": "### Top targeted users (messages with threats)
\r\n\r\n**The 10 users receiving the most Microsoft Teams messages that contained a threat, expanded from each message recipient list.**" + }, + "customWidth": "100", + "name": "teams targeted header", + "id": "827dc0f6-2bb2-49b9-acf8-d7b400238594" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 users receiving Microsoft Teams messages that contained a threat, expanded from the message recipient list, with each user's total Teams messages received and the share that carried a threat. Messages are de-duplicated to the latest record per message.\r\nlet expanded = MessageEvents\r\n | summarize arg_max(Timestamp, *) by TeamsMessageId\r\n | mv-expand rd = parse_json(RecipientDetails)\r\n | extend Recipient = tostring(rd.RecipientSmtpAddress)\r\n | where isnotempty(Recipient);\r\nlet totals = expanded | summarize TotalMessages = count() by Recipient;\r\nexpanded\r\n| where isnotempty(ThreatTypes)\r\n| summarize ThreatMessages = count() by Recipient\r\n| join kind=leftouter (totals) on Recipient\r\n| extend ThreatPct = round(100.0 * ThreatMessages / TotalMessages, 1)\r\n| top 10 by ThreatMessages\r\n| project ['Recipient']=Recipient, ['Threat Messages']=ThreatMessages, ['Total Messages']=TotalMessages, ['Threat %']=ThreatPct", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams targeted users table", + "id": "79481d1b-617e-46df-b555-9f7240932dd0" + }, + { + "type": 1, + "content": { + "json": "### Top senders of URL-warning messages
\r\n\r\n**Senders whose Microsoft Teams messages most often triggered a URL safety-tip warning.**" + }, + "customWidth": "50", + "name": "teams warn senders header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "ef71d7dd-4442-4992-977d-d550aad4533c" + }, + { + "type": 1, + "content": { + "json": "### Top domains in URL-warning messages
\r\n\r\n**URL domains most frequently present in Microsoft Teams messages that triggered a URL safety-tip warning.**" + }, + "customWidth": "50", + "name": "teams warn domains header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "6f41a4ba-f832-4947-ad27-cd6b8015bd63" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 senders whose Microsoft Teams messages triggered a URL safety-tip warning for the selected period, with each sender's total Teams messages and the share that carried a warning. Messages are de-duplicated to the latest record per message.\r\nlet dedup = MessageEvents | summarize arg_max(Timestamp, *) by TeamsMessageId;\r\nlet totals = dedup | summarize TotalMessages = count() by SenderEmailAddress;\r\ndedup\r\n| where SafetyTip == \"URLMessageWarning\"\r\n| summarize WarningMessages = count() by SenderEmailAddress\r\n| join kind=leftouter (totals) on SenderEmailAddress\r\n| extend WarningPct = round(100.0 * WarningMessages / TotalMessages, 1)\r\n| top 10 by WarningMessages\r\n| project ['Sender']=SenderEmailAddress, ['Warning Messages']=WarningMessages, ['Total Messages']=TotalMessages, ['Warning %']=WarningPct", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Warning Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams warn senders table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3fa023af-79e3-407f-ac20-b0aa6e3ba511" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 URL domains appearing in Microsoft Teams messages that triggered a URL safety-tip warning, with the domain's total message appearances and the share that carried a warning.\r\nlet warned = MessageEvents | where SafetyTip == \"URLMessageWarning\" | distinct TeamsMessageId;\r\nlet totals = MessageUrlInfo | where isnotempty(UrlDomain) | summarize TotalMessages = dcount(TeamsMessageId) by UrlDomain;\r\nMessageUrlInfo\r\n| where TeamsMessageId in (warned)\r\n| summarize WarningMessages = dcount(TeamsMessageId) by UrlDomain\r\n| join kind=leftouter (totals) on UrlDomain\r\n| extend WarningPct = round(100.0 * WarningMessages / TotalMessages, 1)\r\n| top 10 by WarningMessages\r\n| project ['URL Domain']=UrlDomain, ['Warning Messages']=WarningMessages, ['Total Messages']=TotalMessages, ['Warning %']=WarningPct", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Warning Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams warn domains table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "68811015-1383-48ad-86da-4f8f9d39e4c4" + }, + { + "type": 1, + "content": { + "json": "### First-contact external senders
\r\n\r\n**External Microsoft Teams senders ordered by when they were first seen in the period (most recent first). Note: some flows tag internal-domain senders as external - to hide your own tenant domains, edit the query and uncomment the ExcludeDomains filter.**" + }, + "customWidth": "100", + "name": "teams fc senders header", + "id": "0f131ff3-d6b2-4187-b86c-ca3493594b54" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists external Microsoft Teams senders by the date they were first seen in the selected period, surfacing recent first-contact senders. Messages are de-duplicated to the latest record per message. In tenants with longer history this highlights genuinely new senders.\r\n// TIP: IsExternalThread may still surface senders from your own accepted domains. To hide them,\r\n// uncomment the ExcludeDomains line below (add your tenant domains) and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"contoso.com\"]);\r\nMessageEvents\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| where IsExternalThread == true\r\n//| where tostring(split(SenderEmailAddress, \"@\")[1]) !in~ (ExcludeDomains)\r\n| summarize FirstSeen = min(Timestamp), Messages = count(), ThreatMessages = countif(isnotempty(ThreatTypes)) by SenderEmailAddress\r\n| top 10 by FirstSeen desc\r\n| project ['Sender']=SenderEmailAddress, ['First Seen']=FirstSeen, ['Messages']=Messages, ['Threat Messages']=ThreatMessages", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true, + "sortBy": [ + { + "itemKey": "Threat Messages", + "sortOrder": 2 + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams fc senders table", + "id": "4e10a78d-8858-4dbb-9db0-e7b7d7e7636c" + }, + { + "type": 1, + "content": { + "json": "### External sender-domain risk
\r\n\r\n**External sending domains ranked by threat volume, with the mix of conversation types (1:1 chat, group chat, channel), threat breakdown, threat rate, count of messages carrying low-reputation URLs (domains on commonly-abused TLDs such as .xyz, .top, .click, .shop, .zip), and first/last-seen. A domain that is new in the period, skews toward 1:1 chats, or shows a high threat rate is anomalous and warrants review. Note: to exclude your own tenant domains, edit the query and uncomment the ExcludeDomains filter.**" + }, + "customWidth": "100", + "name": "teams anomaly header", + "id": "a91295db-8192-4828-93c5-408436e4b0e1" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query ranks external sender domains in Microsoft Teams by threat volume for the selected period, split by conversation type (1:1 chat, group chat, channel), with threat-type breakdown, threat rate, and a count of messages carrying low-reputation URL TLDs. Messages are de-duplicated to the latest record per message. New, 1:1-skewed, or high-threat-rate domains are the anomalies to review.\r\n// TIP: IsExternalThread may still surface your own accepted domains. To hide them, uncomment the\r\n// ExcludeDomains line below (add your tenant domains) and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"contoso.com\"]);\r\nlet suspTlds = dynamic([\"top\",\"xyz\",\"click\",\"link\",\"shop\",\"online\",\"site\",\"live\",\"icu\",\"cyou\",\"sbs\",\"rest\",\"quest\",\"cfd\",\"bond\",\"buzz\",\"fun\",\"space\",\"monster\",\"work\",\"tk\",\"ml\",\"ga\",\"cf\",\"gq\",\"dev\",\"app\",\"zip\",\"mov\",\"info\",\"win\",\"loan\",\"men\",\"stream\",\"country\"]);\r\nlet suspUrlMsgs = MessageUrlInfo\r\n | where isnotempty(UrlDomain)\r\n | extend Tld = tostring(split(UrlDomain, \".\")[-1])\r\n | where Tld in (suspTlds)\r\n | distinct TeamsMessageId;\r\nMessageEvents\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| where IsExternalThread == true\r\n| extend SenderDomain = tostring(split(SenderEmailAddress, \"@\")[1])\r\n| where isnotempty(SenderDomain)\r\n//| where SenderDomain !in~ (ExcludeDomains)\r\n| extend ConvType = case(isnotempty(GroupId), \"Channel\", array_length(todynamic(RecipientDetails)) > 1, \"Group chat\", \"1:1 chat\")\r\n| extend HasSuspUrl = TeamsMessageId in (suspUrlMsgs)\r\n| summarize Messages=count(), Senders=dcount(SenderEmailAddress), OneToOne=countif(ConvType==\"1:1 chat\"), GroupChat=countif(ConvType==\"Group chat\"), ChannelMsgs=countif(ConvType==\"Channel\"), ThreatMessages=countif(isnotempty(ThreatTypes)), Malware=countif(ThreatTypes has \"Malware\"), Phish=countif(ThreatTypes has \"Phish\"), Spam=countif(ThreatTypes has \"Spam\"), SuspUrlMsgs=countif(HasSuspUrl), FirstSeen=min(Timestamp), LastSeen=max(Timestamp) by SenderDomain\r\n| where ThreatMessages > 0\r\n| extend ThreatRatePct = round(100.0 * ThreatMessages / Messages, 1)\r\n| top 10 by ThreatMessages desc\r\n| project ['Sender Domain']=SenderDomain, Messages, Senders, ['1:1']=OneToOne, ['Group']=GroupChat, ['Channel']=ChannelMsgs, ['Threat Msgs']=ThreatMessages, Malware, Phish, Spam, ['Threat Rate %']=ThreatRatePct, ['Low-Rep URL Msgs']=SuspUrlMsgs, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Threat Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams anomaly table", + "id": "bcd6746d-8298-495d-9d6c-2fadc6cba569" + }, + { + "type": 1, + "content": { + "json": "### Suspicious new senders (no threat verdict yet)
\r\n\r\n**External sending domains with no threat verdict yet, but that are either sending low-reputation-URL messages or showing unusual volume. These slip past threat filters - watch for new domains skewing toward 1:1 chats, an early social-engineering signal. Note: to exclude your own tenant domains, edit the query and uncomment the ExcludeDomains filter.**" + }, + "customWidth": "100", + "name": "teams newdom header", + "id": "9e3844f4-befc-4b76-a8cd-ca53fdf51d41" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query surfaces external sender domains in Microsoft Teams that have NO threat verdict yet but are sending messages with low-reputation URL TLDs or unusual volume, split by conversation type. These are early-warning senders that have not tripped a detection. Messages are de-duplicated to the latest record per message.\r\n// TIP: IsExternalThread may still surface your own accepted domains. To hide them, uncomment the\r\n// ExcludeDomains line below (add your tenant domains) and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"contoso.com\"]);\r\nlet suspTlds = dynamic([\"top\",\"xyz\",\"click\",\"link\",\"shop\",\"online\",\"site\",\"live\",\"icu\",\"cyou\",\"sbs\",\"rest\",\"quest\",\"cfd\",\"bond\",\"buzz\",\"fun\",\"space\",\"monster\",\"work\",\"tk\",\"ml\",\"ga\",\"cf\",\"gq\",\"dev\",\"app\",\"zip\",\"mov\",\"info\",\"win\",\"loan\",\"men\",\"stream\",\"country\"]);\r\nlet suspUrlMsgs = MessageUrlInfo\r\n | where isnotempty(UrlDomain)\r\n | extend Tld = tostring(split(UrlDomain, \".\")[-1])\r\n | where Tld in (suspTlds)\r\n | distinct TeamsMessageId;\r\nMessageEvents\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| where IsExternalThread == true\r\n| extend SenderDomain = tostring(split(SenderEmailAddress, \"@\")[1])\r\n| where isnotempty(SenderDomain)\r\n//| where SenderDomain !in~ (ExcludeDomains)\r\n| extend ConvType = case(isnotempty(GroupId), \"Channel\", array_length(todynamic(RecipientDetails)) > 1, \"Group chat\", \"1:1 chat\")\r\n| extend HasSuspUrl = TeamsMessageId in (suspUrlMsgs)\r\n| summarize Messages=count(), Senders=dcount(SenderEmailAddress), OneToOne=countif(ConvType==\"1:1 chat\"), GroupChat=countif(ConvType==\"Group chat\"), ChannelMsgs=countif(ConvType==\"Channel\"), ThreatMessages=countif(isnotempty(ThreatTypes)), SuspUrlMsgs=countif(HasSuspUrl), FirstSeen=min(Timestamp), LastSeen=max(Timestamp) by SenderDomain\r\n| where ThreatMessages == 0\r\n| where SuspUrlMsgs > 0 or Messages >= 5\r\n| order by SuspUrlMsgs desc, Messages desc\r\n| take 10\r\n| project ['Sender Domain']=SenderDomain, Messages, Senders, ['1:1']=OneToOne, ['Group']=GroupChat, ['Channel']=ChannelMsgs, ['Low-Rep URL Msgs']=SuspUrlMsgs, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams newdom table", + "id": "8036a5b7-b5b3-4af4-912f-bb092bb01b89" + }, + { + "type": 1, + "content": { + "json": "### Low-reputation link domains in Teams (IOC radar)
\r\n\r\n**URL domains shared in Teams that use TLDs commonly abused for phishing and malware (for example .xyz, .top, .click, .zip, .shop). Ranked by message reach, with first/last-seen. Review these domains as potential indicators - .zip and .mov are especially deceptive because links read like file names.**" + }, + "customWidth": "100", + "name": "teams tld header", + "id": "d48921f4-233c-4e0f-a97b-83e1bcaed399" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists URL domains shared in Microsoft Teams that use low-reputation TLDs commonly abused for phishing and malware, ranked by the number of Teams messages they appeared in, with first- and last-seen. Treat high-reach or newly-seen domains as candidate indicators of compromise.\r\nlet suspTlds = dynamic([\"top\",\"xyz\",\"click\",\"link\",\"shop\",\"online\",\"site\",\"live\",\"icu\",\"cyou\",\"sbs\",\"rest\",\"quest\",\"cfd\",\"bond\",\"buzz\",\"fun\",\"space\",\"monster\",\"work\",\"tk\",\"ml\",\"ga\",\"cf\",\"gq\",\"dev\",\"app\",\"zip\",\"mov\",\"info\",\"win\",\"loan\",\"men\",\"stream\",\"country\"]);\r\nMessageUrlInfo\r\n| where isnotempty(UrlDomain)\r\n| extend Tld = tostring(split(UrlDomain, \".\")[-1])\r\n| where Tld in (suspTlds)\r\n| summarize Messages=dcount(TeamsMessageId), FirstSeen=min(Timestamp), LastSeen=max(Timestamp) by ['URL Domain']=UrlDomain, ['TLD']=Tld\r\n| top 10 by Messages desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams tld table", + "id": "30d5588e-010c-474a-9c53-74b73dcc9676" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Targeted Users & Risky Senders", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "6fef737b-cb4e-4a51-9ced-bf11754a6b33" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Teams File Protection\r\n
\r\n\r\nMicrosoft Defender for Office 365 scans files shared in Microsoft Teams. These visuals show files scanned versus malware detected, and list the malicious files found.

**Recommended action:** Investigate each malicious file below and confirm it was quarantined and removed from the SharePoint or OneDrive location backing the chat. Enable Safe Attachments for SharePoint, OneDrive, and Microsoft Teams, and use attack surface reduction rules to block executable content delivered through collaboration." + }, + "name": "teams file banner", + "id": "2f01c905-dd65-4a13-9f67-c70402b2c175" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query summarizes Microsoft Teams file protection by Microsoft Defender for Office 365 - files scanned, files with malware detected, and files scanned with no detection - for the selected period.\r\nlet base = FileMaliciousContentInfo | where Workload == \"MicrosoftTeams\";\r\nunion\r\n(base | summarize Count = count() | extend Details = \"Teams Files Scanned\", Ord = 1),\r\n(base | where isnotempty(ThreatTypes) | summarize Count = count() | extend Details = \"Files with Malware Detected\", Ord = 2),\r\n(base | where isempty(ThreatTypes) | summarize Count = count() | extend Details = \"Files Scanned - No Detection\", Ord = 3)\r\n| sort by Ord asc\r\n| project Count, Details", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams file tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "9f555c51-1680-47ef-94d4-b1f8cf9dce3b" + }, + { + "type": 1, + "content": { + "json": "### Malicious files shared in Teams
\r\n\r\n**Files shared in Microsoft Teams that were detected with malware, with owner and file details.**" + }, + "customWidth": "100", + "name": "teams file table header", + "id": "4cd3274e-0c61-4722-83b7-1fccf8a94a57" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists Microsoft Teams files detected with malware by Microsoft Defender for Office 365 for the selected period.\r\nFileMaliciousContentInfo\r\n| where Workload == \"MicrosoftTeams\"\r\n| where isnotempty(ThreatTypes)\r\n| top 10 by Timestamp desc\r\n| project ['Time']=Timestamp, ['File Name']=FileName, ['Threat Type']=tostring(ThreatTypes), ['Threat Names']=ThreatNames, ['File Location']=FolderPath, ['File Owner']=FileOwnerUpn, SHA256", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams file table", + "id": "135e0e7d-7110-40ee-a377-1a5992b2ef9d" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams File Protection", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "8ecc1bae-4a06-4b1c-8952-59fb434b7cbc" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Post-Delivery ZAP Insights (Teams)\r\n
\r\n\r\nZero-hour auto purge (ZAP) removes malicious Microsoft Teams messages after delivery. These visuals summarize ZAP volume, type, result, and the senders whose messages were most often removed.

**Recommended action:** Confirm zero-hour auto purge is enabled for Microsoft Teams so newly-weaponized messages are pulled after delivery. Investigate senders with repeated ZAP removals as likely compromised or malicious accounts and block or restrict them. A rising ZAP trend can signal an active campaign that slipped past delivery-time filtering." + }, + "name": "teams zap banner", + "id": "136cfb4e-d2a5-4db0-9771-6b6380011ba0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query summarizes Microsoft Teams post-delivery ZAP (zero-hour auto purge) activity by Microsoft Defender for Office 365 for the selected period.\r\nlet zap = materialize(MessagePostDeliveryEvents);\r\nunion\r\n(zap | summarize Count = count() | extend Details = \"Total ZAP Actions\", Ord = 1),\r\n(zap | where ActionType == \"Malware ZAP\" | summarize Count = count() | extend Details = \"Malware ZAP\", Ord = 2),\r\n(zap | where ActionType == \"Phish ZAP\" | summarize Count = count() | extend Details = \"Phish ZAP\", Ord = 3),\r\n(zap | where ActionResult == \"Success\" | summarize Count = count() | extend Details = \"Successful Actions\", Ord = 4),\r\n(zap | where ActionResult == \"Failed\" | summarize Count = count() | extend Details = \"Failed Actions\", Ord = 5),\r\n(zap | where Action == \"Moved to quarantine\" | summarize Count = count() | extend Details = \"Moved to Quarantine\", Ord = 6)\r\n| sort by Ord asc\r\n| project Count, Details", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams zap tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "06980411-5e6b-4aa4-a746-351cd2b12dae" + }, + { + "type": 1, + "content": { + "json": "### ZAP actions over time
\r\n\r\n**Microsoft Teams post-delivery ZAP actions (per selected interval) split by Malware ZAP and Phish ZAP.**" + }, + "customWidth": "66", + "name": "teams zap trend header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "7fc1cfcd-3a9f-45b1-9f39-3820fce23c03" + }, + { + "type": 1, + "content": { + "json": "### ZAP by action type
\r\n\r\n**Distribution of Microsoft Teams post-delivery ZAP actions by type.**" + }, + "customWidth": "33", + "name": "teams zap pie header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "9bc0d0a3-876a-49d7-9046-31764511ca38" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Microsoft Teams post-delivery ZAP actions over time by ZAP type, summarizing the data per selected interval.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(MessagePostDeliveryEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(MessagePostDeliveryEvents | summarize max(Timestamp));\r\nlet agg = materialize(MessagePostDeliveryEvents\r\n| summarize MalwareZAP = countif(ActionType == \"Malware ZAP\"), PhishZAP = countif(ActionType == \"Phish ZAP\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, MalwareZAP = coalesce(MalwareZAP, 0), PhishZAP = coalesce(PhishZAP, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "teams zap trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "c78a509e-324f-4a8c-b2e7-bce3e0d20667" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows Microsoft Teams post-delivery ZAP actions by type for the selected period.\r\nMessagePostDeliveryEvents\r\n| summarize Count = count() by ActionType", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "teams zap pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "cfc94695-fb02-4b6c-a223-f79f7b947379" + }, + { + "type": 1, + "content": { + "json": "### Top senders whose messages were removed by ZAP
\r\n\r\n**Senders whose Microsoft Teams messages were most often removed by post-delivery ZAP.**" + }, + "customWidth": "100", + "name": "teams zap senders header", + "id": "f8677ffe-007a-41ca-81de-1ae5dd19d06a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 senders whose Microsoft Teams messages were removed by post-delivery ZAP for the selected period.\r\nMessagePostDeliveryEvents\r\n| where isnotempty(SenderEmailAddress)\r\n| summarize ZapActions = count(), MalwareZAP = countif(ActionType == \"Malware ZAP\"), PhishZAP = countif(ActionType == \"Phish ZAP\") by SenderEmailAddress\r\n| top 10 by ZapActions\r\n| project ['Sender']=SenderEmailAddress, ['ZAP Actions']=ZapActions, ['Malware ZAP']=MalwareZAP, ['Phish ZAP']=PhishZAP", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "ZAP Actions", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams zap senders table", + "id": "50c9a883-6442-40dc-b84f-57adfbb46a38" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams ZAP", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "f5cc2425-e5ae-4520-9a97-2e4c2c447dcd" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Teams Message and Call Submissions\r\n
\r\n\r\nMicrosoft Teams messages and calls reported by users, and messages submitted by admins, for review by Microsoft. Sourced from the submission records in CloudAppEvents.

**Recommended action:** Encourage users to report suspicious Teams messages and calls so Microsoft can tune protection, and triage admin submissions promptly. A cluster of reports naming the same sender, display name, or call identity is an early signal of a targeted campaign: pivot those identities into the impersonation and risky-sender views above to scope it." + }, + "name": "teams sub banner", + "id": "54cbfb29-2626-4b65-8cb5-a42ff4b41e63" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query summarizes Microsoft Teams message and call submissions reported to Microsoft for the selected period, split by user and admin reports. Only completed submissions are counted (submission triage/timeout lifecycle records are excluded).\r\nlet sub = materialize(CloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType in (\"ChatMessage\", \"TeamsCall\"));\r\nunion\r\n(sub | where SubmissionContentType == \"ChatMessage\" and ActionType == \"UserSubmission\" | summarize Count = count() | extend Details = \"Messages Reported by Users\", Ord = 1),\r\n(sub | where SubmissionContentType == \"TeamsCall\" and ActionType == \"UserSubmission\" | summarize Count = count() | extend Details = \"Calls Reported by Users\", Ord = 2),\r\n(sub | where SubmissionContentType == \"ChatMessage\" and ActionType == \"AdminSubmission\" | summarize Count = count() | extend Details = \"Messages Submitted by Admins\", Ord = 3)\r\n| sort by Ord asc\r\n| project Count, Details", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "secondaryContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "showBorder": true, + "size": "full" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams sub tiles", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "419ed645-ebc1-4df1-b9f0-c744403ab494" + }, + { + "type": 1, + "content": { + "json": "### Submissions over time
\r\n\r\n**Microsoft Teams user and admin submissions (per selected interval).**" + }, + "customWidth": "66", + "name": "teams sub trend header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "6a795b0a-82e2-427a-8ac0-abfb5bb5e447" + }, + { + "type": 1, + "content": { + "json": "### Submission mix
\r\n\r\n**Microsoft Teams submissions split by content type (message or call) and reporter (user or admin).**" + }, + "customWidth": "33", + "name": "teams sub pie header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "1f4c55f8-7290-4b6f-b02a-e3134568b9ff" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises Microsoft Teams message and call submissions over time, summarizing the data per selected interval. Only completed submissions are counted (submission triage/timeout lifecycle records are excluded).\r\nlet gran = {Granularity};\r\nlet sub = materialize(CloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType in (\"ChatMessage\", \"TeamsCall\"));\r\nlet minTime = toscalar(sub | summarize min(Timestamp));\r\nlet maxTime = toscalar(sub | summarize max(Timestamp));\r\nlet agg = materialize(sub\r\n| summarize UserReports = countif(ActionType == \"UserSubmission\"), AdminReports = countif(ActionType == \"AdminSubmission\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, UserReports = coalesce(UserReports, 0), AdminReports = coalesce(AdminReports, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "teams sub trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "7dcb03da-de96-4388-90a4-0a3f3ca98dc6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows the mix of Microsoft Teams submissions by content type and reporter for the selected period. Only completed user submissions (chat and call) and admin submissions (chat) are counted; submission triage/timeout lifecycle records are excluded.\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\"\r\n| where (SubmissionContentType == \"ChatMessage\" and ActionType == \"UserSubmission\")\r\n or (SubmissionContentType == \"TeamsCall\" and ActionType == \"UserSubmission\")\r\n or (SubmissionContentType == \"ChatMessage\" and ActionType == \"AdminSubmission\")\r\n| extend Reporter = iif(ActionType == \"AdminSubmission\", \"Admin\", \"User\")\r\n| summarize Count = count() by SubmissionType = strcat(SubmissionContentType, \" (\", Reporter, \")\")", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "teams sub pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "84a0141e-51de-4423-acb0-3c4342a49bf2" + }, + { + "type": 1, + "content": { + "json": "### False Negative (FN) User Submissions by submission State
\r\n\r\n**Microsoft Teams messages reported by users as missed detections, broken down by submission state (for example Rescaned, Graded). Tracks the processing status of user reports.**" + }, + "customWidth": "50", + "name": "teams sub state header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "1b2bdffd-69b0-41b0-bdda-b242b7faaec0" + }, + { + "type": 1, + "content": { + "json": "### False Negative (FN) User Submissions by Triage Verdict
\r\n\r\n**Microsoft Teams user submissions grouped by the verdict assigned during grading (for example Phishing, NotSpam, Spam). Shows how reported messages were graded and highlights detection gaps.**" + }, + "customWidth": "50", + "name": "teams sub verdict header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "bdb97e09-44d2-41ad-a99f-931e4a8169cc" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows Microsoft Teams user (false negative) message submissions by submission state (for example Rescaned, Graded), to track processing status.\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend SubmissionState = tostring(RD.SubmissionState)\r\n| summarize Count = count() by tostring(SubmissionState)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub state pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "139ce840-5fc2-44d1-9872-91b37a74f0e7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows Microsoft Teams user (false negative) message submissions by the triage verdict assigned during grading (for example Phishing, NotSpam, Spam).\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend TriageVerdict = tostring(parse_json(tostring(RD.GradingResult)).TriageVerdict)\r\n| where isnotempty(TriageVerdict)\r\n| summarize Count = count() by TriageVerdict", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub verdict pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "538ce4a3-a1ff-4b8d-a466-2173edbb2cd7" + }, + { + "type": 1, + "content": { + "json": "### Top 10 P2 sender domains in FN User Submissions
\r\n\r\n**The sender domains most often reported by users as missed Microsoft Teams threats. High-volume domains are candidate sources of malicious messaging.**" + }, + "customWidth": "50", + "name": "teams sub domains header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "9b8db0c7-2bf2-4077-ae20-60146001bf23" + }, + { + "type": 1, + "content": { + "json": "### Top 10 individual P2 senders in FN User Submissions
\r\n\r\n**The individual senders most often reported by users as missed Microsoft Teams threats.**" + }, + "customWidth": "50", + "name": "teams sub senders header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "ffbe90ab-129c-47fa-9dac-50cab528ad55" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 P2 (envelope) sender domains of Microsoft Teams messages reported by users as false negatives (missed detections).\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend P2SenderDomain = tostring(RD.P2SenderDomain)\r\n| where isnotempty(P2SenderDomain)\r\n| summarize Submissions = count() by ['P2 Sender Domain']=P2SenderDomain\r\n| top 10 by Submissions", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub domains table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b18192fb-26a8-4bd1-9b07-7aeab496eae3" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 individual P2 (envelope) senders of Microsoft Teams messages reported by users as false negatives (missed detections).\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend P2Sender = tostring(RD.P2Sender)\r\n| where isnotempty(P2Sender)\r\n| summarize Submissions = count() by ['P2 Sender']=P2Sender\r\n| top 10 by Submissions", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub senders table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "7ead0a01-2b56-4225-b625-554b09350013" + }, + { + "type": 1, + "content": { + "json": "### Top 10 users performing the most FN User Submissions
\r\n\r\n**The users who report the most Microsoft Teams messages as missed detections - useful for recognising engaged reporters and spotting over-reporting.**" + }, + "customWidth": "50", + "name": "teams sub topusers header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "fb893cdd-d6d3-431a-a1d2-87652571a10d" + }, + { + "type": 1, + "content": { + "json": "### Top 10 admins performing the most FN Admin Submissions
\r\n\r\n**The admins who submit the most Microsoft Teams messages as missed detections.**" + }, + "customWidth": "50", + "name": "teams sub topadmins header", + "styleSettings": { + "margin": "10px", + "padding": "0px" + }, + "id": "14fca69b-e152-4a5d-bd2c-020c34c2226a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 users who reported the most Microsoft Teams messages as false negatives (missed detections), with each submitter's email (from the submission record) to disambiguate users with similar names.\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend Submitter = tostring(RD.SubmitterDisplayName), SubmitterEmail = tostring(RD.UserId)\r\n| where isnotempty(Submitter) and SubmitterEmail has \"@\"\r\n| summarize Submissions = count() by ['Submitter']=Submitter, ['Email']=SubmitterEmail\r\n| top 10 by Submissions", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub topusers table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a171a35b-35b0-46ce-a916-052a54101126" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the top 10 admins who submitted the most Microsoft Teams messages as false negatives (missed detections). The admin's own email is not present in the submission record (that would require the Identity table), so the Submitter ID (object GUID) is shown to disambiguate admins with similar names.\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"AdminSubmission\"\r\n| extend Submitter = tostring(RD.SubmitterDisplayName), SubmitterId = tostring(RD.SubmitterId)\r\n| where isnotempty(Submitter)\r\n| summarize Submissions = count() by ['Admin']=Submitter, ['Submitter ID']=SubmitterId\r\n| top 10 by Submissions", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "teams sub topadmins table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8bf37c2b-067a-4341-a192-2aa45699c3f7" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Submissions", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "eeea53a4-69d9-426e-bf9f-1789cd73bfed" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Recent Threat Detail\r\n
\r\n\r\nThe most recent Microsoft Teams phishing and malware messages, de-duplicated to the latest record per message, for investigation." + }, + "name": "teams detail banner", + "id": "4bdd917c-721f-450b-b455-45cbd5f59cc5" + }, + { + "type": 1, + "content": { + "json": "### Last 10 Teams phishing messages
\r\n\r\n**Most recent Microsoft Teams messages detected as phishing, with sender, delivery action, safety tip, team/group, and subject. TeamsMessageId is included to pivot to Advanced Hunting.**" + }, + "customWidth": "100", + "name": "teams detail phish header", + "id": "9bcf96c1-a958-4515-b171-10ec2f3ba660" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the 10 most recent Microsoft Teams messages detected as phishing by Microsoft Defender for Office 365, de-duplicated to the latest record per message. TeamsMessageId is included so analysts can pivot to Advanced Hunting.\r\nMessageEvents\r\n| where ThreatTypes has \"Phish\"\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| top 10 by Timestamp desc\r\n| project ['Time']=Timestamp, ['Sender']=SenderEmailAddress, ['Threat Types']=ThreatTypes, ['Delivery Action']=DeliveryAction, ['Safety Tip']=SafetyTip, ['Team / Group']=GroupName, ['External Thread']=IsExternalThread, ['Subject']=MessageSubject, TeamsMessageId", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams detail phish table", + "id": "3675d08f-1165-4f47-a633-e432cf96e3d5" + }, + { + "type": 1, + "content": { + "json": "### Last 10 Teams malware messages
\r\n\r\n**Most recent Microsoft Teams messages detected as malware, with sender, delivery action, safety tip, team/group, and subject. TeamsMessageId is included to pivot to Advanced Hunting.**" + }, + "customWidth": "100", + "name": "teams detail mal header", + "id": "6b9d66d2-8d89-47b0-a72a-5ee8623082dc" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists the 10 most recent Microsoft Teams messages detected as malware by Microsoft Defender for Office 365, de-duplicated to the latest record per message. TeamsMessageId is included so analysts can pivot to Advanced Hunting.\r\nMessageEvents\r\n| where ThreatTypes has \"Malware\"\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| top 10 by Timestamp desc\r\n| project ['Time']=Timestamp, ['Sender']=SenderEmailAddress, ['Threat Types']=ThreatTypes, ['Delivery Action']=DeliveryAction, ['Safety Tip']=SafetyTip, ['Team / Group']=GroupName, ['External Thread']=IsExternalThread, ['Subject']=MessageSubject, TeamsMessageId", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "teams detail mal table", + "id": "d6e76d0a-7eee-4c05-8e92-10f9622b5ab3" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "14" + }, + "name": "group - Teams Detail", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "1e9c879b-d6be-4d36-9068-b5438abf7dd2" + }, + { + "type": 1, + "content": { + "json": "# Top Attacked Users, Top Senders, and Automatic External Email Forwarding\r\n\r\n---\r\nThis tab provides insights into **Top attacked users, Top Senders** in inbound email messages and details about **automatic external email forwarding**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "6" + }, + "name": "text - 24 - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f1a60054-44b1-432e-be7a-9d7d114ff5c7" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Top Attacked Users and Top Senders Insights\r\n
\r\n\r\nThis section provides key visuals that highlight top attacked users – individuals most frequently targeted by inbound email threats as detected by Microsoft Defender for Office 365. Offers insights into top email senders and sender domains across inbound email traffic, helping identify patterns and potential risk sources.

**Recommended action:** Apply the Strict preset to the most-attacked users and review the top sender domains as possible block-list candidates." + }, + "name": "text - 13 - Copy - Copy", + "id": "ff220902-30b8-4aef-9b79-14c913a1b2d2" + }, + { + "type": 1, + "content": { + "json": "### Top Attacked Users
\r\n\r\n**Displays the top 10 recipient email addresses that received inbound emails flagged as Spam, Phishing, or Malware. Helps identify high-risk users for targeted security awareness and policy enforcement.**" + }, + "name": "text - 13 - Copy - Copy - Copy", + "id": "58f34b9f-824d-4fcf-b2aa-d7d380aa08d5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 users that are receiving Spam, Phishing or Malware emails\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\" and EmailDirection ==\"Inbound\"\r\n| extend MDO_detection = parse_json(DetectionMethods) \r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),MalwareEmailCount = countif(FirstDetection == \"Malware\"),PhishEmailCount = countif(FirstDetection == \"Phish\"),SpamEmailCount = countif(FirstDetection == \"Spam\") by RecipientEmailAddress\r\n| extend ThreatEmailCount=(MalwareEmailCount+PhishEmailCount+SpamEmailCount)\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(ThreatEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| top 15 by ThreatEmailCount\r\n| project ['Recipient']=RecipientEmailAddress, ['Total Emails']=TotalEmailCount, ['Threat Emails']=ThreatEmailCount, ['Malware']=MalwareEmailCount, ['Phish']=PhishEmailCount, ['Spam']=SpamEmailCount, ['Bad Traffic %']=Bad_Traffic_Percentage_Inbound", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Threat Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Malware", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spam", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + } + } + ], + "filter": true, + "sortBy": [ + { + "itemKey": "$gen_bar_Threat Emails_2", + "sortOrder": 2 + } + ] + }, + "sortBy": [ + { + "itemKey": "$gen_bar_Threat Emails_2", + "sortOrder": 2 + } + ], + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 28", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e9459e78-6b43-4ef2-9596-32169d95c610" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Senders of Inbound Emails
\r\n\r\n**Displays the top 10 sender email addresses from external sources delivering inbound emails. Helps identify high-volume external senders for monitoring and policy enforcement.**" + }, + "name": "text - 13 - Copy - Copy - Copy - Copy", + "id": "eb4590a7-57c7-4728-af62-3d798afe6f2d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 senders by inbound email sending volume\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\" and EmailDirection ==\"Inbound\"\r\n| extend MDO_detection = parse_json(DetectionMethods) \r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),MalwareEmailCount = countif(FirstDetection == \"Malware\"),PhishEmailCount = countif(FirstDetection == \"Phish\"),SpamEmailCount = countif(FirstDetection == \"Spam\") by SenderFromAddress\r\n| extend ThreatEmailCount=(MalwareEmailCount+PhishEmailCount+SpamEmailCount)\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(ThreatEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| top 15 by TotalEmailCount\r\n| project ['Sender']=SenderFromAddress, ['Total Emails']=TotalEmailCount, ['Threat Emails']=ThreatEmailCount, ['Malware']=MalwareEmailCount, ['Phish']=PhishEmailCount, ['Spam']=SpamEmailCount, ['Bad Traffic %']=Bad_Traffic_Percentage_Inbound", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Threat Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Malware", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spam", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + } + } + ], + "filter": true + }, + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 28 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e4272979-1073-4c1e-9b1b-b971bc3efc33" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains of Inbound Emails
\r\n\r\n**Displays the top 10 sender domains from external sources delivering inbound emails. Helps identify high-volume external sender domains for monitoring and policy enforcement.**" + }, + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "id": "7ab63415-17ce-47f1-a614-e5e6edbe472e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 senders by inbound email sending volume\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\" and EmailDirection ==\"Inbound\"\r\n| extend MDO_detection = parse_json(DetectionMethods) \r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),MalwareEmailCount = countif(FirstDetection == \"Malware\"),PhishEmailCount = countif(FirstDetection == \"Phish\"),SpamEmailCount = countif(FirstDetection == \"Spam\") by SenderFromDomain\r\n| extend ThreatEmailCount=(MalwareEmailCount+PhishEmailCount+SpamEmailCount)\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(ThreatEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| top 15 by TotalEmailCount\r\n| project ['Sender Domain']=SenderFromDomain, ['Total Emails']=TotalEmailCount, ['Threat Emails']=ThreatEmailCount, ['Malware']=MalwareEmailCount, ['Phish']=PhishEmailCount, ['Spam']=SpamEmailCount, ['Bad Traffic %']=Bad_Traffic_Percentage_Inbound", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Threat Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Malware", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spam", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Bad Traffic %", + "formatter": 4, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + } + } + ], + "filter": true + }, + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 28 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b593da94-b735-4fe3-a82d-18c90156e506" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "6" + }, + "name": "group - 10-Top attacked users and top senders", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "3e41cc1a-166e-4094-bc66-7e26a918b2e9" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Automatic External Email Forwarding Insights\r\n
\r\n\r\n**Email forwarding can be useful, but can also pose a security risk due to the potential disclosure of information.**\r\n
\r\n\r\nUsers can configure [Inbox rules](https://support.microsoft.com/en-US/Outlook/mail/use-rules-to-automatically-forward-messages) in Outlook or set up [SMTP forwarding](https://support.microsoft.com/en-us/office/turn-on-automatic-forwarding-in-outlook-7f2670a1-7fff-4475-8a3c-5822d63b0c8e) to automatically forward messages to external recipients. You can control automatic external email forwarding from cloud mailboxes using [Outbound spam policies](https://learn.microsoft.com/en-us/defender-office-365/outbound-spam-policies-external-email-forwarding) in Microsoft Defender for Office 365. \r\n**Attackers might exploit this capability to compromise your organization or its partners.**

**Recommended action:** Investigate external auto-forwarding - it is a common data-exfiltration path. Consider disabling auto-forwarding via the outbound spam policy unless a business case is documented." + }, + "name": "text - 8", + "id": "b04d1590-98e3-4650-9172-33e75561e1e5" + }, + { + "type": 1, + "content": { + "json": "### Automatic Email Forwarding by Type
\r\n\r\n**Displays counts of outbound emails automatically forwarded to external addresses, grouped by forwarding type (e.g., SMTP forwarding, inbox rules). Helps identify forwarding behaviors that may pose data exfiltration risks.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "c7cb7917-eaf4-4a1e-989a-75f4b6182851" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Internal Users Forwarding Emails Externally
\r\n\r\n**Displays the top 10 internal user accounts that have automatically forwarded emails to external addresses (regardless of the forwarding type used). Helps identify potential data exfiltration risks and enforce forwarding policies.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5a5d5a8c-c195-45db-a878-e6ac908cc919" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises automatic email forwarding to external email addresses by forwarding type\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| summarize count() by ForwardingType\r\n| sort by count_ desc \r\n", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "15094d98-add2-4b50-a0df-ee91fd34c6fb" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 internal senders who are automatically forwarding emails to external email addresses\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| summarize TotalForwardedMessages = count() by ForwardingUser\r\n| sort by TotalForwardedMessages desc \r\n| top 10 by TotalForwardedMessages\r\n| project ['Forwarding User']=ForwardingUser, ['Forwarded Messages']=TotalForwardedMessages\r\n\r\n", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "TotalForwardedMessages" + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "73d66038-2ea0-449d-9aeb-a1bd4b207d7f" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Internal Users Forwarding Emails Using Mailbox Rules
\r\n\r\n**Displays the top 10 internal user accounts that have automatically forwarded outbound emails to external addresses using Mailbox Rules. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "9a7b5fc3-da23-4e95-87df-542a5e3f6320" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 internal senders who are automatically forwarding emails to external email addresses using Mailbox Rules\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| where ForwardingType ==\"MbxRule\"\r\n| summarize TotalForwardedMessages = count() by ForwardingUser\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Forwarding User']=ForwardingUser, ['Forwarded Messages']=TotalForwardedMessages", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "TotalForwardedMessages" + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 30 - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f8d7b85d-944a-493f-a143-7e18277846c9" + }, + { + "type": 1, + "content": { + "json": "### Top 10 External domains Receiving Auto-Forwarded Emails (Mailbox Rules)
\r\n\r\n**Displays the top 10 external recipient email domains that received automatically forwarded emails from internal users via Mailbox Rules. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "cda99a50-b7c4-4d95-ac61-7231080a3f5d" + }, + { + "type": 1, + "content": { + "json": "### Top 10 External Recipients Receiving Auto-Forwarded Emails (Mailbox Rules)
\r\n\r\n**Displays the top 10 external recipient email addresses that received automatically forwarded emails from internal users via Mailbox Rules. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "72b01575-c33e-457c-98db-ea755c003bf0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 external domains who are recieving automatically forwarded emails using Mailbox Rules\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser),RecipientDomain = tostring(split(RecipientEmailAddress, \"@\")[1])\r\n| where ForwardingType ==\"MbxRule\"\r\n| summarize TotalForwardedMessages = count() by RecipientDomain\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Recipient Domain']=RecipientDomain, ['Forwarded Messages']=TotalForwardedMessages", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "823dec28-48b5-4be3-8e68-04301a952a62" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 external recipients who are recieving automatically forwarded emails using Mailbox Rules\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| where ForwardingType ==\"MbxRule\"\r\n| summarize TotalForwardedMessages = count() by RecipientEmailAddress\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Recipient']=RecipientEmailAddress, ['Forwarded Messages']=TotalForwardedMessages", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "14804990-bfc9-43b7-8c8d-95c2cf32ee56" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Internal Users Forwarding Emails via SMTP Forwarding
\r\n\r\n**Displays the top 10 internal user accounts that have automatically forwarded outbound emails to external addresses using SMTP Forwarding. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "100", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "fa04b313-5756-4ff7-9ee8-ec61e6b382cc" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 internal senders who are automatically forwarding emails to external email addresses using SmtpForwarding\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| where ForwardingType ==\"SmtpForwarding\"\r\n| summarize count() by ForwardingUser\r\n| top 10 by count_ desc\r\n| project ['Forwarding User']=ForwardingUser, ['Forwarded Messages']=count_", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 30 - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "bed8e717-4ea7-4f71-aaa7-b70a31f4dc88" + }, + { + "type": 1, + "content": { + "json": "### Top 10 External domains receiving Auto-Forwarded Emails (SMTP Forwarding)
\r\n\r\n**Displays the top 10 external recipient email domains that received automatically forwarded emails from internal users using SMTP Forwarding. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "f76bc717-3cf8-4d8d-92fa-3f2024065f8f" + }, + { + "type": 1, + "content": { + "json": "### Top 10 External Recipients Receiving Auto-Forwarded Emails (SMTP Forwarding)
\r\n\r\n**Displays the top 10 external recipient email addresses that received automatically forwarded emails from internal users using SMTP Forwarding. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" + }, + "customWidth": "50", + "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "2190c799-ab4f-4bd8-87e1-f9c5c224cca4" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 external recipients who are recieving automatically forwarded emails using SmtpForwarding\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser),RecipientDomain = tostring(split(RecipientEmailAddress, \"@\")[1])\r\n| where ForwardingType ==\"SmtpForwarding\"\r\n| summarize TotalForwardedMessages = count() by RecipientDomain\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Recipient Domain']=RecipientDomain, ['Forwarded Messages']=TotalForwardedMessages", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "c3be87b3-8ce8-40f2-ad92-0651bed71117" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// This query visualises the top 10 external recipients who are recieving automatically forwarded emails using SmtpForwarding\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| where ForwardingType ==\"SmtpForwarding\"\r\n| summarize TotalForwardedMessages = count() by RecipientEmailAddress\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Recipient']=RecipientEmailAddress, ['Forwarded Messages']=TotalForwardedMessages", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Forwarded Messages", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "chartSettings": { + "yAxis": [ + "count_" + ], + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 30 - Copy - Copy - Copy - Copy - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "fb6b0113-f5bb-46a7-994b-92ebc3c7881d" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "6" + }, + "name": "group - 34 - Automatic email forwarding", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "02c91ebb-4f92-4843-a73b-6dea7a6ac2bd" + }, + { + "type": 1, + "content": { + "json": "# Email detection action overrides\r\n\r\n---\r\n\r\nThis tab provides insights into admin or end-user configured **detection overrides** where the message was detected as a threat by Microsoft Defender for Office 365, however an admin-configured policy or end-user setting overrode the detection action.[

Learn more

](https://learn.microsoft.com/en-us/defender-office-365/step-by-step-guides/understand-overrides-in-email-entity) " + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "text - 13 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "ae594968-00b9-40b8-b5dd-052a27440afb" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Admin configured Detection Overrides (Allow)\r\n
\r\n\r\nThis section consolidates key visuals that track emails subject to administrator policies (e.g., Transport Rules, Tenant Allow/Block List) with an \"Allow\" action, overriding Microsoft Defender for Office 365 detections (excluding SecOps Mailbox overrides).

**Recommended action:** Review Allow overrides that later carried threats and remove stale or overly broad allow entries - they weaken protection." + }, + "name": "text - AdminOverridesAllowHeader", + "id": "3d70a304-c590-4156-a6d4-da147fe106ab" + }, + { + "type": 1, + "content": { + "json": "### Admin Overrides (Allow) Trend\r\n**Displays the count (per {Granularity}) of emails where an administrator policy with an \"Allow\" action overrode detections (excluding SecOps Mailbox). Helps track the frequency of admin overrides over time.**" + }, + "name": "text - AdminOverridesAllowTrend", + "id": "a4ee104a-a0a1-4725-a60f-deedcc91af70" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to an admin policy with action of allow independent of action taken, summarizing the data daily\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where isnotempty(OrgLevelPolicy) and OrgLevelPolicy!=\"SecOps Mailbox\" and OrgLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalAdminOverrides = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Admin Overrides'] = coalesce(TotalAdminOverrides, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Admin Overrides", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 3", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "79928e9e-48ed-4d08-8ff7-c21fe027550e" + }, + { + "type": 1, + "content": { + "json": "### Total Emails by Admin Override type (Allow)\r\n**Summarizes the total count of emails subject to administrator policies with an \"Allow\" action, grouped by the type of override. Helps identify which policies are most frequently allowing emails.**" + }, + "customWidth": "50", + "name": "text - AdminOverridesAllowByType", + "id": "855fce09-2000-4d16-8521-8b4eeddfae00" + }, + { + "type": 1, + "content": { + "json": "### Admin Overrides (Allow) by Override Type and Threat Type\r\n**Details the count of emails allowed by administrator policies, categorized by the override type and the detected threat type. Helps assess the risk associated with allowed emails.**" + }, + "customWidth": "50", + "name": "text - AdminOverridesAllowByTypeAndThreat", + "id": "a2613078-b427-4b23-aca0-21989b1944db" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails subject to an admin policy with action of allow, independent of action taken, summarizing the data by type of override\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelPolicy!=\"SecOps Mailbox\" and OrgLevelAction == \"Allow\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by OrgLevelPolicy", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 16", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b21a0329-8f52-45c2-81f2-6df65c134673" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to an admin policy with action of allow, independent of action taken, summarizing the data by type of override and threats type found\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelPolicy!=\"SecOps Mailbox\" and OrgLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by OrgLevelAction,OrgLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=OrgLevelAction, ['Override Policy']=OrgLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 2", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "0bf4cbe6-7c84-49d4-801c-d955762b5699" + }, + { + "type": 1, + "content": { + "json": "### SecOps Mailbox Overrides (Allow)\r\nThis section focuses on emails allowed specifically due to the SecOps Mailbox override policy, typically used for investigation and analysis.[

Learn more

](https://learn.microsoft.com/en-us/defender-office-365/advanced-delivery-policy-configure) " + }, + "name": "text - SecOpsOverridesHeader", + "id": "f582dc86-4c40-4cdd-ba0b-ec6ef8820a27" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails subject to the \r\nEmailEvents \r\n| where OrgLevelPolicy==\"SecOps Mailbox\" and OrgLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by OrgLevelPolicy", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "statSettings": { + "valueAggregation": "None", + "colorSettings": { + "type": "static", + "mode": "background", + "heatmapPalette": "greenRed", + "thresholdsGrid": [] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "tagText": "", + "valueFontStyle": "auto", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 1", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8ad2fea4-dcd0-454e-a4d4-b5275c86fd9b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails delivered to the SecOps Mailbox by threat type\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelPolicy==\"SecOps Mailbox\" and OrgLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by OrgLevelAction,OrgLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=OrgLevelAction, ['Override Policy']=OrgLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", + "size": 1, + "showAnalytics": true, + "title": " ", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 4", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "52c04df2-69b5-46e4-a000-7c6d212a132a" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "group - 15 - Admin Detection Overrides - Allow", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "9b9baf2f-fd5f-41b6-8368-b515f8de4fd4" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Admin configured Detection Overrides (Block)\r\n
\r\n\r\nThis section provides insights into email messages blocked by administrative policies (e.g. Tenant allow/block list, Antimalware policy file type block), overriding detection actions defined by Microsoft Defender for Office 365.

**Recommended action:** Confirm these blocks are still needed and consolidate them into the Tenant Allow/Block List where appropriate." + }, + "name": "text - AdminOverridesBlockHeader", + "id": "6157683b-cce7-4165-886f-0da73e25ce86" + }, + { + "type": 1, + "content": { + "json": "### Admin Overrides (Block) Trend\r\n**Displays the count (per {Granularity}) of emails where an administrator policy with a \"Block\" action overrode detections. Helps track the frequency of admin blocks over time.**" + }, + "name": "text - AdminOverridesBlockTrend", + "id": "699820b4-a984-45cc-ab2f-607c3c8569d4" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to an admin policy with action of block, summarizing the data daily\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where isnotempty(OrgLevelPolicy) and OrgLevelAction == \"Block\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalAdminOverrides = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Admin Overrides'] = coalesce(TotalAdminOverrides, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Admin Overrides", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 5", + "styleSettings": { + "margin": "10", + "padding": "10" + }, + "id": "9ef5e7fb-843e-439b-b4f3-9b0bb149e74b" + }, + { + "type": 1, + "content": { + "json": "### Total Emails by Admin Override Type (Block)\r\n**Summarizes the total count of emails subject to administrator policies with a \"Block\" action, grouped by the type of override.**" + }, + "customWidth": "50", + "name": "text - AdminOverridesBlockByType", + "id": "5694a7c0-1ee5-40b4-ae2b-263d189c4b4e" + }, + { + "type": 1, + "content": { + "json": "### Admin Overrides (Block) by Override Type and Threat Type\r\n**Details the count of emails blocked by administrator policies, categorized by the override type and the detected threat type.**" + }, + "customWidth": "50", + "name": "text - AdminOverridesBlockByTypeAndThreat", + "id": "6e309742-37c0-4ad5-9b9a-63643059bfaf" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails subject to an admin policy with action of block, summarizing the data by type of override\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelAction == \"Block\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by OrgLevelPolicy", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 6", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "eabc80ed-d0e9-43d2-ab13-a5af478f11c8" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to an admin policy with action of block, summarizing the data by type of override and threats type found\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelAction == \"Block\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by OrgLevelAction,OrgLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=OrgLevelAction, ['Override Policy']=OrgLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 7", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1661bfa6-d8fd-4387-a334-1bc027a3f6d1" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "group - 36-Admin Detection Overrides - Block", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "7d514e9a-f67f-45a6-ba1b-6492348cc18b" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
User configured Detection Overrides (Allow)\r\n
\r\n\r\nThis section consolidates key visuals that track email messages subject to user policies (e.g. [Safe Senders list defined in Outlook](https://learn.microsoft.com/en-us/defender-office-365/create-safe-sender-lists-in-office-365#use-outlook-safe-senders)) with an \"Allow\" action, overriding Microsoft Defender for Office 365 detections.

**Recommended action:** Educate users that safe-sender allows can bypass protection; review high-risk user allow entries." + }, + "name": "text - UserOverridesAllowHeader", + "id": "4d41c560-0e73-40c5-b610-33e9500e88c4" + }, + { + "type": 1, + "content": { + "json": "### User Overrides (Allow) Trend\r\n**Displays the count (per {Granularity}) of emails where a user policy with an \"Allow\" action overrode detections. Helps track the frequency of user overrides over time.**" + }, + "name": "text - UserOverridesAllowTrend", + "id": "9432efff-9f03-4d74-8781-02be8b2d07fa" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to a user type policy with action of allow, summarizing the data daily\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalUserOverrides = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['User Overrides'] = coalesce(TotalUserOverrides, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "User Overrides", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "query - 3", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "02da1d33-e477-479d-bdd3-95ab1ad7c75c" + }, + { + "type": 1, + "content": { + "json": "### Total Emails by User Override Type (Allow)\r\n**Summarizes the total count of emails subject to user policies with an \"Allow\" action, grouped by the type of override.**" + }, + "customWidth": "50", + "name": "text - UserOverridesAllowByType", + "id": "006a2e87-b1b6-4cc3-a763-ceebaa86b340" + }, + { + "type": 1, + "content": { + "json": "### User Overrides (Allow) by Override Type and Threat Type\r\n**Details the count of emails allowed by user policies, categorized by the override type and the detected threat type. Helps assess the risk associated with user-allowed emails.**" + }, + "customWidth": "50", + "name": "text - UserOverridesAllowByTypeAndThreat", + "id": "7c34bb4b-46c0-4054-9596-3dfd010bb036" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails subject to a user type policy with action of allow, summarizing the data by type of override\r\nEmailEvents \r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Allow\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by UserLevelPolicy", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 16", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d1d9021d-e6bf-47b1-bdd2-438a212d2767" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to a user type policy with action of allow, summarizing the data by type of override and threats type found\r\nEmailEvents \r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Allow\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by UserLevelAction,UserLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=UserLevelAction, ['Override Policy']=UserLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "sortBy": [], + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 2", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "1acd913c-c945-4a58-b04e-d008ca53ffe3" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "group - 15 - User Detection Overrides - Allow", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "c939060e-6a8b-49ff-951b-a3abddbd9fb4" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
User configured Detection Overrides (Block)\r\n
\r\n\r\nThis section provides insights into emails blocked by user-configured policies (e.g., [Blocked Senders list in Outlook](https://support.microsoft.com/en-us/office/block-or-unblock-senders-in-outlook-9bf812d4-6995-4d19-901a-76d6e26939b0)).

**Recommended action:** Use user block trends to identify unwanted senders that may warrant tenant-wide blocking." + }, + "name": "text - UserOverridesBlockHeader", + "id": "be6c6a3e-08ee-47c5-b8e7-6a1078dd17d1" + }, + { + "type": 1, + "content": { + "json": "### User Overrides (Block) Trend\r\n**Displays the count (per {Granularity}) of emails where a user policy with a \"Block\" action overrode detections. Helps track the frequency of user blocks over time.**" + }, + "name": "text - UserOverridesBlockTrend", + "id": "7cd77d54-2e2b-4d23-a6a9-4bd6bca2642a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to a user type policy with action of block, summarizing the data daily\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Block\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalUserOverrides = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['User Overrides'] = coalesce(TotalUserOverrides, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "User Overrides", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "query - 5", + "styleSettings": { + "margin": "10", + "padding": "10" + }, + "id": "0b21b66c-001d-4b3d-b47f-f3a420ccaaf8" + }, + { + "type": 1, + "content": { + "json": "### Total Emails by User Override Type (Block)\r\n**Summarizes the total count of emails subject to user policies with a \"Block\" action, grouped by the type of override.**" + }, + "customWidth": "50", + "name": "text - UserOverridesBlockByType", + "id": "fd513501-5e9d-45d9-9d0d-cd546002b8cf" + }, + { + "type": 1, + "content": { + "json": "### User Overrides (Block) by Override Type and Threat Type\r\n**Details the count of emails blocked by user policies, categorized by the override type and the detected threat type.**" + }, + "customWidth": "50", + "name": "text - UserOverridesBlockByTypeAndThreat", + "id": "4fbfa876-47ed-4c3b-81ee-1c40b982cecd" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of emails subject to a user type policy with action of block, summarizing the data by type of override\r\nEmailEvents \r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Block\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by UserLevelPolicy", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 6", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d3fccaa6-80fd-419d-bb37-aedf67263419" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails subject to a user type policy with action of block, summarizing the data by type of override and threats type found\r\nEmailEvents \r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Block\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by UserLevelAction,UserLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=UserLevelAction, ['Override Policy']=UserLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Total Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "query - 7", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e5e74ce1-fa67-45ea-bc80-97237342e370" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "group - 37-User Detection Overrides - Block", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "0c1d327a-c2f1-4b9b-b210-53c808b53b48" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
User & Sender Override Detail (Allow)\r\n
\r\n\r\nInbound messages that Microsoft Defender for Office 365 **detected as threats but delivered anyway** because of an admin- or user-configured **Allow** override (phishing-simulation and SecOps Mailbox traffic excluded). **Total Threats** is all detected threats to that recipient / sender domain in the selected range; **Overridden Threats** and **Override %** are the portion delivered due to an Allow override, and **Override Types** names the specific overrides responsible. **User-configured** overrides come from the recipient's own mailbox junk-email settings in Outlook / Outlook on the web (the mailbox \"safelist collection\") — the **Safe Senders** and **Safe Recipients** lists and **trusted contacts** (\"Also trust email from my Contacts\"). **Admin-configured** overrides come from the **Tenant Allow/Block List, Exchange mail flow (transport) rules, the IP Allow List, or allowed sender/domain lists in anti-spam policies**. Use this to spot users or domains where overrides are letting threats through — candidates for policy review or a Tenant Allow/Block List (TABL) block.

**Recommended action:** Focus on the users and sender domains with the most allow overrides - these are the biggest protection gaps." + }, + "name": "Overrides - User Detail Header", + "id": "3b0e83f3-f340-4b95-85c5-831783e8abc2" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top recipients receiving threats that were delivered due to an admin or user override, with the share of their threats that were overridden and a breakdown of which override types caused them.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend OverrideType = case(\r\n OrgLevelAction == \"Allow\" and OrgLevelPolicy != \"\" and OrgLevelPolicy != \"SecOps Mailbox\", OrgLevelPolicy,\r\n UserLevelAction == \"Allow\", strcat(\"User: \", UserLevelPolicy),\r\n \"(none)\")\r\n| summarize PerType = count() by RecipientEmailAddress, OverrideType\r\n| summarize TotalThreats = sum(PerType),\r\n OverriddenThreats = sumif(PerType, OverrideType != \"(none)\"),\r\n OverrideTypes = strcat_array(make_set_if(strcat(OverrideType, \" (\", PerType, \")\"), OverrideType != \"(none)\"), \"; \")\r\n by RecipientEmailAddress\r\n| where OverriddenThreats > 0\r\n| extend OverridePercent = round(OverriddenThreats * 100.0 / TotalThreats, 1)\r\n| top 15 by OverriddenThreats\r\n| project ['Recipient']=RecipientEmailAddress, ['Total Threats']=TotalThreats, ['Overridden Threats']=OverriddenThreats, ['Override %']=OverridePercent, ['Override Types']=OverrideTypes", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Overridden Threats", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Override %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ] + }, + "graphSettings": { + "type": 2, + "topContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Value", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + }, + "nodeIdField": "StatisticName", + "sourceIdField": "Value", + "targetIdField": "Value", + "graphOrientation": 3, + "showOrientationToggles": false, + "nodeSize": null, + "staticNodeSize": 100, + "colorSettings": null, + "hivesMargin": 5, + "edgeColorSettings": null + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "Overrides - Top Users", + "id": "d7e169a2-808a-4bbf-86ee-5be561c690f7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top sender domains sending threats to users, with the share of those threats that were delivered because of an admin or user override and a breakdown of which override types caused them. High override rates are strong candidates for policy review or a Tenant Allow/Block List (TABL) block.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend OverrideType = case(\r\n OrgLevelAction == \"Allow\" and OrgLevelPolicy != \"\" and OrgLevelPolicy != \"SecOps Mailbox\", OrgLevelPolicy,\r\n UserLevelAction == \"Allow\", strcat(\"User: \", UserLevelPolicy),\r\n \"(none)\")\r\n| summarize PerType = count() by SenderFromDomain, OverrideType\r\n| summarize TotalThreats = sum(PerType),\r\n OverriddenThreats = sumif(PerType, OverrideType != \"(none)\"),\r\n OverrideTypes = strcat_array(make_set_if(strcat(OverrideType, \" (\", PerType, \")\"), OverrideType != \"(none)\"), \"; \")\r\n by SenderFromDomain\r\n| where OverriddenThreats > 0\r\n| extend OverridePercent = round(OverriddenThreats * 100.0 / TotalThreats, 1)\r\n| top 10 by OverriddenThreats\r\n| project ['Sender Domain']=SenderFromDomain, ['Total Threats']=TotalThreats, ['Overridden Threats']=OverriddenThreats, ['Override %']=OverridePercent, ['Override Types']=OverrideTypes", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Overridden Threats", + "formatter": 3, + "formatOptions": { + "palette": "redDark" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Override %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ] + }, + "graphSettings": { + "type": 2, + "topContent": { + "columnMatch": "StatisticName", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Value", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + }, + "nodeIdField": "StatisticName", + "sourceIdField": "Value", + "targetIdField": "Value", + "graphOrientation": 3, + "showOrientationToggles": false, + "nodeSize": null, + "staticNodeSize": 100, + "colorSettings": null, + "hivesMargin": 5, + "edgeColorSettings": null + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "Overrides - Top Sender Domains", + "id": "0eda3153-10ea-4d4e-80ca-7e5ad99e9883" + } + ] + }, + "customWidth": "100", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "7" + }, + "name": "Overrides - User & Sender Detail", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "d5f38e54-a3c7-4df6-b569-bbabe85e1a36" + }, + { + "type": 1, + "content": { + "json": "# False Negative(FN) Submissions insights\r\n\r\n---\r\n\r\nThis tab provides insights into email message **False Negative(FN) Submissions** performed by users or administrators in Microsoft Defender for Office 365 where the message reported to have **Malware, Phish or Spam threat** within its **content, URLs or attachments**." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "8" + }, + "name": "text - 13 - Copy", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3b243dca-89ce-41e6-bccb-9ceb0953aa2e" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
False Negative(FN) Admin submissions\r\n
\r\n\r\nThis section provides insights into email message **False Negative(FN) Submissions performed by administrators** in Microsoft Defender for Office 365 where the message reported to have Malware, Phish or Spam threat within its content, URLs or attachments.

**Recommended action:** Prioritise admin-submitted misses for policy tuning; recurring sender domains may be block-list candidates." + }, + "name": "fn admin - section header", + "id": "64420254-0dae-4495-bd55-fc49e5bc1ed0" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) Admin Submissions per-{Granularity} trend by submission types \r\n**Displays counts (per {Granularity}) of False Negative(FN) Admin Submissions grouped by submission type (Spam, Phish, Malware) and content type (Mail, URL, Attachment). Helps to monitor where detections were missed and later submitted by admins as false negatives to Microsoft.**" + }, + "name": "fn admin - trend heading", + "id": "5f2de929-6f32-4079-a031-cbf689c15b29" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of admin false negative submission by submission type.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(CloudAppEvents\r\n| where ActionType contains \"Submission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| summarize Admin_Malware_FN=countif(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"), Admin_Phish_FN=countif(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"), Admin_Spam_FN=countif(SubmissionType == \"0\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"), Admin_Malware_URL_FN=countif(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\"), Admin_Malware_Attach_FN=countif(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\"), Admin_Phish_URL_FN=countif(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\"), Admin_Phish_Attach_FN=countif(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Malware (Mail)']=coalesce(Admin_Malware_FN,0), ['Phish (Mail)']=coalesce(Admin_Phish_FN,0), ['Spam (Mail)']=coalesce(Admin_Spam_FN,0), ['Malware (URL)']=coalesce(Admin_Malware_URL_FN,0), ['Malware (Attachment)']=coalesce(Admin_Malware_Attach_FN,0), ['Phish (URL)']=coalesce(Admin_Phish_URL_FN,0), ['Phish (Attachment)']=coalesce(Admin_Phish_Attach_FN,0) | sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "TotalAdminSubmissions", + "color": "redDark" + }, + { + "seriesName": "Phish (Mail)", + "color": "redBright" + }, + { + "seriesName": "Spam (Mail)", + "color": "orange" + }, + { + "seriesName": "Malware (Mail)", + "color": "redDark" + }, + { + "seriesName": "Phish (URL)", + "color": "purple" + }, + { + "seriesName": "Malware (Attachment)", + "color": "yellowDark" + }, + { + "seriesName": "Phish (Attachment)", + "color": "purpleDark" + }, + { + "seriesName": "Malware (URL)", + "color": "yellow" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "fn admin - submissions trend", + "id": "1b61155b-92a1-4533-9561-2e85e9a4dbf8" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) Admin Submissions by submission types \r\n**Displays counts (per {Granularity}) of False Negative(FN) Admin Submissions grouped by submission type (Spam, Phish, Malware) and content type (Mail, URL, Attachment).**" + }, + "customWidth": "50", + "name": "fn admin - by-type heading", + "id": "bbaa9ff9-a95d-495a-a44c-6b4cae888a24" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) Admin Submissions by submission State\r\n**Displays the total count of False Negative(FN) Admin Submissions by submission State (e.g., Pending, Completed, Failed). Helps track the processing status of admin submissions and identify bottlenecks or errors.**" + }, + "customWidth": "50", + "name": "fn admin - by-state heading", + "id": "b060c706-342a-4b2e-b81a-920bf4d8c5d9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of admin false negative submission by submission type.\r\nCloudAppEvents \r\n| where ActionType contains \"Submission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| extend Admin_SubmissionType=\r\niff(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Malware (Mail)\",\r\niff(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\r\niff(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\",\"Malware (URL)\",\r\niff(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\",\"Malware (Attachment)\",\r\niff(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\",\"Phish (URL)\",\r\niff(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\",\"Phish (Attachment)\",\r\n\"Other\")))))))\r\n| where Admin_SubmissionType!=\"Other\"\r\n| summarize count() by Admin_SubmissionType", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn admin - by-type pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "9d9d714a-357b-4ac3-bcb7-33601d3c3108" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of admin false negative submissions by the state of the submission.\r\nCloudAppEvents \r\n| where ActionType contains \"AdminSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType in (\"0\",\"1\",\"2\")\r\n| summarize count() by tostring(SubmissionState)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn admin - by-state pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "169f0f1c-1f1e-44fb-965e-850733f01879" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN)/False Positive(FP) Admin Submissions by Triage Verdict\r\n**Displays the total count of False Negative(FN)/False Positive(FP) Admin Submissions grouped by TriageVerdict (e.g., Malware, Spam, Phish, Clean). Helps assess how submissions were graded during triage and identify detection gaps.**" + }, + "customWidth": "50", + "name": "fn admin - triage-verdict heading", + "id": "3df841be-c1b0-4d61-8e38-316a34a48bd1" + }, + { + "type": 1, + "content": { + "json": "### Top Admins Submitting False Negatives \r\n**Displays the top 15 admin accounts that submitted the highest number of false negative messages (missed detections) via AdminSubmission. Helps identify key contributors to threat remediation and potential patterns in detection gaps.**" + }, + "customWidth": "50", + "name": "fn admin - top-admins heading", + "id": "e1e966f4-1f4d-4377-97c6-e2077fc0b8fa" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of admin false negative or false positive submissions by the verdict of the submission grading.\r\nCloudAppEvents \r\n| where ActionType contains \"AdminSubmissionTriage\" \r\n| extend UserKey = (parse_json(RawEventData)).UserKey, SubmissionState = (parse_json(RawEventData)).SubmissionState, SubmissionId=(parse_json(RawEventData)).SubmissionId, TriageVerdict=(parse_json(RawEventData)).GradingResult.TriageVerdict \r\n| summarize count() by tostring(TriageVerdict)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn admin - triage-verdict pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6df0db72-f9db-444e-856a-4369921d199b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top admins performing false negative submissions\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend Record= (parse_json(RawEventData)).RecordType,SubmissionState = (parse_json(RawEventData)).SubmissionState, UserId = (parse_json(RawEventData)).UserId,SubmissionType = parse_json(RawEventData).SubmissionType \r\n| where Record == 29 and SubmissionType in (\"0\",\"1\",\"2\")\r\n| summarize ['Submissions']=count() by ['Admin']=tostring(UserId)\r\n| top 15 by ['Submissions'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn admin - top-admins pie", + "id": "b5ccb4a1-9783-47cf-bf21-ded924f1a200" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) Admin Submissions by Top Sender Domains\r\n**For each top sender domain that admins reported missed threats for, shows the domain's MDO-detected threat profile (emails with threats and the Malware/Phish/Spam breakdown), the count of admin FN submissions, and the submission rate (Admin Submission % = admin submissions / total inbound from the domain). A high rate can flag a domain whose mail is frequently reported as missed.**" + }, + "customWidth": "100", + "name": "fn admin - top-sender-domains heading", + "id": "1a481c97-ac85-4b62-a86d-51b33b5a8e68" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top 10 sender domains that admins reported false negatives (missed threats) for, with each domain's MDO-detected threat profile for context.\r\nlet subs = CloudAppEvents\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType), SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), P2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"2\",\"1\",\"0\")\r\n| summarize AdminSubmissions=count() by P2SenderDomain;\r\nlet domainProfile = EmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalInbound=count(), EmailsWithThreats=countif(isnotempty(ThreatTypes)), Malware=countif(ThreatTypes has \"Malware\"), Phish=countif(ThreatTypes has \"Phish\"), Spam=countif(ThreatTypes has \"Spam\") by SenderFromDomain;\r\nsubs\r\n| join kind=leftouter (domainProfile) on $left.P2SenderDomain == $right.SenderFromDomain\r\n| extend AdminSubmissionPct = round(AdminSubmissions * 100.0 / todouble(coalesce(TotalInbound, AdminSubmissions)), 2)\r\n| top 10 by AdminSubmissions desc\r\n| project ['Sender Domain']=P2SenderDomain, ['Emails With Threats']=coalesce(EmailsWithThreats,0), ['Malware']=coalesce(Malware,0), ['Phish']=coalesce(Phish,0), ['Spam']=coalesce(Spam,0), ['Admin Submissions']=AdminSubmissions, ['Admin Submission %']=AdminSubmissionPct", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails With Threats", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Malware", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Phish", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Spam", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Admin Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "120px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Admin Submission %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "110px" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn admin - top-sender-domains table", + "id": "e56bed92-b0fb-4b76-90f3-169f4206418b" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) Admin Submissions by admin Detection override types\r\n**Displays the top 10 cases where emails were submitted as false negatives by admins, even though they were initially detected by Microsoft Defender for Office 365 but delivered due to an admin policy override. Includes details on PolicyOverride, PolicySource, and DetectionVerdict for deeper insight into override behaviour.**" + }, + "customWidth": "100", + "name": "fn admin - override-types heading", + "id": "293c174c-0197-4cf8-bbce-36fe42e5cf1b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises emails submitted as false negatives by admins where emails where already detected by MDO but there was a admin policy override\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| extend Admin_SubmissionType=\r\niff(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Malware (Mail)\",\r\niff(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\"))),\r\nP2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain),NetworkMessageId=tostring((parse_json(RawEventData).ObjectId)),DetectionVerdict=tostring((parse_json(RawEventData)).DeliveryMessageInfo.FinalFilterVerdict),PolicyOverride=tostring((parse_json(RawEventData)).DeliveryMessageInfo.PolicyOverride),PolicyPolicyOverrideType=tostring((parse_json(RawEventData)).DeliveryMessageInfo.PolicySource)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"2\",\"1\",\"0\") and PolicyOverride !=\"NoOverride\"\r\n| summarize count() by PolicyOverride, PolicyPolicyOverrideType,DetectionVerdict,Admin_SubmissionType\r\n| top 10 by count_ desc\r\n| project ['Policy Override']=PolicyOverride, ['Override Source']=PolicyPolicyOverrideType, ['Detection Verdict']=DetectionVerdict, ['Submission Type']=Admin_SubmissionType, ['Emails']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn admin - override-types table", + "id": "97799422-53e0-4e3b-8103-297fd1c744eb" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "8" + }, + "name": "group - 11-Fn Admin Submissions", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "45a1c185-4fbf-4e83-832e-1f20af427796" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
False Negative(FN) User submissions\r\n
\r\n\r\nThis section provides insights into email message **False Negative(FN) Submissions performed by end users** in Microsoft Defender for Office 365 where the message reported as having Phish, Spam threat within its content, URLs or attachments.

**Recommended action:** Recognise engaged reporters, coach over-reporters, and use graded phishing verdicts to tune anti-phishing policy." + }, + "name": "fn user - section header", + "id": "ca0b48e6-8bd8-4f99-956a-f9c72cc870db" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions per-{Granularity} trend by submission types \r\n**Displays counts (per {Granularity}) of False Negative(FN) User Submissions grouped by submission type (Spam, Phish and Attack simulations) . Helps to monitor where detections were missed and later submitted by users as false negatives.**" + }, + "name": "fn user - trend heading", + "id": "60ac8608-7875-45e6-8c83-e6bd0c34af8b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of users false negative submission by submission type, including phish simulations reported by users.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(CloudAppEvents\r\n| where ActionType contains \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| summarize User_Phish_FN=countif(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\"), User_Spam_FN=countif(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\"), User_AttackSim_Submission=countif(ActionType == \"AttackSimUserSubmission\" and SubmissionContentType==\"Mail\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Phish (Mail)']=coalesce(User_Phish_FN,0), ['Spam (Mail)']=coalesce(User_Spam_FN,0), ['Attack simulation reported']=coalesce(User_AttackSim_Submission,0) | sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "TotalAdminSubmissions", + "color": "redDark" + }, + { + "seriesName": "Phish (Mail)", + "color": "redDark" + }, + { + "seriesName": "Attack simulation reported", + "color": "green" + }, + { + "seriesName": "Spam (Mail)", + "color": "orangeDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "fn user - submissions trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "29355816-6cba-4264-938e-b0b27afdcb12" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions by submission State\r\n**Displays the total count of False Negative(FN) User Submissions by submission State (e.g., Pending, Completed, Failed). Helps track the processing status of user submissions and identify bottlenecks or errors.**" + }, + "customWidth": "50", + "name": "fn user - by-state heading", + "id": "6a4b32cc-b7e4-47bb-b1b9-f415df7e629c" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions by Triage Verdict\r\n**Displays the total count of False Negative(FN)/False Positive(FP) User Submissions grouped by TriageVerdict (e.g., Malware, Spam, Phish, Clean). Helps assess how submissions were graded during triage and identify detection gaps.**" + }, + "customWidth": "50", + "name": "fn user - triage-verdict heading", + "id": "1427e34f-be44-4517-ae73-cc4776a49fe7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of user false negative submissions by the state of the submission.\r\nCloudAppEvents \r\n| where ActionType contains \"UserSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType in (\"0\",\"1\")\r\n| summarize count() by tostring(SubmissionState)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - by-state pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a6151271-e925-4804-a3c1-06afee27c026" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of user false negative or false positive submissions by the verdict of the submission grading.\r\nCloudAppEvents \r\n| where ActionType contains \"UserSubmissionTriage\" \r\n| extend UserKey = (parse_json(RawEventData)).UserKey, SubmissionState = (parse_json(RawEventData)).SubmissionState, SubmissionId=(parse_json(RawEventData)).SubmissionId, TriageVerdict=(parse_json(RawEventData)).GradingResult.TriageVerdict \r\n| summarize count() by tostring(TriageVerdict)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - triage-verdict pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "6ff319ea-b5c5-4e33-9e5c-065aadbf465d" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions of already detected Emails (from Junk folder)\r\n**Displays the total count of False Negative(FN) User Submissions where the email message was already detected by Microsoft Defender for Office 365 and the detection action was configured to deliver the message into the Junk folder of the user mailbox. It breaks down the result based on the original detection verdict determined by Microsoft Defender for Office 365. Helps track the user submissions of messages that already had a detection. Consider changing the detection action to Quarantine to avoid these submissions.**" + }, + "name": "fn user - junk-folder heading", + "id": "d6338907-489d-4c88-b82f-260fc0f9d302" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of user false negative submissions that are already detected by MDO and already delivered in the junk folder\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where DeliveryLocation == \"Junk folder\"\r\n| summarize count() by ThreatTypes,User_SubmissionType\r\n| project ThreatTypes,User_SubmissionType, Emails = count_", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - junk-folder pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "c13452cb-e864-4f01-8623-51f3ea13bbbc" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of user false negative submissions that are already detected by MDO and already delivered in the junk folder\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId,UserId = (parse_json(RawEventData)).UserId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where DeliveryLocation == \"Junk folder\"\r\n| extend MDO_detection = parse_json(DetectionMethods) \r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n| summarize TotalJunkSubmittedEmailCount=count(),PhishEmailCount = countif(FirstDetection == \"Phish\"),SpamEmailCount = countif(FirstDetection == \"Spam\") by tostring(UserId)\r\n| top 15 by TotalJunkSubmittedEmailCount desc\r\n| project ['User']=UserId, ['Junk Submissions']=TotalJunkSubmittedEmailCount, ['Phish']=PhishEmailCount, ['Spam']=SpamEmailCount", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Junk Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Phish", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Spam", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - junk-folder table", + "id": "b242f301-c9f7-41f9-aa73-03848bd58eae" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions - Admin review status (Mark and Notify)\r\n**Displays counts of False Negative(FN) User Submissions that were reviewed by admins and marked with a notify action. The Mark and Notify action also can be taken automatically with Automated investigation and response (AIR). Helps track cases where admins confirmed user reports and communicated the outcome, supporting transparency and user trust.**" + }, + "customWidth": "50", + "name": "fn user - mark-notify heading", + "id": "784bf171-53ae-4907-b2b0-7fc5039df231" + }, + { + "type": 1, + "content": { + "json": "### False Negative(FN) User Submissions accuracy vs Admin review verdict\r\n**Displays counts of False Negative(FN) User Submissions (Phish, Junk, NotJunk) compared to admin review results. Highlights whether submissions were Correct, Not Correct, or misclassified comparing user submission type with the Admin decision using Mark and Notify action in Microsoft Defender for Office 365 (e.g., “Phish reported as Junk”, “Reported but not malicious”).**" + }, + "customWidth": "50", + "name": "fn user - accuracy heading", + "id": "3d137383-6436-4213-9824-72f424b67290" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises user submissions where admin also performed 'mark and notify' action on the submission\r\nlet ReviewResults = CloudAppEvents | where ActionType == \"SubmissionNotification\" \r\n| extend SubmissionId = tostring(parse_json(RawEventData).SubmissionId)\r\n| extend Properties = parse_json(RawEventData.ExtendedProperties)\r\n| mv-expand element = Properties\r\n| where element.Name == \"AdminReviewResult\"\r\n| project SubmissionId, AdminReviewResult = element.Value;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionId = tostring(parse_json(RawEventData).SubmissionId), SubmissionType = parse_json(RawEventData).SubmissionType\r\n| join kind=leftouter ReviewResults on SubmissionId\r\n| extend UserReportedAs=iif(SubmissionType == 1, \"Phish\",iif(SubmissionType == 2, \"Junk\",iif(SubmissionType == 3, \"NotJunk\",\"\")))\r\n| extend ReviewedAccuracy=iif(UserReportedAs==AdminReviewResult, 1,0)\r\n| extend Reviewed=iif(isempty(AdminReviewResult),\"Not Reviewed\",\"Reviewed\")\r\n| project SubmissionId,UserReportedAs,Reviewed,AdminReviewResult, ReviewedAccuracy\r\n| summarize count() by Reviewed", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - mark-notify pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "7bb7d116-bd61-4e46-81dd-d634a31e7369" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises user submissions type compared to admin review verdict. \r\n//Eg. User reporting a phish but admin review is 'not threat found'\r\nlet ReviewResults = CloudAppEvents | where ActionType == \"SubmissionNotification\" \r\n| extend SubmissionId = tostring(parse_json(RawEventData).SubmissionId)\r\n| extend Properties = parse_json(RawEventData.ExtendedProperties)\r\n| mv-expand element = Properties\r\n| where element.Name == \"AdminReviewResult\"\r\n| project SubmissionId, AdminReviewResult = element.Value;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionId = tostring(parse_json(RawEventData).SubmissionId), SubmissionType = parse_json(RawEventData).SubmissionType\r\n| join kind=leftouter ReviewResults on SubmissionId\r\n| extend UserReportedAs=iif(SubmissionType == 1, \"Phish\",iif(SubmissionType == 2, \"Junk\",iif(SubmissionType == 3, \"NotJunk\",\"\")))\r\n| extend ReviewedAccuracy=iif(AdminReviewResult==UserReportedAs, \"Correct\", iif(AdminReviewResult==\"Phish\" and UserReportedAs == \"Junk\", \"Phish reported as junk\",iif(AdminReviewResult==\"Junk\" and UserReportedAs == \"Phish\",\"Junk reported as Phish\",iif(AdminReviewResult==\"NotJunk\",\"Reported but not malicious or spam\",iif(isempty(AdminReviewResult),\"Not Reviewed\",\"Not correct\")))))\r\n| extend Reviewed=iif(isempty(AdminReviewResult),\"Not Reviewed\",\"Reviewed\")\r\n| project SubmissionId,UserReportedAs,Reviewed,AdminReviewResult, ReviewedAccuracy\r\n| where Reviewed==\"Reviewed\"\r\n| summarize count() by ReviewedAccuracy", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fn user - accuracy pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8af1b9f0-995c-4c58-9960-8e69c6960987" + }, + { + "type": 1, + "content": { + "json": "### Top 10 P2 Email Senders domains in False Negative(FN) User Submissions \r\n**Displays the top 10 P2 email sender domains of inbound emails reported by users as false negatives (missed detections). Includes total inbound email volume and calculates the percentage of user submissions per domain to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "fn user - top-p2-domains heading", + "id": "78dab1f9-09ec-46e2-aee4-f256e368cdd5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises top 10 sender domains of inbound emails submitted as false negatives by users.\r\nlet TotalInboundbySender=\r\nEmailEvents\r\n| where EmailDirection ==\"Inbound\"\r\n| summarize count() by SenderFromDomain;\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType),RecipientObjectId=AccountObjectId,NetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\"\r\n| summarize UserSubmissions=count() by SenderFromDomain\r\n| join TotalInboundbySender on SenderFromDomain\r\n| extend UserSubmissions_Percentage = todouble(round(UserSubmissions / todouble(count_) * 100, 2))\r\n| top 10 by UserSubmissions desc\r\n| project ['Sender Domain']=SenderFromDomain, ['User Submissions']=UserSubmissions, ['Total Inbound']=count_, ['User Submission %']=UserSubmissions_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "User Submission %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "12ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - top-p2-domains table", + "id": "6e6a59d4-70e1-4d85-bebb-6bb23d25d2d9" + }, + { + "type": 1, + "content": { + "json": "### Top 10 P2 Individual Email Senders in False Negative(FN) User Submissions \r\n**Displays the top 10 P2 individual email sender addresses of inbound emails reported by users as false negatives (missed detections). Includes total inbound email volume and calculates the percentage of user submissions per sender to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "fn user - top-p2-senders heading", + "id": "a6e8fda5-dd05-49ed-87e2-16443495396e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises top 10 sender email addresses of inbound emails submitted as false negatives by users.\r\nlet TotalInboundbySender=\r\nEmailEvents\r\n| where EmailDirection ==\"Inbound\"\r\n| summarize count() by SenderFromAddress;\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType),P2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain),RecipientObjectId=AccountObjectId,NetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\"\r\n| summarize UserSubmissions=count() by SenderFromAddress\r\n| join TotalInboundbySender on SenderFromAddress\r\n| extend UserSubmissions_Percentage = todouble(round(UserSubmissions / todouble(count_) * 100, 2))\r\n| top 10 by UserSubmissions desc\r\n| project ['Sender Address']=SenderFromAddress, ['User Submissions']=UserSubmissions, ['Total Inbound']=count_, ['User Submission %']=UserSubmissions_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "User Submission %", + "formatter": 4, + "formatOptions": { + "customColumnWidthSetting": "12ch", + "palette": "red", + "min": 0, + "max": 20 + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - top-p2-senders table", + "id": "878fd15f-2607-4d6d-b919-0b4bea6a1850" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Intra-org Email Senders in False Negative(FN) User Submissions \r\n**Displays the top 10 email senders of intra-org emails reported by users as false negatives (missed detections). Includes total intra-org email volume and calculates the percentage of user submissions per sender to highlight high-risk sources.**" + }, + "customWidth": "100", + "name": "fn user - intraorg-senders heading", + "id": "87a51814-7f01-42e3-aea2-4136c869d39d" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises top 10 sender email address of intra-org emails submitted as false negatives by users.\r\nlet TotalInboundbySender=\r\nEmailEvents\r\n| where EmailDirection ==\"Intra-org\"\r\n| summarize count() by SenderFromAddress;\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType),P2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain),RecipientObjectId=AccountObjectId,NetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Intra-org\"\r\n| summarize UserSubmissions=count() by SenderFromAddress\r\n| join TotalInboundbySender on SenderFromAddress\r\n| extend UserSubmissions_Percentage = todouble(round(UserSubmissions / todouble(count_) * 100, 2))\r\n| top 10 by UserSubmissions desc\r\n| project ['Sender Address']=SenderFromAddress, ['User Submissions']=UserSubmissions, ['Total Intra-org']=count_, ['User Submission %']=UserSubmissions_Percentage", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Intra-org", + "formatter": 0, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "User Submission %", + "formatter": 4, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "12ch" + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - intraorg-senders table", + "id": "38edca4b-a403-41e8-8c2b-7c0595e93b7a" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Intra-org Email Subjects in False Negative(FN) User Submissions \r\n**Displays the top 10 Email Subjects of intra-org emails reported by users as false negatives (missed detections). Helps to highlight high-risk intra-org email sources.**" + }, + "customWidth": "100", + "name": "fn user - intraorg-subjects heading", + "id": "52b0bc5b-7e54-4a5b-a487-8a736a8c2397" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises top 10 subjects of intra-org emails submitted as false negatives by users.\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Intra-org\"\r\n| summarize count() by Subject\r\n| top 10 by count_ desc\r\n| project ['Subject']=Subject, ['User Submissions']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Subject", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "70ch" + } + }, + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - intraorg-subjects table", + "id": "ee2c1d2e-3d4e-4024-8422-985b22cb7475" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Detection Overrides defined by Admins in False Negative(FN) User Submissions \r\n**Displays the top 10 use cases where users submitted emails as false negatives (Spam or Phish) that were already detected by Microsoft Defender for Office 365 but delivered due to an admin-defined policy override. Includes details on OrgLevelAction, OrgLevelPolicy, and ThreatTypes for deeper insight into override behaviour.**" + }, + "customWidth": "100", + "name": "fn user - admin-override heading", + "id": "0dd9b3ce-9716-42bb-93de-495f0af2d075" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises emails submitted as false negatives by users where emails where already detected by MDO but there was an admin definded policy override.\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where ThreatTypes !=\"\"and OrgLevelAction!=\"\"\r\n| summarize count() by OrgLevelAction, OrgLevelPolicy,ThreatTypes,User_SubmissionType\r\n| top 10 by count_ desc\r\n| project ['Override Action']=OrgLevelAction, ['Override Policy']=OrgLevelPolicy, ['Threat Type']=ThreatTypes, ['Submission Type']=User_SubmissionType, ['User Submissions']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Override Policy", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "48ch" + } + }, + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - admin-override table", + "id": "100de6ca-beb0-44d7-a715-449a389e9e8a" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Detection Overrides defined by Users in False Negative(FN) User Submissions \r\n**Displays the top 10 use cases where users submitted emails as false negatives (Spam or Phish) that were already detected by Microsoft Defender for Office 365 but delivered due to a user-defined override. Includes details on UserLevelAction, UserLevelPolicy, and ThreatTypes for deeper insight into override behaviour.**" + }, + "customWidth": "100", + "name": "fn user - user-override heading", + "id": "67057c7d-c0af-4373-b23a-4001fbced888" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises emails submitted as false negatives by users where emails where already detected by MDO but there was an policy override.\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where ThreatTypes !=\"\"and UserLevelAction!=\"\"\r\n| summarize count() by UserLevelAction, UserLevelPolicy,ThreatTypes,User_SubmissionType\r\n| top 10 by count_ desc\r\n| project ['Override Action']=UserLevelAction, ['Override Policy']=UserLevelPolicy, ['Threat Type']=ThreatTypes, ['Submission Type']=User_SubmissionType, ['User Submissions']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Override Policy", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "48ch" + } + }, + { + "columnMatch": "User Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - user-override table", + "id": "1b97f7d2-152d-4eb0-bfac-e161fbfa4046" + }, + { + "type": 1, + "content": { + "json": "### Top 10 users performing the most False Negative(FN) User Submissions\r\n**Displays the Top 10 user accounts that performed the highest number of False Negative(FN) User Submissions (missed detections). Helps identify individuals most engaged in reporting suspicious, malicious messages and potential patterns in detection gaps.**" + }, + "customWidth": "100", + "name": "fn user - top-users heading", + "id": "7799a0a0-a835-4080-b59a-736b08ad809e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top 10 users performing false negative submissions\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType in (\"0\",\"1\")\r\n| extend UserId = (parse_json(RawEventData)).UserId\r\n| summarize ['Submissions']=count() by ['User']=tostring(UserId)\r\n| top 10 by ['Submissions'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - top-users pie", + "id": "44838734-43a0-4301-9ddb-a644c7ec509a" + }, + { + "type": 1, + "content": { + "json": "### Top 10 users performing the most User Submissions of Attack simulation messages\r\n**Displays the top 10 user accounts that reported phishing simulation emails during cyber security awareness campaigns. Supports evaluation of cyber security awareness programme effectiveness and identifies highly engaged users.**" + }, + "customWidth": "100", + "name": "fn user - attacksim-users heading", + "id": "8a96e90f-765f-40c0-8476-30c97d43c328" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top users reporting the phishing simulation emails.\r\nCloudAppEvents \r\n| extend Record= (parse_json(RawEventData)).RecordType \r\n| extend SubmissionState = (parse_json(RawEventData)).SubmissionState \r\n| extend UserId = (parse_json(RawEventData)).UserId\r\n| where Record == 29\r\n| where ActionType == \"AttackSimUserSubmission\" \r\n| summarize ['Submissions']=count() by ['User']=tostring(UserId)\r\n| top 10 by ['Submissions'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fn user - attacksim-users pie", + "id": "ab648c4a-4c46-4c73-96f0-784c9bcef961" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "8" + }, + "name": "group - 11 - FN User submissions", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "348ce24a-7cbc-4b66-a471-dfe3827bed2d" + }, + { + "type": 1, + "content": { + "json": "# False Positive(FP) Submissions insights\r\n\r\n---\r\n\r\nThis tab provides insights into email message **False Positive(FP) Submissions** performed by users or administrators in Microsoft Defender for Office 365 where the message was flagged as a threat by Microsoft Defender for Office 365 but was later reported as No Threat by administrators or users." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "10" + }, + "name": "fp - tab description", + "id": "78e2df52-a0d2-499a-95fe-708f67db5ad6" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
False Positive(FP) Admin Submissions\r\n
\r\n\r\nAdministrator submissions represent escalated false positive reports submitted by security team members rather than end users. These typically involve more complex cases requiring expert review, such as recurring issues affecting multiple users, business-critical communications being blocked, or suspected policy misconfigurations. Admin submissions carry higher priority and can result in actions as allow-list additions or global policy changes to prevent widespread user impact.

**Recommended action:** Review recurring false-positive sender domains and consider allow entries or policy tuning to reduce business disruption." + }, + "name": "fp admin - section header", + "id": "02d54e9c-e989-4cde-a128-68a6381ed9d7" + }, + { + "type": 1, + "content": { + "json": "### Admin Submission Volume and Type Breakdown\r\n\r\n**These charts track the volume and composition of administrator-initiated false positive submissions. The trend chart shows submission patterns (per {Granularity}) across Email, URL, and Attachment types, while the pie chart reveals the distribution among these categories. Spikes in admin submissions often signal systemic issues requiring immediate policy review, as admins typically escalate only the most impactful or recurring problems.**" + }, + "name": "fp admin - volume/type heading", + "id": "103b8362-a10f-4b46-a757-8290c4269a5c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of admin false positive submission by submission type.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(CloudAppEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(CloudAppEvents | summarize max(Timestamp));\r\nlet agg = materialize(CloudAppEvents\r\n| where ActionType contains \"Submission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| summarize Admin_Email_FP=countif(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"), Admin_URL_FP=countif(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\"), Admin_Attach_FP=countif(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Email']=coalesce(Admin_Email_FP,0), ['URL']=coalesce(Admin_URL_FP,0), ['Attachment']=coalesce(Admin_Attach_FP,0) | sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "TotalAdminSubmissions", + "color": "redDark" + }, + { + "seriesName": "Admin_Phish_FN", + "color": "redBright" + }, + { + "seriesName": "Admin_Spam_FN", + "color": "orange" + }, + { + "seriesName": "Admin_Malware_FN", + "color": "redDark" + }, + { + "seriesName": "Admin_Phish_URL_FN", + "color": "purple" + }, + { + "seriesName": "Admin_Malware_Attach_FN", + "color": "yellowDark" + }, + { + "seriesName": "Admin_Phish_Attach_FN", + "color": "purpleDark" + }, + { + "seriesName": "Admin_Malware_URL_FN", + "color": "yellow" + }, + { + "seriesName": "Admin_Email_FP", + "color": "redDark" + }, + { + "seriesName": "Admin_URL_FP", + "color": "orangeDark" + }, + { + "seriesName": "Admin_Attach_FP", + "color": "yellow" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "66", + "name": "fp admin - submissions trend", + "id": "326762ca-1f2b-48e9-90d6-ff2aa6a75e95" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of admin false positive submission by submission type.\r\nCloudAppEvents \r\n| where ActionType contains \"Submission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| extend Admin_SubmissionType=\r\niff(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Email\",\r\niff(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\",\"URL\",\r\niff(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\",\"Attachment\",\r\n\"Other\")))\r\n| where Admin_SubmissionType!=\"Other\"\r\n| summarize count() by Admin_SubmissionType", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "chartSettings": { + "createOtherGroup": 10 + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "fp admin - by-type pie", + "id": "be925c4c-5718-4385-8e82-59c57b975ac5" + }, + { + "type": 1, + "content": { + "json": "### False Positive(FP) Admin Submissions by submission state
\r\n\r\n**Displays the total count of False Positive(FP) Admin Submissions by submission State (e.g., Pending, Completed, Failed). Helps track the processing status of admin submissions and identify bottlenecks or errors.**" + }, + "customWidth": "50", + "name": "fp admin - by-state heading", + "id": "2b2acb67-c070-48bd-acf1-025c05aae8b5" + }, + { + "type": 1, + "content": { + "json": "### Top Admins Submitting False Positives
\r\n\r\n**Displays the top 15 admin accounts that submitted the highest number of false positive messages via AdminSubmission.**" + }, + "customWidth": "50", + "name": "fp admin - top-admins heading", + "id": "52206f40-fae9-460f-97b8-2cf9b633098f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of admin false positive submissions by the state of the submission.\r\nCloudAppEvents \r\n| where ActionType contains \"AdminSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType == \"3\"\r\n| summarize count() by tostring(SubmissionState)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp admin - by-state pie", + "id": "96133d9e-24fb-417e-a3cd-df98dda4c60a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top admins performing false positive submissions.\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend Record= (parse_json(RawEventData)).RecordType,SubmissionState = (parse_json(RawEventData)).SubmissionState, UserId = (parse_json(RawEventData)).UserId,SubmissionType = parse_json(RawEventData).SubmissionType \r\n| where Record == 29 and SubmissionType ==\"3\"\r\n| summarize ['Submissions']=count() by ['Admin']=tostring(UserId)\r\n| top 15 by ['Submissions'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp admin - top-admins pie", + "id": "da7b4c89-904d-4917-b6cd-04b32e02d4a1" + }, + { + "type": 1, + "content": { + "json": "### Admin Submission False Positive Malware Detection Breakdown\r\n**Shows the count of administrator-submitted false positive reports (legitimate emails flagged as malware) grouped by the detection method that flagged them. Helps identify which filtering technologies most often misclassify valid messages as malware.**" + }, + "customWidth": "100", + "name": "fp admin - malware-detection heading", + "id": "69d649e0-86fd-4c08-afd4-e6c200b11c86" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Admin false positive submissions whose original verdict was Malware, grouped by the detection method that flagged them. A high count means that method most often misclassifies legitimate mail as Malware.\r\nlet total = toscalar(CloudAppEvents\r\n | where ActionType == \"AdminSubmissionSubmitted\"\r\n | extend R = parse_json(RawEventData)\r\n | where tostring(R.SubmissionContentType) == \"Mail\" and tostring(R.SubmissionType) == \"3\" and tostring(R.DeliveryMessageInfo.FinalFilterVerdict) == \"Malware\"\r\n | count);\r\nCloudAppEvents\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), DetectionMethod = tostring(R.DeliveryMessageInfo.FinalFilterVerdictControlSource), DetectionVerdict = tostring(R.DeliveryMessageInfo.FinalFilterVerdict), P2SenderDomain = tostring(R.P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\" and DetectionVerdict == \"Malware\"\r\n| extend DetectionMethod = iif(isempty(DetectionMethod), \"Not specified\", DetectionMethod)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(P2SenderDomain) by DetectionMethod\r\n| extend Pct = iif(total == 0, 0.0, round(FPSubmissions * 100.0 / total, 1))\r\n| sort by FPSubmissions desc\r\n| project ['Detection Method'] = DetectionMethod, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains, ['% of Malware FPs'] = Pct", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "% of", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp admin - malware-detection table", + "id": "607eb19b-1ded-488d-98db-8b23f9e90967" + }, + { + "type": 1, + "content": { + "json": "### Admin Submission False Positive Phish Detection Breakdown\r\n**Shows the count of administrator-submitted false positive reports (legitimate emails flagged as phishing) grouped by the detection method that flagged them. Helps identify which filtering technologies most often misclassify valid messages as phishing.**" + }, + "customWidth": "100", + "name": "fp admin - phish-detection heading", + "id": "c1f1e12f-d0aa-4023-9172-8182772b3331" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Admin false positive submissions whose original verdict was Phish, grouped by the detection method that flagged them. A high count means that method most often misclassifies legitimate mail as Phish.\r\nlet total = toscalar(CloudAppEvents\r\n | where ActionType == \"AdminSubmissionSubmitted\"\r\n | extend R = parse_json(RawEventData)\r\n | where tostring(R.SubmissionContentType) == \"Mail\" and tostring(R.SubmissionType) == \"3\" and tostring(R.DeliveryMessageInfo.FinalFilterVerdict) == \"Phish\"\r\n | count);\r\nCloudAppEvents\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), DetectionMethod = tostring(R.DeliveryMessageInfo.FinalFilterVerdictControlSource), DetectionVerdict = tostring(R.DeliveryMessageInfo.FinalFilterVerdict), P2SenderDomain = tostring(R.P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\" and DetectionVerdict == \"Phish\"\r\n| extend DetectionMethod = iif(isempty(DetectionMethod), \"Not specified\", DetectionMethod)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(P2SenderDomain) by DetectionMethod\r\n| extend Pct = iif(total == 0, 0.0, round(FPSubmissions * 100.0 / total, 1))\r\n| sort by FPSubmissions desc\r\n| project ['Detection Method'] = DetectionMethod, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains, ['% of Phish FPs'] = Pct", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "% of", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp admin - phish-detection pie", + "id": "b6c074f9-affa-41a3-802a-53541394ae73" + }, + { + "type": 1, + "content": { + "json": "### Admin Submission False Positive Spam Detection Breakdown\r\n**Shows the count of administrator-submitted false positive reports (legitimate emails flagged as spam) grouped by the detection method that flagged them. Helps identify which filtering technologies most often misclassify valid messages as spam.**" + }, + "customWidth": "100", + "name": "fp admin - spam-detection heading", + "id": "f0f2adb9-34af-4df0-90e6-087a265bedf6" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Admin false positive submissions whose original verdict was Spam, grouped by the detection method that flagged them. A high count means that method most often misclassifies legitimate mail as Spam.\r\nlet total = toscalar(CloudAppEvents\r\n | where ActionType == \"AdminSubmissionSubmitted\"\r\n | extend R = parse_json(RawEventData)\r\n | where tostring(R.SubmissionContentType) == \"Mail\" and tostring(R.SubmissionType) == \"3\" and tostring(R.DeliveryMessageInfo.FinalFilterVerdict) == \"Spam\"\r\n | count);\r\nCloudAppEvents\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), DetectionMethod = tostring(R.DeliveryMessageInfo.FinalFilterVerdictControlSource), DetectionVerdict = tostring(R.DeliveryMessageInfo.FinalFilterVerdict), P2SenderDomain = tostring(R.P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\" and DetectionVerdict == \"Spam\"\r\n| extend DetectionMethod = iif(isempty(DetectionMethod), \"Not specified\", DetectionMethod)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(P2SenderDomain) by DetectionMethod\r\n| extend Pct = iif(total == 0, 0.0, round(FPSubmissions * 100.0 / total, 1))\r\n| sort by FPSubmissions desc\r\n| project ['Detection Method'] = DetectionMethod, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains, ['% of Spam FPs'] = Pct", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "20ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "% of", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "14ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp admin - spam-detection pie", + "id": "e877d9c9-3bd3-4368-997e-945f18ffcf5f" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains for Admin False Positive Submissions
\r\n\r\n**Lists the top 10 sender domains of emails reported as false positives by administrators (legitimate messages incorrectly flagged as spam or phishing). Helps identify domains frequently misclassified.**" + }, + "customWidth": "50", + "name": "fp admin - top-sender-domains heading", + "id": "37680101-7e4b-4bcc-9e7e-0ccd2d914881" + }, + { + "type": 1, + "content": { + "json": "### Admin False Positive Submissions by Original Threat Verdict
\r\n\r\n**Displays all administrator-submitted false positive emails by their original filter verdict (e.g., spam, phishing) and policy override details. Helps identify which threat categories are most often misclassified.**" + }, + "customWidth": "50", + "name": "fp admin - by-verdict heading", + "id": "879e81ad-00a6-4a10-bcb6-56879133bb9f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top 10 sender domains of emails which are submitted as false positive by admins\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType),P2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType ==\"3\"\r\n| summarize count() by P2SenderDomain\r\n| top 10 by count_ desc\r\n| project ['Sender Domain']=P2SenderDomain, ['Emails']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp admin - top-sender-domains table", + "id": "42844dc9-4418-487b-a5ad-31e1f6b4b487" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises all emails submitted as false positive by admins summarizing by the original filter verdict threat type\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| extend Admin_SubmissionType=\r\niff(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\" ,\"Email\",\r\n\"Other\"),\r\nP2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain),NetworkMessageId=tostring((parse_json(RawEventData).ObjectId)),DetectionVerdict=tostring((parse_json(RawEventData)).DeliveryMessageInfo.FinalFilterVerdict),PolicyOverride=tostring((parse_json(RawEventData)).DeliveryMessageInfo.PolicyOverride),PolicyPolicyOverrideType=tostring((parse_json(RawEventData)).DeliveryMessageInfo.PolicySource)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| summarize count() by PolicyOverride,DetectionVerdict,Admin_SubmissionType\r\n| top 10 by count_ desc\r\n| project ['Policy Override']=PolicyOverride, ['Detection Verdict']=DetectionVerdict, ['Submission Type']=Admin_SubmissionType, ['Emails']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Emails", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "40ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp admin - by-verdict table", + "id": "3ebbd402-06ef-45a7-b4ee-c5938b98b540" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "10" + }, + "name": "fp admin - group", + "styleSettings": { + "showBorder": true + }, + "id": "b6215b53-c181-4693-a14f-441809f65f38" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
False Positive (FP) User Submissions\r\n
\r\n\r\nThis section provides insights into email message False Postive(FP) Submissions performed by end users in Microsoft Defender for Office 365 where the message was flagged as a threat by Microsoft Defender for Office 365 but was later reported as No Threat by users. User submissions are critical feedback mechanisms that help security teams identify overly aggressive detection rules, refine security policies, and reduce user friction. High false positive rates can erode user trust and lead to security fatigue, so monitoring these metrics helps balance protection with productivity.

**Recommended action:** High user false-positive volume suggests over-aggressive filtering - review the affected senders and adjust policy." + }, + "name": "fp user - section header", + "id": "0d93d7ee-a61e-43b7-bdcd-172bd79ad050" + }, + { + "type": 1, + "content": { + "json": "### User Submission Trend\r\n\r\n**Displays the volume (per {Granularity}) of false positive submissions from end users. A sudden spike may indicate a new detection rule causing widespread misclassification, while a declining trend suggests improving detection accuracy. Monitoring this trend helps security teams respond quickly to detection issues before they impact user productivity.**" + }, + "name": "fp user - trend heading", + "id": "c3f8ae45-0498-4fa8-b9d1-35e926932639" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of user false positive submission by submission type.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(CloudAppEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(CloudAppEvents | summarize max(Timestamp));\r\nlet agg = materialize(CloudAppEvents\r\n| where ActionType contains \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where SubmissionType == \"3\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\"\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['User FP Submissions'] = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "User FP Submissions", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - submissions trend", + "id": "847032f5-56a8-4681-9665-9e917c7c9355" + }, + { + "type": 1, + "content": { + "json": "### User False Positive Submissions by State
\r\n\r\n**Displays the total number of user-reported false positive email submissions grouped by their processing state (e.g., pending, completed). Helps track submission workflow and resolution progress.**" + }, + "customWidth": "50", + "name": "fp user - by-state heading", + "id": "7bd03278-7734-4fbf-a502-95b42e90160e" + }, + { + "type": 1, + "content": { + "json": "### Top Users Performing False Positive Submissions
\r\n\r\n**Lists the top 15 users who reported emails as false positives (legitimate messages incorrectly flagged as threats). Helps identify frequent reporters and potential training or policy adjustment needs.**" + }, + "customWidth": "50", + "name": "fp user - top-users heading", + "id": "7e2b987b-325d-4f69-8d6b-fafd6676a03a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of user false positive submission by submission state.\r\nCloudAppEvents \r\n| where ActionType contains \"UserSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType == \"3\"\r\n| summarize count() by tostring(SubmissionState)", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp user - by-state pie", + "id": "df79d08b-3eac-4101-a3f2-3a4a3bf450ce" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the top users performing false positive submissions.\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType == \"3\"\r\n| extend UserId = (parse_json(RawEventData)).UserId\r\n| summarize ['Submissions']=count() by ['User']=tostring(UserId)\r\n| top 15 by ['Submissions'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "fp user - top-users pie", + "id": "ec7505d8-3a70-4bde-a985-baf5a0c4ec34" + }, + { + "type": 1, + "content": { + "json": "### User Submission False Positive Malware Detection Breakdown\r\n**Shows the count of user-submitted false positive reports (legitimate emails flagged as malware) grouped by the detection technique that flagged them. Malware quarantine is admin-only by default, so this table only populates when a custom quarantine policy lets users view and report their own malware detections - it is usually empty.**" + }, + "customWidth": "100", + "name": "fp user - malware-verdict heading", + "id": "693b1072-5ddd-49d0-a0f5-2bba4c287edf" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//User false positive submissions whose email was originally flagged as Malware, by the detection technique that flagged it. A high count means that technique most often misclassifies legitimate mail as Malware.\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has \"Malware\"\r\n| mv-expand Technique = parse_json(DetectionMethods).Malware to typeof(string)\r\n| where isnotempty(Technique)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(SenderFromDomain) by Technique\r\n| sort by FPSubmissions desc\r\n| project ['Detection Technique'] = Technique, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "22ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - malware-verdict table", + "id": "10ea55bd-937e-454d-b6cc-a9dccfdf3417" + }, + { + "type": 1, + "content": { + "json": "### User Submission False Positive Phish Detection Breakdown\r\n**Shows the count of user-submitted false positive reports (legitimate emails flagged as phishing) grouped by the detection technique that flagged them. Helps identify which filtering technologies most often misclassify valid messages as phishing.**" + }, + "customWidth": "100", + "name": "fp user - phish-verdict heading", + "id": "6dd14abb-2772-4271-89d8-8c0dcdbfd9e5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//User false positive submissions whose email was originally flagged as Phish, by the detection technique that flagged it. A high count means that technique most often misclassifies legitimate mail as Phish.\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has \"Phish\"\r\n| mv-expand Technique = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Technique)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(SenderFromDomain) by Technique\r\n| sort by FPSubmissions desc\r\n| project ['Detection Technique'] = Technique, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "22ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - phish-verdict pie", + "id": "57049aad-eb17-4e65-a8a4-b5d05b0501cd" + }, + { + "type": 1, + "content": { + "json": "### User Submission False Positive Spam Detection Breakdown\r\n**Shows the count of user-submitted false positive reports (legitimate emails flagged as spam) grouped by the detection technique that flagged them. Helps identify which filtering technologies most often misclassify valid messages as spam.**" + }, + "customWidth": "100", + "name": "fp user - spam-verdict heading", + "id": "5479b2ed-b629-41e7-9857-c91191b09c8f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//User false positive submissions whose email was originally flagged as Spam, by the detection technique that flagged it. A high count means that technique most often misclassifies legitimate mail as Spam.\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has \"Spam\"\r\n| mv-expand Technique = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Technique)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(SenderFromDomain) by Technique\r\n| sort by FPSubmissions desc\r\n| project ['Detection Technique'] = Technique, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Sender Domains", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "22ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - spam-verdict pie", + "id": "45a2122e-0281-4602-906d-a0406ed20d54" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Sender Domains for User False Positive Submissions
\r\n\r\n**Lists the top 10 sender domains of emails reported as false positives by users (legitimate messages incorrectly flagged as threats). Helps identify domains frequently misclassified.**" + }, + "customWidth": "100", + "name": "fp user - top-sender-domains heading", + "id": "2751fca4-3ac5-45fe-a965-8c811018926a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top 10 sender domains reported as false positives by users, with each domain's total inbound volume and the share of it reported as FP (a high rate flags a domain whose legitimate mail is most often misclassified).\r\nlet totalByDomain = EmailEvents | where EmailDirection == \"Inbound\" | summarize TotalInbound = count() by SenderFromDomain;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), P2SenderDomain = tostring(R.P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| summarize FPSubmissions = count() by P2SenderDomain\r\n| join kind=leftouter (totalByDomain) on $left.P2SenderDomain == $right.SenderFromDomain\r\n| extend FPPct = iif(isnull(TotalInbound) or TotalInbound == 0, 0.0, round(FPSubmissions * 100.0 / TotalInbound, 2))\r\n| top 10 by FPSubmissions desc\r\n| project ['Sender Domain'] = P2SenderDomain, ['FP Submissions'] = FPSubmissions, ['Total Inbound'] = coalesce(TotalInbound, 0), ['FP Submission %'] = FPPct", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "18ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "FP Submission %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - top-sender-domains table", + "id": "c69b126d-9f25-44a0-b96d-601d89a563f1" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Senders in User False Positive Submissions
\r\n\r\n**Displays the top 10 email senders whose messages were reported as false positives by users (legitimate emails incorrectly flagged as threats). Helps identify senders frequently misclassified.**" + }, + "customWidth": "100", + "name": "fp user - top-senders heading", + "id": "b39966ad-2b40-4144-ae3f-c7ac6b9fb97c" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top 10 email senders reported as false positives by users, with each sender's total inbound volume and the share reported as FP.\r\nlet totalBySender = EmailEvents | where EmailDirection == \"Inbound\" | summarize TotalInbound = count() by SenderMailFromAddress;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\"\r\n| summarize FPSubmissions = count() by SenderMailFromAddress\r\n| join kind=leftouter (totalBySender) on SenderMailFromAddress\r\n| extend FPPct = iif(isnull(TotalInbound) or TotalInbound == 0, 0.0, round(FPSubmissions * 100.0 / TotalInbound, 2))\r\n| top 10 by FPSubmissions desc\r\n| project ['Sender Address'] = SenderMailFromAddress, ['FP Submissions'] = FPSubmissions, ['Total Inbound'] = coalesce(TotalInbound, 0), ['FP Submission %'] = FPPct", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Inbound", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "18ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "FP Submission %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - top-senders table", + "id": "077ab610-58ed-4d23-886c-dbf912cef2d7" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Subjects in User False Positive Submissions
\r\n\r\n**Displays the top 10 email subjects reported as false positives by users (legitimate messages incorrectly flagged as threats). Helps identify common patterns in misclassified emails.**" + }, + "customWidth": "100", + "name": "fp user - top-subjects heading", + "id": "a5b939e1-0fbf-4ee1-a6a3-01fa7639af3a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top 10 email subjects reported as false positives by users, with how many distinct recipients reported each (a subject reported by many users is a broad misclassification pattern).\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\"\r\n| summarize FPSubmissions = count(), DistinctRecipients = dcount(RecipientObjectId) by Subject\r\n| top 10 by FPSubmissions desc\r\n| project ['Subject'] = Subject, ['FP Submissions'] = FPSubmissions, ['Distinct Recipients'] = DistinctRecipients", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Subject", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "70ch" + } + }, + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Distinct Recipients", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "18ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - top-subjects table", + "id": "71d5c290-f5d0-493c-b821-b5345dbe7312" + }, + { + "type": 1, + "content": { + "json": "### Top 10 Intra-Org Senders in User False Positive Submissions
\r\n\r\n**Displays the top 10 internal senders whose emails were reported as false positives by users (legitimate intra-org messages incorrectly flagged as threats). Helps identify internal communication patterns causing misclassification.**" + }, + "customWidth": "100", + "name": "fp user - intraorg-senders heading", + "id": "1d38f458-dfde-4608-ad7d-ee8628e85ee7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top 10 internal senders whose emails were reported as false positives by users, with total intra-org volume and the share reported as FP.\r\nlet totalBySender = EmailEvents | where EmailDirection == \"Intra-org\" | summarize TotalIntraOrg = count() by SenderMailFromAddress;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Intra-org\"\r\n| summarize FPSubmissions = count() by SenderMailFromAddress\r\n| join kind=leftouter (totalBySender) on SenderMailFromAddress\r\n| extend FPPct = iif(isnull(TotalIntraOrg) or TotalIntraOrg == 0, 0.0, round(FPSubmissions * 100.0 / TotalIntraOrg, 2))\r\n| top 10 by FPSubmissions desc\r\n| project ['Sender Address'] = SenderMailFromAddress, ['FP Submissions'] = FPSubmissions, ['Total Intra-org'] = coalesce(TotalIntraOrg, 0), ['FP Submission %'] = FPPct", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "FP Submissions", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + }, + { + "columnMatch": "Total Intra-org", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "18ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "FP Submission %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "16ch" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "fp user - intraorg-senders table", + "id": "b6699a7f-897a-4016-ae2c-d816f3a9492b" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "10" + }, + "name": "fp user - group", + "styleSettings": { + "showBorder": true + }, + "id": "2ad3311e-e92b-4a49-bdd0-775f085c4587" + }, + { + "type": 1, + "content": { + "json": "# File Malware Detections (SharePoint, Teams and OneDrive)\r\n\r\n---\r\n\r\nThis tab provides insights into malicious file detections across Microsoft collaboration platforms such as SharePoint, OneDrive, and Teams.\r\n\r\n[

Safe Attachments for SharePoint, OneDrive, and Microsoft Teams

](https://learn.microsoft.com/en-us/defender-office-365/safe-attachments-for-spo-odfb-teams-about)\r\n[

Built-in virus protection in SharePoint, SharePoint Embedded, OneDrive, and Microsoft Teams

](https://learn.microsoft.com/en-us/defender-office-365/anti-malware-protection-for-spo-odfb-teams-about) " + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "9" + }, + "name": "filemal - tab description", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "cefcac88-f373-4748-b0ea-e7600f63edd7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Microsoft Defender for Office 365 value for files in SharePoint / OneDrive / Teams: total files processed, how many had a malware detection, and how many were scanned with no detection. A per-period Trend series feeds the tile sparkline.\r\nlet gran = {Granularity};\r\nlet base = FileMaliciousContentInfo;\r\nlet counts = union\r\n(base | summarize Count = count() | extend Cat = \"Total Files Processed (SPO/ODB/Teams)\", Ord = 1),\r\n(base | where isnotempty(ThreatTypes) | summarize Count = count() | extend Cat = \"Files with Malware Detected\", Ord = 2),\r\n(base | where isempty(ThreatTypes) | summarize Count = count() | extend Cat = \"Files Scanned - No Detection\", Ord = 3);\r\nlet tagged = union\r\n(base | extend Cat = \"Total Files Processed (SPO/ODB/Teams)\"),\r\n(base | where isnotempty(ThreatTypes) | extend Cat = \"Files with Malware Detected\"),\r\n(base | where isempty(ThreatTypes) | extend Cat = \"Files Scanned - No Detection\");\r\nlet trends = tagged | make-series Trend = count() default = 0 on Timestamp step gran by Cat;\r\ncounts\r\n| join kind=leftouter (trends) on Cat\r\n| sort by Ord asc\r\n| project Count, Details = Cat, Trend", + "size": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "tiles", + "tileSettings": { + "titleContent": { + "columnMatch": "Details", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "Count", + "formatter": 12, + "formatOptions": { + "min": 0, + "palette": "blue" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + "secondaryContent": { + "columnMatch": "Trend", + "formatter": 21, + "formatOptions": { + "min": 0, + "palette": "blue" + } + }, + "showBorder": true, + "size": "auto" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "filemal - MDO value tiles", + "id": "843e58a9-6324-4a90-a652-bfb0549e79dc", + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "9" + } + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
File Malware Detection (SharePoint, OneDrive, and Teams)\r\n
\r\n\r\nThis section monitors malware detections in files stored across Microsoft 365 collaboration platforms. Microsoft Defender for Office 365 and built-in SharePoint Online antivirus work together to scan files uploaded to SharePoint, OneDrive, and Teams. Understanding file-based malware patterns helps protect collaborative workspaces and identify potential security risks in shared content.

**Recommended action:** For repeat file owners or sites, investigate possible compromise and confirm Safe Attachments for SharePoint, OneDrive and Teams is enabled." + }, + "name": "filemal - section header", + "id": "373fe4e5-fc90-49cf-93ba-c8b100efce57" + }, + { + "type": 1, + "content": { + "json": "### File Malware Detection Trend
\r\n\r\n**This visual tracks the volume (per {Granularity}) of malware detections in files across all Microsoft 365 workloads. Spikes in detection activity may indicate targeted attacks or emerging malware campaigns affecting collaborative platforms. Regular monitoring helps identify unusual patterns that require investigation.**" + }, + "name": "filemal - trend heading", + "id": "30145585-8998-443a-b6ec-062d136c621f" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total files located on SharePoint, OneDrive and Teams with Malware detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(FileMaliciousContentInfo\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Files']=coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "tileSettings": { + "showBorder": false + }, + "graphSettings": { + "type": 0 + }, + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Files", + "color": "blueDark" + } + ], + "showDataPoints": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "filemal - detection trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "d39cea9b-75a8-4c29-bfdb-2e0db855e98a" + }, + { + "type": 1, + "content": { + "json": "### Malware Family Analysis - Defender for Office 365\r\n**Provides a breakdown of malware detections in files scanned by Microsoft Defender for Office 365 (Safe Attachments detonation) across SharePoint, OneDrive, and Teams. The table lists each malware family with total detections, distinct files, affected locations and when it was last seen, helping identify dominant threats and their spread across collaboration platforms.**" + }, + "customWidth": "100", + "name": "filemal - family MDO heading", + "id": "4e330873-f732-4d37-a7b0-dced08b019b0" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query summarizes File malware detections by Microsoft Defender for Office 365 (Safe Attachments detonation) into a per-family table: total detections, distinct files, affected locations (file owner or site) and when the family was last seen.\r\nFileMaliciousContentInfo\r\n| where tostring(DetectionMethods) contains \"detonation\"\r\n| extend Owner = iff(isnotempty(FileOwnerUpn), FileOwnerUpn, strcat(\"Site: \", tostring(split(FolderPath, \"/\")[4])))\r\n| summarize ['Files']=count(), ['Distinct Files']=dcount(SHA256), ['Affected Locations']=dcount(Owner), ['Last Seen']=max(Timestamp) by ThreatNames\r\n| sort by ['Files'] desc\r\n| project ['Threat Name']=ThreatNames, ['Files'], ['Distinct Files'], ['Affected Locations'], ['Last Seen']", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "tileSettings": { + "showBorder": false, + "titleContent": { + "columnMatch": "RawinfoVirusInfo", + "formatter": 1 + }, + "leftContent": { + "columnMatch": "count_", + "formatter": 12, + "formatOptions": { + "palette": "auto" + }, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "graphSettings": { + "type": 0, + "topContent": { + "columnMatch": "RawinfoVirusInfo", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "count_", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "chartSettings": { + "xAxis": "RawinfoVirusInfo", + "createOtherGroup": 15 + }, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Files", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "filemal - family MDO table", + "id": "c3fbb1c9-be67-43b9-9a32-7fb265a84ffc" + }, + { + "type": 1, + "content": { + "json": "### Malware Family Analysis - SharePoint AV\r\n**Provides a breakdown of malware detections in files across SharePoint, OneDrive, and Teams caught by the built-in SharePoint antivirus (Antimalware engine). The table lists each malware family with total detections, distinct files, affected locations and when it was last seen, helping identify prevalent threats and their spread across collaboration environments.**" + }, + "customWidth": "100", + "name": "filemal - family SPO-AV heading", + "id": "331a8361-6e81-4615-b33a-97ebb3e31529" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query summarizes File malware detections by the built-in SharePoint antivirus (Antimalware engine) into a per-family table: total detections, distinct files, affected locations (file owner or site) and when the family was last seen.\r\nFileMaliciousContentInfo\r\n| where tostring(DetectionMethods) contains \"Antimalware engine\"\r\n| extend Owner = iff(isnotempty(FileOwnerUpn), FileOwnerUpn, strcat(\"Site: \", tostring(split(FolderPath, \"/\")[4])))\r\n| summarize ['Files']=count(), ['Distinct Files']=dcount(SHA256), ['Affected Locations']=dcount(Owner), ['Last Seen']=max(Timestamp) by ThreatNames\r\n| sort by ['Files'] desc\r\n| project ['Threat Name']=ThreatNames, ['Files'], ['Distinct Files'], ['Affected Locations'], ['Last Seen']", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "chartSettings": { + "xAxis": "RawinfoVirusInfo", + "createOtherGroup": 10 + }, + "gridSettings": { + "formatters": [ + { + "columnMatch": "Files", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "filemal - family SPO-AV table", + "id": "bbcdccd9-eedb-476a-a0e7-8504f8770229" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by Location
\r\n\r\n**Displays the number of malware detections grouped by specific SharePoint sites or OneDrive locations. Helps identify which sites have the highest volume of detected threats for targeted remediation and security hardening.**" + }, + "customWidth": "50", + "name": "filemal - by-location heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "c5668d6e-7c0e-4ce3-9509-ca93dda3efad" + }, + { + "type": 1, + "content": { + "json": "### Malware Detections by Application
\r\n\r\n**Summarizes malware detections across Microsoft collaboration apps, including SharePoint, OneDrive, and Teams. Helps identify which applications experience the highest volume of detected threats for targeted security measures.**" + }, + "customWidth": "50", + "name": "filemal - by-application heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "07e64ca9-04a2-44b2-a044-e927bc73ef1b" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query lists total Malware detections of files on SharePoint, OneDrive and Teams by the location (site or personal path) where the file resides.\r\nFileMaliciousContentInfo\r\n| extend ['Site / Location'] = tostring(split(FolderPath, '/')[4])\r\n| summarize ['Detections'] = count() by ['Site / Location']\r\n| sort by ['Detections'] desc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "filemal - by-location table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3ce3ea65-a4df-450f-871c-8956d59818a9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises total Malware detections of files located on SharePoint, OneDrive and Teams summarizing the data by the Microsoft collaboration application (workload).\r\nFileMaliciousContentInfo\r\n| summarize count() by Workload\r\n| sort by count_ desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "filemal - by-application pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "003afc8e-0403-4aa9-9084-a3c2e435216a" + }, + { + "type": 1, + "content": { + "json": "### Top File Owners Holding Malware\r\n**Lists the users (or the SharePoint/Teams site, when a file has no individual owner) whose files in SharePoint, OneDrive or Teams were flagged as malware, with the count of malicious files, distinct files, affected workloads and sample threat names. Helps pinpoint the accounts and collaboration locations most affected by malicious content for targeted remediation.**" + }, + "customWidth": "100", + "name": "filemal - top-owners heading", + "id": "c2f8d3b5-0a4e-4b7c-9d23-8e6f0a1b2c34" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Top file owners (or the SharePoint/Teams site, when a file has no user owner) whose SharePoint/OneDrive/Teams files were flagged as malware, with distinct files, workloads and sample threat names.\r\nFileMaliciousContentInfo\r\n| extend Owner = iff(isnotempty(FileOwnerUpn), FileOwnerUpn, strcat(\"Site: \", tostring(split(FolderPath, \"/\")[4])))\r\n| summarize ['Malicious Files'] = count(),\n ['Distinct Files'] = dcount(SHA256),\n ['Workloads'] = make_set(Workload, 3),\n ['Sample Threats'] = make_set_if(ThreatNames, isnotempty(ThreatNames), 5),\n ['Last Seen'] = max(Timestamp)\n by ['Owner']=Owner\n| top 20 by ['Malicious Files']", + "size": 0, + "title": "Top File Owners Holding Malware", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Malicious Files", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Distinct Files", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "filemal - top-owners table", + "id": "36d9a683-9f9d-4a70-84d9-ec351542f827" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "9" + }, + "name": "filemal - group", + "styleSettings": { + "showBorder": true + }, + "id": "50886cd9-87bf-4a84-bd80-d7f44441b3f7" + }, + { + "type": 1, + "content": { + "json": "# Post-Delivery & Quarantine Insights\r\n\r\n---\r\nThis tab covers what happens to threats **after delivery**: Zero-hour Auto Purge (ZAP) remediation of malicious messages already in mailboxes, and quarantine management - what is held, released, and by whom. Together they show how effectively post-delivery response contains threats that reached the inbox." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "11" + }, + "name": "postdelivery - tab description", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "93371620-d968-4987-bddd-6c9b9e5a0344" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Post Delivery Protection offered by ZAP\r\n
\r\n\r\nThis section provides insights into Microsoft Defender for Office 365's post-delivery protection capabilities through Zero-Hour Auto Purge (ZAP). ZAP is a critical security feature that continuously monitors delivered emails and automatically removes messages that are later identified as malicious. These visuals help track ZAP effectiveness, response times, and remediation patterns.

**Recommended action:** High post-delivery ZAP volume means threats are reaching inboxes before being caught - review pre-delivery filtering and detection latency." + }, + "name": "postdelivery - section header", + "id": "b22ee5f1-a2dc-4509-92a3-1dbcad3a6ee7" + }, + { + "type": 1, + "content": { + "json": "### ZAP Post-Delivery Actions (per {Granularity})
\r\n\r\n**Shows the count (per {Granularity}) of emails that were remediated post-delivery by Zero-Hour Auto Purge (ZAP). Helps track how often threats are detected and removed after reaching user mailboxes.**" + }, + "customWidth": "50", + "name": "postdelivery - zap-actions heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "af1aa73f-d952-4827-bcc9-b97a19016829" + }, + { + "type": 1, + "content": { + "json": "### ZAP Actions by Detection Type (per {Granularity})
\r\n\r\n**Visualizes the count (per {Granularity}) of post-delivery remediation actions performed by Zero-Hour Auto Purge (ZAP), broken down by detection type (Spam ZAP, Phish ZAP, Malware ZAP). Helps track which threat categories are most frequently remediated after delivery.**" + }, + "customWidth": "50", + "name": "postdelivery - by-detection-type heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "8eb38cb1-4e2d-435a-81be-e661c9b89ff4" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of emails that had a post delivery action from zero-hour auto purge.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailPostDeliveryEvents \r\n| where ActionType has \"ZAP\"\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Zapped Emails'] = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Zapped Emails", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "postdelivery - zap-actions trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "dd60fd71-4e14-4b38-ad22-39f1e3e3f55a" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of emails that had a post delivery action from zero-hour auto purge, summarizing by phish,spam or malware detection action\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailPostDeliveryEvents\r\n| where ActionType has \"ZAP\"\r\n| summarize [\"Spam ZAP\"]=countif(ActionType has 'Spam ZAP'), [\"Phish ZAP\"]=countif(ActionType has 'Phish ZAP'), [\"Malware ZAP\"]=countif(ActionType has 'Malware ZAP') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, [\"Spam ZAP\"]=coalesce([\"Spam ZAP\"],0), [\"Phish ZAP\"]=coalesce([\"Phish ZAP\"],0), [\"Malware ZAP\"]=coalesce([\"Malware ZAP\"],0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "50", + "name": "postdelivery - by-detection-type trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "511f4a43-9f56-48ad-a644-b72722af82d7" + }, + { + "type": 1, + "content": { + "json": "### ZAP Remediation by Destination
\r\n\r\n**This visual shows where ZAP moves malicious emails during remediation. Post-delivery actions can send emails to different locations: Quarantine (isolated for admin review), Deleted Items (soft delete), Junk Email folder, or back to Inbox (for false positive corrections). Understanding these patterns helps evaluate ZAP policy configurations and ensures malicious content is properly isolated from users.**" + }, + "name": "postdelivery - by-destination heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "dc7b9b6c-36fb-4ae4-a3e8-ff11da681c97" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of emails that had a post delivery action, summarizing the data daily by the final location as a result of the action\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailPostDeliveryEvents\r\n| where ActionType contains \"ZAP\"\r\n| summarize Quarantine=countif(DeliveryLocation has 'Quarantine'), ['Deleted Items']=countif(DeliveryLocation has 'Delete'), Junk=countif(DeliveryLocation has 'Junk'), Inbox=countif(DeliveryLocation has 'Inbox') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, Quarantine=coalesce(Quarantine,0), ['Deleted Items']=coalesce(['Deleted Items'],0), Junk=coalesce(Junk,0), Inbox=coalesce(Inbox,0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "name": "postdelivery - by-destination trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "cbb737ef-1c7e-4b3e-af26-a553fe6147c9" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "11" + }, + "name": "postdelivery - group", + "styleSettings": { + "showBorder": true + }, + "id": "e436ecee-8886-4179-a578-9e4a42e75b9e" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Quarantine Management and Insights\r\n
\r\n\r\nThis section provides comprehensive insights into quarantine operations, including release patterns, detection methods, and threat categorization. It helps security teams understand what types of threats are being quarantined and monitor quarantine release activity to identify potential false positives or security policy effectiveness.

**Recommended action:** Investigate high release rates - they indicate false positives or risky user releases; review quarantine policies and release permissions." + }, + "name": "quarantine - section header", + "id": "c4862977-6670-4716-8109-252a361d7478" + }, + { + "type": 1, + "content": { + "json": "### Quarantine Release Trend
\r\n\r\n**This visual displays the per-{Granularity} trend of emails released from quarantine by administrators. Monitoring this metric helps identify patterns in quarantine management and potential areas where policy adjustments may be needed to reduce unnecessary quarantines.**" + }, + "name": "quarantine - release-trend heading", + "id": "8526a5e0-c6a4-44e3-b00a-5e135374f58e" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of emails released from quarantine\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailPostDeliveryEvents\r\n| where ActionTrigger has \"AdminAction\" and Action has 'Quarantine release'\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Quarantine Releases'] = coalesce(Count, 0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "chartSettings": { + "seriesLabelSettings": [ + { + "seriesName": "Quarantine Releases", + "color": "blueDark" + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - release trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "3625d1f1-f34a-4cbf-a78f-eb2e5506bad4" + }, + { + "type": 1, + "content": { + "json": "### Quarantine Release Percentage
\r\n\r\n**Calculates the percentage of quarantined emails that were successfully released compared to the total quarantined messages. This metric helps measure engagement with quarantine and assess the effectiveness of quarantine policies.**" + }, + "customWidth": "40", + "name": "quarantine - release-pct heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "e3a9502c-9030-4621-b248-55cdf69f81ae" + }, + { + "type": 1, + "content": { + "json": "### Quarantine Release Analysis by Detection Type
\r\n\r\n**For each detection technology, this shows the share of its quarantined emails that were later released from quarantine (Release % = released / quarantined). A high release rate flags a detector that may be over-flagging legitimate mail - a strong candidate for policy or rule tuning. The Released count shows the volume behind each rate.**" + }, + "customWidth": "60", + "name": "quarantine - release-by-detection heading", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "976fc90f-bf46-4315-b05e-4e501b37b869" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the percentage of emails released from quarantine out of the total ammount of quarantined emails\r\nlet Quarantine_Releases = toscalar(EmailPostDeliveryEvents\r\n| where Action == \"Quarantine release\"\r\n| join kind=leftouter (EmailEvents | where DeliveryLocation == \"Quarantine\") on NetworkMessageId\r\n| summarize count());\r\nlet Quarantined_Mailflow = toscalar(EmailEvents | where DeliveryLocation == \"Quarantine\"\r\n| summarize count());\r\nprint\r\nQuarantine_Releases = toreal(Quarantine_Releases),\r\nQuarantined_Mailflow = toreal(Quarantined_Mailflow),\r\nRelease_Percentage = abs(round(((toreal(Quarantine_Releases)/toreal(Quarantined_Mailflow))*100),2))", + "size": 0, + "showAnalytics": true, + "title": " ", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "stat", + "tileSettings": { + "titleContent": { + "columnMatch": "Release_Percentage", + "formatter": 12, + "formatOptions": { + "palette": "none" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + }, + "showBorder": true, + "sortCriteriaField": "Release_Percentage", + "size": "auto" + }, + "statSettings": { + "valueField": "Release_Percentage", + "valueAggregation": "None", + "colorSettings": { + "type": "thresholds", + "mode": "foreground", + "heatmapPalette": "greenRed", + "thresholdsGrid": [ + { + "operator": "<", + "thresholdValue": "5", + "representation": "green" + }, + { + "operator": ">", + "thresholdValue": "5", + "representation": "redDark" + } + ] + }, + "iconSettings": { + "thresholdsGrid": [] + }, + "numberFormatSettings": { + "unit": 1, + "options": { + "style": "decimal" + } + }, + "tagText": "Quarantine Release Percentage", + "valueFontStyle": "mega", + "tagTextPosition": "bottom" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "40", + "name": "quarantine - release-pct stat", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "64e157ce-2f6a-423f-9ce5-eade8b6f41d5" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Per detection technology: the share of its quarantined emails that were later released from quarantine.\r\n//Release % = released / quarantined for that detection technology - a high rate flags a detector that may be over-flagging legitimate mail (potential false positives). Detectors with fewer than 10 quarantined emails are excluded so the rate is statistically meaningful.\r\nEmailEvents\r\n| where DeliveryLocation == \"Quarantine\"\r\n| extend MDO_detection = parse_json(DetectionMethods)\r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0]))\r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\")\r\n| where FirstSubcategory contains \"Malware\" or FirstSubcategory contains \"Phish\" or FirstSubcategory contains \"Spam\"\r\n| join kind=leftouter (\r\n EmailPostDeliveryEvents\r\n | where Action == \"Quarantine release\"\r\n | distinct NetworkMessageId\r\n | extend ReleasedFlag = \"yes\"\r\n ) on NetworkMessageId\r\n| summarize Quarantined = dcount(NetworkMessageId), Released = dcountif(NetworkMessageId, ReleasedFlag == \"yes\") by FirstSubcategory\r\n| where Quarantined >= 10 and Released > 0\r\n| extend ReleaseRate = round(Released * 100.0 / Quarantined, 2)\r\n| project ['Detection Type']=FirstSubcategory, ['Quarantined Emails']=Quarantined, ['Released']=Released, ['Release %']=ReleaseRate\r\n| order by ['Release %'] desc", + "size": 3, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Quarantined Emails", + "formatter": 0, + "formatOptions": { + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Released", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Release %", + "formatter": 4, + "formatOptions": { + "palette": "red", + "min": 0, + "max": 20, + "customColumnWidthSetting": "90px" + }, + "numberFormat": { + "unit": 1, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "60", + "name": "quarantine - release-by-detection pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "9a6d21b7-7542-4ae5-8f3f-b18474b52a20" + }, + { + "type": 1, + "content": { + "json": "### Malware Email Quarantine Analysis
\r\n\r\n**These visuals break down quarantined malware emails by their specific detection methods. Microsoft Defender for Office 365 employs multiple malware detection techniques including file detonation, file reputation analysis, and advanced filters. Understanding which detection methods are most frequently triggered helps optimize anti-malware policies and identify emerging malware tactics.
The line chart shows per-{Granularity} trends across all malware detection methods, while the table provides an overall distribution of detection reasons.**" + }, + "name": "quarantine - malware heading", + "id": "59f84161-a010-44c2-aec1-b72ed98ccdff" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of malware emails that are quarantined, summarized daily by the detection method\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has \"Malware\" and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Details = parse_json(DetectionMethods).Malware to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - malware trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "a54a8daf-0be2-4c0e-a8d7-4ff0e0879fd2" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of malware emails that are quarantined, summarized by the detection method\r\n//(QA 2026-07-14) mv-expand over DetectionMethods.Malware (matching the sibling line chart) so each slice is a clean single method name instead of a bracketed JSON array.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has 'Malware' and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Malware = parse_json(DetectionMethods).Malware to typeof(string)\r\n| where isnotempty(Malware)\r\n| summarize count() by Malware\r\n| sort by count_ desc\r\n| project ['Detection Technology']=Malware, ['Detections']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - malware table", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "b5d0d022-cf41-47e5-ae06-cf2176b47758" + }, + { + "type": 1, + "content": { + "json": "### Phishing Email Quarantine Analysis
\r\n\r\n**These visuals break down quarantined phishing emails by their specific detection methods. Microsoft Defender for Office 365 employs multiple phishing detection techniques including impersonation protection, URL detonation, spoof detection, and advanced filters. Understanding which detection methods are most frequently triggered helps optimize anti-phishing policies and identify emerging phishing tactics.
The line chart shows per-{Granularity} trends across all phishing detection methods, while the table provides an overall distribution of detection reasons.**" + }, + "name": "quarantine - phish heading", + "id": "aca50104-cb68-4a8f-82ee-ea8eee25fe14" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of phish emails that are quarantined, summarized daily by the detection method\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has \"Phish\" and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - phish trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "57151360-0577-45ce-8fc6-10a3790865ce" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of phish emails that are quarantined, summarized by the detection method\r\n//(QA 2026-07-14) mv-expand over DetectionMethods.Phish (matching the sibling line chart) so each slice is a clean single method name instead of a bracketed JSON array.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has 'Phish' and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Phish = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Phish)\r\n| summarize count() by Phish\r\n| sort by count_ desc\r\n| project ['Detection Technology']=Phish, ['Detections']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - phish pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "df78c64b-76f6-4980-80df-d0d432e780a5" + }, + { + "type": 1, + "content": { + "json": "### Spam Email Quarantine Analysis
\r\n\r\n**These visuals provide detailed insights into quarantined spam emails categorized by detection methods. Spam detection technologies include advanced filters, general filters, bulk email filtering, reputation-based systems (IP, domain, URL), and mixed analysis detection. Analyzing spam quarantine patterns helps fine-tune spam filtering policies to balance security with user productivity and reduce false positives.
The line chart displays per-{Granularity} trends for each spam detection method, while the table shows the overall distribution.**" + }, + "name": "quarantine - spam heading", + "id": "e131910f-0233-474a-a9b8-9f70a49246cf" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the ammount of spam emails that are quarantined, summarized daily by the detection method\r\nlet gran = {Granularity};\r\nlet baseQuery = EmailEvents\r\n| where DetectionMethods has \"Spam\" and DeliveryLocation == \"Quarantine\";\r\nlet agg = materialize(baseQuery\r\n| mv-expand Details = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - spam trend", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "5762bcc7-bbda-4a3d-91cf-de18fbdd2775" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the total ammount of spam emails that are quarantined, summarized by the detection method\r\n//(QA 2026-07-14) mv-expand over DetectionMethods.Spam (matching the sibling line chart) so each slice is a clean single method name instead of a bracketed JSON array.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has 'Spam' and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Spam = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Spam)\r\n| summarize count() by Spam\r\n| sort by count_ desc\r\n| project ['Detection Technology']=Spam, ['Detections']=count_", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "formatters": [ + { + "columnMatch": "Detections", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "30ch" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal" + } + } + } + ], + "filter": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "quarantine - spam pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "2995f55b-17f9-458b-8630-e0370d14522a" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "11" + }, + "name": "quarantine - group", + "id": "430294af-c68f-4427-8b55-d552a3d89d42", + "styleSettings": { + "showBorder": true + } + }, + { + "type": 1, + "content": { + "json": "# Security Operations Center (SOC) Insights \r\n\r\n---\r\n\r\nThis tab provides a view for security operations. Combines incident response metrics with investigation insights to evaluate the effectiveness of both automated systems and manual interventions." + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "13" + }, + "name": "soc - tab description", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "fd65243c-514c-4813-978f-fb908226d049" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Security Incident Response Metrics\r\n
\r\n\r\n**Operational efficiency insights.** Tracks incident volume, resolution speed, automation efficacy, and classification accuracy to evaluate SOC performance.

**Recommended action:** Track mean time to close by severity against your SLA and investigate any severity trending upward." + }, + "name": "soc - incident-metrics section header", + "id": "f92c3e24-3e0f-4f4c-8ee9-3ec60832f7b1" + }, + { + "type": 1, + "content": { + "json": "### Email Security Incidents
\r\n\r\n**These visuals display the per-{Granularity} trend of email-related security incidents, as well as the proportion of email incidents compared to the total number of incidents in Defender.**" + }, + "name": "soc - email-incidents heading", + "id": "c1cf6796-6071-4d2e-bf2c-c5e8d2a99a12" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "customWidth": "75", + "name": "soc - email-incidents trend", + "id": "e23cfcda-1017-4fd0-ac71-8a861c450f71" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "customWidth": "25", + "name": "soc - incident-category pie", + "id": "baae2150-1b04-43b4-9713-48fd3cc6247f" + }, + { + "type": 1, + "content": { + "json": "### Average Incident Time To Close (minutes)\r\n**This visual displays the average time, in minutes, to close email-related security incidents (per {Granularity}), split by severity, so you can see how resolution speed changes over time. Reference SLA targets: High 60, Medium 120, Low 240, Informational 480 minutes.**" + }, + "name": "soc - time-to-close heading", + "id": "e23ccc6c-b0f0-407b-8e01-d8b69c40a745" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "name": "soc - sla-by-severity trend", + "id": "3f7d1f17-8d2f-4a1b-a97e-17973812ca6f" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "### Closed Incident Classification (True Positive vs False Positive)\r\n\r\nThis visual shows the distribution of closed email-related incidents classified as True Positive versus False Positive. It helps assess detection accuracy and provides insight into validation trends." + }, + "customWidth": "33.3", + "name": "soc - classification heading", + "styleSettings": { + "margin": "10px" + }, + "id": "48db10ce-8246-4f5e-8b68-f618d9c7f77c" + }, + { + "type": 1, + "content": { + "json": "### True Positive Incident Classification Rate\r\n\r\nThis visual displays the percentage of email-related incidents confirmed as True Positive. It offers a clear measure of classification accuracy and highlights changes in detection effectiveness over time." + }, + "customWidth": "33.3", + "name": "soc - tp-rate heading", + "styleSettings": { + "margin": "10px" + }, + "id": "34a84dbf-609a-407f-afef-f1592eb4a92b" + }, + { + "type": 1, + "content": { + "json": "### Incidents Automated vs Manual Closure\r\n\r\nThis visual illustrates the proportion of email-related incidents closed automatically versus manually. It provides visibility into operational efficiency and the impact of automation on incident resolution.\r\n
⚠️ *You will have to review the underlying query and add any automation system specific to your organization.*" + }, + "customWidth": "33.3", + "name": "soc - auto-vs-manual-closure heading", + "styleSettings": { + "margin": "10px" + }, + "id": "a1fd9136-7a12-4d80-b3e1-e2704a84f734" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "customWidth": "33.3", + "name": "soc - classification pie", + "styleSettings": { + "margin": "10px" + }, + "id": "cfa5b7c5-50cc-4b3b-8bba-1a93c57bff43" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "customWidth": "33.3", + "name": "soc - tp-rate stat", + "styleSettings": { + "margin": "10px" + }, + "id": "eca235aa-38aa-46dd-a569-74dd8f83b2f0" + }, + { + "type": 1, + "content": { + "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." + }, + "customWidth": "33.3", + "name": "soc - closure pie", + "styleSettings": { + "margin": "10px" + }, + "id": "a4bc160f-1ba6-4779-86cd-ef44422f1e29" + } + ] + }, + "name": "soc - incident-insights group", + "id": "3083ac4d-0bdd-4db7-a5f0-0d41cb67a4eb" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "13" + }, + "name": "soc - incident-metrics group", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "18ff8970-e5f6-4c51-918a-aa693a45d18f" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Investigation & Response Actions\r\n
\r\n\r\n**Remediation efficacy analysis.** Compares automated (AIR) and manual admin actions to evaluate response times and investigation outcomes.\r\n

**Recommended action:** Reduce AIR pending-action latency by reviewing why approvals take long, and increase automation where it is safe to do so." + }, + "name": "soc - air section header", + "id": "5e0b06c8-7774-4eb4-8b7f-572b3732de84" + }, + { + "type": 1, + "content": { + "json": "### Automated Investigation and Response (AIR) Actions (per {Granularity})\r\n\r\nThis visual shows the per-{Granularity} trend of Automated Investigation and Response (AIR) actions, including the number of successful and failed attempts (because of prior remediation)." + }, + "customWidth": "100", + "name": "soc - air-actions heading", + "styleSettings": { + "margin": "10px" + }, + "id": "05f14dec-e76c-413c-83a0-31a05dce65e7" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query attempts to show AIR Efficiency Over Time by displaying the number of successes and failures over time\r\nEmailPostDeliveryEvents\r\n| where ActionType =~ \"Automated Remediation\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Count = count() by bin(Timestamp, {Granularity}), ActionResult", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "graphSettings": { + "type": 0, + "topContent": { + "columnMatch": "AlertId", + "formatter": 1 + }, + "centerContent": { + "columnMatch": "Count", + "formatter": 1, + "numberFormat": { + "unit": 17, + "options": { + "maximumSignificantDigits": 3, + "maximumFractionDigits": 2 + } + } + } + }, + "chartSettings": { + "xAxis": "Timestamp" + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "soc - air-efficiency trend", + "styleSettings": { + "margin": "10px" + }, + "id": "ae2a1850-5b7e-49f7-bac4-d888053ab49b" + }, + { + "type": 1, + "content": { + "json": "### Automated Investigation and Response (AIR) Response Time After Email Delivery (per {Granularity})\r\n\r\nThis visual displays the average (per {Granularity}), 80th percentile (p80), 90th percentile (p90) and 99th percentile (p99) time needed, measured in minutes, from email delivery to AIR action. It serves as a SOC metric to monitor responsiveness (security team members reviewing and manually approving AIR Pending Actions) and identify potential latency in automated incident handling. If the latency is high focus on reviewing why reviwing AIR Pending Actions takes longer time for admins and consider auto-aproval of URL, Files and Email clusters. \r\n" + }, + "customWidth": "100", + "name": "soc - air-response-time heading", + "styleSettings": { + "margin": "10px" + }, + "id": "98c66d9e-efdf-40fc-b8b0-be35d7fd97a9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// SOC metric: Daily average/p75 delay (in minutes) from email delivery to AIR action\r\nlet deliveries = EmailEvents\r\n | where DeliveryAction == \"Delivered\"// delivered emails\r\n | extend MsgKey = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n | summarize FirstDelivery = min(Timestamp) by MsgKey, Threat = tostring(ThreatTypes);\r\nlet remediations = EmailPostDeliveryEvents\r\n | where ActionType =~ \"Automated Remediation\"// automated remediation events\r\n | extend MsgKey = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n | summarize FirstRemediation = min(Timestamp) by MsgKey;\r\ndeliveries\r\n| join kind=inner remediations on MsgKey\r\n| extend DelayMinutes = datetime_diff(\"minute\", FirstRemediation, FirstDelivery)\r\n| where DelayMinutes >= 0\r\n| summarize ['Avg (min)'] = avg(DelayMinutes),\r\n ['P80 (min)'] = percentile(DelayMinutes, 80),\r\n ['P90 (min)'] = percentile(DelayMinutes, 90),\r\n ['P99 (min)'] = percentile(DelayMinutes, 99),\r\n CountEmails = count()\r\n by bin(FirstRemediation, 1d) ", + "size": 0, + "aggregation": 3, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "areachart", + "gridSettings": { + "sortBy": [ + { + "itemKey": "FirstRemediation", + "sortOrder": 1 + } + ] + }, + "sortBy": [ + { + "itemKey": "FirstRemediation", + "sortOrder": 1 + } + ], + "chartSettings": { + "xAxis": "FirstRemediation", + "yAxis": [ + "P99 (min)", + "P90 (min)", + "P80 (min)", + "Avg (min)" + ], + "showLegend": true + }, + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "100", + "name": "soc - air-latency area", + "styleSettings": { + "margin": "10px" + }, + "id": "900383f1-6443-4d50-b15d-26e4ac11b255" + }, + { + "type": 1, + "content": { + "json": "### Automated Investigation and Response (AIR) Investigation Results Trend\r\n\r\nThis visual displays the per-{Granularity} trend of AIR investigation outcomes, categorized as **Threat Detected** or **Clean**. It helps track the effectiveness of automated investigations over time and highlights patterns in threat detection." + }, + "customWidth": "67", + "name": "soc - air-outcomes heading", + "styleSettings": { + "margin": "10px" + }, + "id": "d1cabfbe-6040-4b6e-9ce5-f48e9973dfc9" + }, + { + "type": 1, + "content": { + "json": "### Investigation Actions Taken: Automated Investigation and Response (AIR) vs Manual (Human)\r\n\r\nThis visual shows whether actions taken after an Automated Investigation and Response (AIR) required manual approval by an administrator or were executed automatically. It provides insight into the level of automation versus human intervention in post-investigation remediation." + }, + "customWidth": "33", + "name": "soc - air-auto-vs-manual heading", + "styleSettings": { + "margin": "10px" + }, + "id": "2f98514b-0172-4c4e-ba25-9a5e4138c570" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "// AIR investigation outcomes by day: ThreatDetected vs. Clean\r\n\r\n// Step 1: Deduplicate automated remediation events by message and recipient\r\nlet AutoRemediations = \r\n EmailPostDeliveryEvents\r\n | where ActionType == \"Automated Remediation\"\r\n | summarize arg_max(Timestamp, ActionResult) by NetworkMessageId, RecipientEmailAddress\r\n | project NetworkMessageId, RecipientEmailAddress, Timestamp;\r\n\r\n// Step 2: Derive threat verdicts using AlertEvidence\r\nlet EvidenceVerdicts =\r\n AlertEvidence\r\n | where EntityType in (\"MailMessage\", \"MailCluster\")\r\n | extend extra = todynamic(AdditionalFields)\r\n // If this is a mail cluster, use provided NetworkMessageIds array; otherwise wrap NetworkMessageId as a single-item array\r\n | extend networkIds = iff(\r\n isnull(extra.NetworkMessageIds) or array_length(extra.NetworkMessageIds) == 0,\r\n pack_array(NetworkMessageId), // create a single-element array using pack_array\r\n extra.NetworkMessageIds // use the array as-is if it exists\r\n )\r\n | mv-expand nmID = networkIds // expand to individual message IDs\r\n // Derive verdict from LastVerdict, ThreatAnalysisSummary, and ThreatIntelligence\r\n | extend \r\n lastVerdict = tolower(tostring(extra.LastVerdict)),\r\n threatAIList = extra.ThreatAnalysisSummary,\r\n threatInt = extra.ThreatIntelligence\r\n | extend verdictFromAnalysis = iff(array_length(threatAIList) > 0, tolower(tostring(threatAIList[0].Verdict)), \"\"),\r\n verdictTI = iff(array_length(threatInt) > 0, \"malicious\", \"\") // any item in ThreatIntelligence indicates malicious\r\n // Mark as threat-detected if verdict is malicious/suspicious or threat evidence is present\r\n | extend ThreatDetectedFlag = \r\n case(\r\n lastVerdict in (\"malicious\",\"suspicious\") or verdictFromAnalysis in (\"malicious\",\"suspicious\")\r\n or verdictTI == \"malicious\",\r\n true,\r\n false\r\n )\r\n // Weight mail clusters by MailCount; default to 1 for single messages\r\n | extend MailCountInt = toint(extra.MailCount)\r\n | extend Weight = iff(EntityType == \"MailCluster\", \r\n coalesce(MailCountInt, 1), // default to 1 if MailCount is missing\r\n 1)\r\n | summarize IsThreatDetected = any(ThreatDetectedFlag), \r\n WeightSum = sum(Weight) \r\n by nmID = tostring(nmID);\r\n\r\n// Step 3: Join remediation events with verdicts and aggregate by day\r\nAutoRemediations\r\n| join kind=leftouter EvidenceVerdicts on $left.NetworkMessageId == $right.nmID\r\n| extend isThreat = coalesce(IsThreatDetected, false), \r\n effectiveWeight= coalesce(WeightSum, 1)\r\n| extend InvestigationOutcome = iif(isThreat, \"Threat Detected\", \"Clean\")\r\n| summarize PreventionCount = sum(effectiveWeight) by Day = bin(Timestamp, {Granularity}), InvestigationOutcome\r\n| order by Day asc, InvestigationOutcome asc", + "size": 0, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "67", + "name": "soc - air-outcomes trend", + "styleSettings": { + "margin": "10px" + }, + "id": "18552ccb-d8d4-45c4-a3cf-072203df9325" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query shows if the action taken after an Automated Investigation required manual approval by and admin or was automatically taken\r\nEmailPostDeliveryEvents\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ActionType == \"Automated Remediation\"\r\n| summarize count() by ActionTrigger", + "size": 3, + "showAnalytics": true, + "queryType": "advancedHunting", + "visualization": "piechart", + "timeContext": { + "durationMs": 0 + } + }, + "customWidth": "33", + "name": "soc - air-auto-vs-manual pie", + "styleSettings": { + "margin": "10px", + "padding": "10px" + }, + "id": "03bc6e3c-05de-426d-91d8-b48a36b4ea74" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "### Post-Delivery Actions by Admin\r\n\r\nThis visual displays the number (per {Granularity}) of emails where an administrator performed a post-delivery action. Actions are summarized by type, including **Soft Delete**, **Hard Delete**, **Moved to Junk Folder**, **Moved to Inbox**, and **Quarantine Release**, providing insight into manual intervention trends after email delivery." + }, + "name": "soc - post-delivery-by-admin heading", + "styleSettings": { + "margin": "10px" + }, + "id": "a0961ca9-da58-49c4-9a1c-873c5569bed9" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//This query visualises the daily ammount of emails that had an admin post delivery action, summarizing the data by action type\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailPostDeliveryEvents\r\n| where ActionTrigger has \"AdminAction\"\r\n| summarize [\"Soft Delete\"]=countif(Action has 'Soft Delete'), [\"Hard Delete\"]=countif(Action has 'Hard Delete'), [\"Moved to junk folder\"]=countif(Action has 'Moved to junk folder'), [\"Moved to inbox\"]=countif(Action has 'Moved to inbox'), [\"Quarantine release\"]=countif(Action has 'Quarantine release') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, [\"Soft Delete\"]=coalesce([\"Soft Delete\"],0), [\"Hard Delete\"]=coalesce([\"Hard Delete\"],0), [\"Moved to junk folder\"]=coalesce([\"Moved to junk folder\"],0), [\"Moved to inbox\"]=coalesce([\"Moved to inbox\"],0), [\"Quarantine release\"]=coalesce([\"Quarantine release\"],0)\r\n| sort by Timestamp asc", + "size": 0, + "showAnalytics": true, + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "linechart", + "timeContext": { + "durationMs": 0 + } + }, + "name": "soc - post-delivery-by-admin trend", + "styleSettings": { + "margin": "10px" + }, + "id": "d2ea8eac-a3db-46b0-bcb4-3abbb95ba4ad" + } + ] + }, + "customWidth": "100", + "name": "soc - post-delivery group", + "id": "ebca14d5-954d-4e35-a225-cb0f8a3ea81b" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "13" + }, + "name": "soc - air group", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "0a05394d-f813-4408-ac4d-8f481ae34c0b" + }, + { + "type": 12, + "content": { + "version": "NotebookGroup/1.0", + "groupType": "editable", + "items": [ + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Top Malicious Email Campaigns (Clustered)\r\n
\r\n\r\n**Groups malicious inbound emails into campaigns (attack waves) using the Email Cluster ID assigned by Microsoft Defender for Office 365, showing one row per campaign with the message count, distinct recipients, sender domains, threat mix and sample subjects. Helps the SOC understand the scale and shape of coordinated attacks rather than viewing individual messages in isolation.**

**Recommended action:** Pivot on the top campaign clusters to hunt related messages and consider blocking shared sender infrastructure." + }, + "name": "soc - campaigns heading", + "id": "d3a9e4c6-1b5f-4c8d-ae34-9f7a1b2c3d45" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Largest malicious inbound email campaigns clustered by EmailClusterId - one row per attack wave (messages, recipients, URL clicks, sender domains, threat mix, sample subjects).\r\n//URL Clicks = clicks by recipients on URLs within the campaign's messages (UrlClickEvents joined via NetworkMessageId).\r\nlet clicksByCluster = UrlClickEvents\r\n| join kind=inner (EmailEvents | where EmailClusterId > 0 | distinct NetworkMessageId, EmailClusterId) on NetworkMessageId\r\n| summarize UrlClicks = count() by EmailClusterId;\r\nlet qrClusters = EmailUrlInfo\r\n| where UrlLocation == \"QRCode\"\r\n| join kind=inner (EmailEvents | where EmailClusterId > 0 | distinct NetworkMessageId, EmailClusterId) on NetworkMessageId\r\n| summarize QrMessages = dcount(NetworkMessageId) by EmailClusterId;\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and EmailClusterId > 0\r\n| where OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Messages = count(),\r\n Recipients = dcount(RecipientEmailAddress),\r\n SenderDomains = dcount(SenderFromDomain),\r\n SampleSenderDomains = make_set(SenderFromDomain, 5),\r\n ThreatTypesRaw = make_set(ThreatTypes, 50),\r\n SampleSubjects = make_set(Subject, 5),\r\n FirstSeen = min(Timestamp),\r\n LastSeen = max(Timestamp)\r\n by EmailClusterId\r\n| join kind=leftouter (clicksByCluster) on EmailClusterId\r\n| extend UrlClicks = coalesce(UrlClicks, 0)\r\n| join kind=leftouter (qrClusters) on EmailClusterId\r\n| extend ['QR Code'] = iif(coalesce(QrMessages, 0) > 0, \"QR code\", \"\")\r\n| extend ThreatMix = array_sort_asc(set_union(split(strcat_array(ThreatTypesRaw, \", \"), \", \"), dynamic([])))\r\n| top 20 by Messages\r\n| project ['Email Cluster ID']=EmailClusterId, ['Messages']=Messages, ['Recipients']=Recipients, ['URL Clicks']=UrlClicks, ['Sender Domains']=SenderDomains, ['Sample Sender Domains']=SampleSenderDomains, ['Threat Mix']=ThreatMix, ['QR Code']=['QR Code'], ['Sample Subjects']=SampleSubjects, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", + "size": 0, + "title": "", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Recipients", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "URL Clicks", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "soc - campaigns table", + "id": "a2a391e1-0e26-4e0e-a8d3-26e3c7132079" + }, + { + "type": 1, + "content": { + "json": "\r\n\r\n\r\n\r\n
Most-Clicked Email Campaigns (Recipient Engagement)\r\n
\r\n\r\n**Ranks malicious inbound campaigns by recipient URL clicks, surfacing the attack waves that reached a mailbox and drew engagement regardless of raw message volume. The highest-volume campaigns are usually quarantined before delivery, so the clusters that draw clicks are often smaller, targeted waves. A non-zero URL Clicks count means a recipient opened a URL within the campaign's messages. Because attackers often mix legitimate URLs with malicious ones to build credibility, and a per-URL threat verdict is not available here, treat these as clicks on potentially malicious URLs that warrant review rather than confirmed malicious clicks.**

**Recommended action:** Focus on these clusters for user follow-up (awareness and, where credentials may be exposed, password reset) and hunt for related messages sharing sender infrastructure." + }, + "name": "soc - mostclicked heading", + "id": "e9e41b47-0434-42e5-8b04-4170ab061b81" + }, + { + "type": 3, + "content": { + "version": "KqlItem/1.0", + "query": "//Malicious inbound campaigns ranked by recipient URL clicks - the attack waves that reached a mailbox and drew engagement, regardless of message volume.\r\n//URL Clicks = clicks by recipients on URLs within the campaign's messages (UrlClickEvents joined via NetworkMessageId).\r\nlet clicksByCluster = UrlClickEvents\r\n| join kind=inner (EmailEvents | where EmailClusterId > 0 | distinct NetworkMessageId, EmailClusterId) on NetworkMessageId\r\n| summarize UrlClicks = count() by EmailClusterId;\r\nlet qrClusters = EmailUrlInfo\r\n| where UrlLocation == \"QRCode\"\r\n| join kind=inner (EmailEvents | where EmailClusterId > 0 | distinct NetworkMessageId, EmailClusterId) on NetworkMessageId\r\n| summarize QrMessages = dcount(NetworkMessageId) by EmailClusterId;\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and EmailClusterId > 0\r\n| where OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Messages = count(),\r\n Recipients = dcount(RecipientEmailAddress),\r\n SenderDomains = dcount(SenderFromDomain),\r\n SampleSenderDomains = make_set(SenderFromDomain, 5),\r\n ThreatTypesRaw = make_set(ThreatTypes, 50),\r\n SampleSubjects = make_set(Subject, 5),\r\n FirstSeen = min(Timestamp),\r\n LastSeen = max(Timestamp)\r\n by EmailClusterId\r\n| join kind=inner (clicksByCluster) on EmailClusterId\r\n| where UrlClicks > 0\r\n| join kind=leftouter (qrClusters) on EmailClusterId\r\n| extend ['QR Code'] = iif(coalesce(QrMessages, 0) > 0, \"QR code\", \"\")\r\n| extend ThreatMix = array_sort_asc(set_union(split(strcat_array(ThreatTypesRaw, \", \"), \", \"), dynamic([])))\r\n| top 20 by UrlClicks\r\n| project ['Email Cluster ID']=EmailClusterId, ['URL Clicks']=UrlClicks, ['Messages']=Messages, ['Recipients']=Recipients, ['Sender Domains']=SenderDomains, ['Sample Sender Domains']=SampleSenderDomains, ['Threat Mix']=ThreatMix, ['QR Code']=['QR Code'], ['Sample Subjects']=SampleSubjects, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", + "size": 0, + "title": "", + "timeContextFromParameter": "TimeRange", + "queryType": "advancedHunting", + "visualization": "table", + "gridSettings": { + "filter": true, + "formatters": [ + { + "columnMatch": "URL Clicks", + "formatter": 3, + "formatOptions": { + "palette": "redDark", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Messages", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + }, + { + "columnMatch": "Recipients", + "formatter": 3, + "formatOptions": { + "palette": "blue", + "customColumnWidthSetting": "130px" + }, + "numberFormat": { + "unit": 17, + "options": { + "style": "decimal", + "maximumFractionDigits": 1 + } + } + } + ] + }, + "timeContext": { + "durationMs": 0 + } + }, + "name": "soc - mostclicked table", + "id": "1ffe8f97-ad79-47d9-9598-dd73ee54cd8d" + } + ] + }, + "conditionalVisibility": { + "parameterName": "Tab", + "comparison": "isEqualTo", + "value": "13" + }, + "name": "soc - campaigns group", + "styleSettings": { + "margin": "10px", + "padding": "10px", + "showBorder": true + }, + "id": "b8f2a1c4-5d6e-4a7b-9c8d-0e1f2a3b4c5d" + } + ], + "isLocked": false, + "fallbackResourceIds": [], + "$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json", + "xdrMetadata": { + "contentId": "55a394cc-f0af-55c1-8ff2-ec483e3e68a3", + "instanceId": "0eba4431-9e8b-5ffb-9623-2a0391db7b01", + "version": "3.2.0", + "schemaVersion": "1.0.0", + "displayName": "Microsoft Defender for Office 365 Detections and Insights - ISOC" + }, + "contentProvenance": { + "origin": "native-xdr", + "source": { + "path": "Workbook Sources/Native/MicrosoftDefenderForOffice365DetectionsAndInsights.json", + "sha256": "7985b58b9c0f12ca79dd7d7ca33a197243c23953508bf81638082ff3a2663b6b" + }, + "nativeReview": { + "origin": "native-xdr", + "source": { + "path": "Workbook Sources/Native/MicrosoftDefenderForOffice365DetectionsAndInsights.json", + "sha256": "7985b58b9c0f12ca79dd7d7ca33a197243c23953508bf81638082ff3a2663b6b" + }, + "displayName": "Microsoft Defender for Office 365 Detections and Insights - ISOC", + "actor": "kingwil", + "reference": "Explicit user approval of all 237 source-bound query hashes and MDO/MDA/MTP prerequisites in this session on 2026-10-15. Native upstream Defender workbook; 14 tabs and six Sentinel-only notices retained. Offline review only.", + "requiredWorkloads": [ + { + "workload": "mda", + "dataTypes": [ + "CloudAppEvents" + ] + }, + { + "workload": "mdo", + "dataTypes": [ + "EmailEvents", + "EmailPostDeliveryEvents", + "EmailUrlInfo", + "FileMaliciousContentInfo", + "MessageEvents", + "MessagePostDeliveryEvents", + "MessageUrlInfo", + "UrlClickEvents" + ] + }, + { + "workload": "mtp", + "dataTypes": [ + "AlertEvidence" + ] + } + ], + "requiredDataConnectors": [], + "queries": [ + { + "path": "/items/3/content/items/0/content/items/1/content/items/0/content/query", + "querySha256": "a20e6049790672c279964f006cf8f6b26f5264ec2543c185fc927d68bc008b32", + "tables": [ + "CloudAppEvents", + "EmailEvents", + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/0/content/items/1/content/items/0/content/query SHA256 a20e6049790672c279964f006cf8f6b26f5264ec2543c185fc927d68bc008b32; complete discovered native inputs: CloudAppEvents, EmailEvents, EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/0/content/items/1/content/items/1/content/query", + "querySha256": "b9a2ddf63c5404a5073a9d0a9707bd5adfe06254d526136d9c94310279a51965", + "tables": [ + "EmailEvents", + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/0/content/items/1/content/items/1/content/query SHA256 b9a2ddf63c5404a5073a9d0a9707bd5adfe06254d526136d9c94310279a51965; complete discovered native inputs: EmailEvents, EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/0/content/items/2/content/items/1/content/query", + "querySha256": "d524bd647ff40942d49725aea7dbbe3a599f9527e2d478e7ffada042ef173893", + "tables": [ + "CloudAppEvents", + "EmailEvents", + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/0/content/items/2/content/items/1/content/query SHA256 d524bd647ff40942d49725aea7dbbe3a599f9527e2d478e7ffada042ef173893; complete discovered native inputs: CloudAppEvents, EmailEvents, EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/0/content/items/3/content/items/1/content/query", + "querySha256": "85ed7ec77cc8bf2b0ea05d753a5eb3285800b15fae28dac80145460883f101c7", + "tables": [ + "EmailEvents", + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/0/content/items/3/content/items/1/content/query SHA256 85ed7ec77cc8bf2b0ea05d753a5eb3285800b15fae28dac80145460883f101c7; complete discovered native inputs: EmailEvents, EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/1/content/items/2/content/query", + "querySha256": "54c5da330fa9d7f225441bf1d9d0a714ca10e676ddc26acfa7c972e1037bbf69", + "tables": [ + "CloudAppEvents", + "EmailEvents", + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/1/content/items/2/content/query SHA256 54c5da330fa9d7f225441bf1d9d0a714ca10e676ddc26acfa7c972e1037bbf69; complete discovered native inputs: CloudAppEvents, EmailEvents, EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/1/content/items/3/content/items/0/content/items/0/content/query", + "querySha256": "5ea9001623bf807401855ab2dc1227cc2028df25607fe48dd189eed3403c66cc", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/1/content/items/3/content/items/0/content/items/0/content/query SHA256 5ea9001623bf807401855ab2dc1227cc2028df25607fe48dd189eed3403c66cc; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/1/content/items/3/content/items/1/content/items/0/content/query", + "querySha256": "11024d9cb81b049a21e345bc5524f772f9154ffa2308755d5e91d7640e03a000", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/1/content/items/3/content/items/1/content/items/0/content/query SHA256 11024d9cb81b049a21e345bc5524f772f9154ffa2308755d5e91d7640e03a000; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/1/content/items/3/content/items/1/content/items/1/content/query", + "querySha256": "28cafb2e50cec0219284436da53500fb14de8f6f152b78f9fb7b46de674ef36d", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/1/content/items/3/content/items/1/content/items/1/content/query SHA256 28cafb2e50cec0219284436da53500fb14de8f6f152b78f9fb7b46de674ef36d; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/1/content/items/3/content/items/1/content/items/2/content/query", + "querySha256": "317de152ba920fdf351f7321099fdeabdc9976846d339eb9b88fdde797cb3eea", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/1/content/items/3/content/items/1/content/items/2/content/query SHA256 317de152ba920fdf351f7321099fdeabdc9976846d339eb9b88fdde797cb3eea; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/1/content/items/3/content/items/1/content/items/3/content/query", + "querySha256": "2c92c916613af150c9fb9002575262812efe51a25f3e895f7b13c48cd2cd5f75", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/1/content/items/3/content/items/1/content/items/3/content/query SHA256 2c92c916613af150c9fb9002575262812efe51a25f3e895f7b13c48cd2cd5f75; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/1/content/items/3/content/items/2/content/items/0/content/query", + "querySha256": "6d26ede06beed91a44a33f5e92d356dbda265fb9d28a08085a8b9c1a20ab222d", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/1/content/items/3/content/items/2/content/items/0/content/query SHA256 6d26ede06beed91a44a33f5e92d356dbda265fb9d28a08085a8b9c1a20ab222d; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/1/content/items/3/content/items/2/content/items/1/content/query", + "querySha256": "0dd446cd43e873feeeb05f3fb5d66fee5c565c5b31ea65512c4e667343eeae2e", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/1/content/items/3/content/items/2/content/items/1/content/query SHA256 0dd446cd43e873feeeb05f3fb5d66fee5c565c5b31ea65512c4e667343eeae2e; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/1/content/items/3/content/items/2/content/items/2/content/query", + "querySha256": "07b6448883cc7e806585aa65b32d23f9885de98f00db547259bf3abc51782695", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/1/content/items/3/content/items/2/content/items/2/content/query SHA256 07b6448883cc7e806585aa65b32d23f9885de98f00db547259bf3abc51782695; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/1/content/items/3/content/items/3/content/items/0/content/query", + "querySha256": "e1a57a032e584b925d55abf853598511c207c992fba71727c350eb2fbe9a7955", + "tables": [ + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/1/content/items/3/content/items/3/content/items/0/content/query SHA256 e1a57a032e584b925d55abf853598511c207c992fba71727c350eb2fbe9a7955; complete discovered native inputs: EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/1/content/items/3/content/items/3/content/items/1/content/query", + "querySha256": "bfe851f071babb9c7bdb272265c227c0e5b412e8a2b45f2e650105234bed34d4", + "tables": [ + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/1/content/items/3/content/items/3/content/items/1/content/query SHA256 bfe851f071babb9c7bdb272265c227c0e5b412e8a2b45f2e650105234bed34d4; complete discovered native inputs: EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/1/content/items/3/content/items/3/content/items/2/content/query", + "querySha256": "a3d38b001812d4243757f54d219cc3483324bfe96169a973957f48e8f38b9661", + "tables": [ + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/1/content/items/3/content/items/3/content/items/2/content/query SHA256 a3d38b001812d4243757f54d219cc3483324bfe96169a973957f48e8f38b9661; complete discovered native inputs: EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/1/content/items/3/content/items/4/content/items/0/content/query", + "querySha256": "ca205c791cd98cc9ca1dd117e21f72b3ec9297eac3d66edc502ea235b2c00771", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/1/content/items/3/content/items/4/content/items/0/content/query SHA256 ca205c791cd98cc9ca1dd117e21f72b3ec9297eac3d66edc502ea235b2c00771; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/1/content/items/3/content/items/4/content/items/1/content/query", + "querySha256": "7e3420b2827239bf920fb9719d44a299424cae3a7814795abbc9c07efbae589f", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/1/content/items/3/content/items/4/content/items/1/content/query SHA256 7e3420b2827239bf920fb9719d44a299424cae3a7814795abbc9c07efbae589f; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/1/content/items/5/content/query", + "querySha256": "29e1433c6e19b5452fe2be9b62bcf61ad37e29d746484dbfa5a645054e30a3cc", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/1/content/items/5/content/query SHA256 29e1433c6e19b5452fe2be9b62bcf61ad37e29d746484dbfa5a645054e30a3cc; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/1/content/items/7/content/query", + "querySha256": "5c341f1f2dbee19255c01125ce8be61b3a9ae6e65b982e4170f53e132c40148f", + "tables": [ + "CloudAppEvents", + "EmailEvents", + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/1/content/items/7/content/query SHA256 5c341f1f2dbee19255c01125ce8be61b3a9ae6e65b982e4170f53e132c40148f; complete discovered native inputs: CloudAppEvents, EmailEvents, EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/1/content/items/9/content/query", + "querySha256": "134d3d4d6893f1d88c14e42b7976e21006dabba9d3fc71dd58a55e0ca52db645", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/1/content/items/9/content/query SHA256 134d3d4d6893f1d88c14e42b7976e21006dabba9d3fc71dd58a55e0ca52db645; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/2/content/items/1/content/query", + "querySha256": "554088d9c128e08443f51fecd276d5435baaa56ab9f2dd744e1325fc0c0d4132", + "tables": [ + "CloudAppEvents", + "FileMaliciousContentInfo", + "MessageEvents", + "MessageUrlInfo", + "UrlClickEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/2/content/items/1/content/query SHA256 554088d9c128e08443f51fecd276d5435baaa56ab9f2dd744e1325fc0c0d4132; complete discovered native inputs: CloudAppEvents, FileMaliciousContentInfo, MessageEvents, MessageUrlInfo, UrlClickEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/3/content/items/4/content/items/1/content/query", + "querySha256": "a691b608e29297a7398550427e7dc2331253dfba5a35075418caf680155de8a8", + "tables": [], + "decision": "accept", + "evidence": "User approved exact query /items/3/content/items/4/content/items/1/content/query SHA256 a691b608e29297a7398550427e7dc2331253dfba5a35075418caf680155de8a8; complete discovered native inputs: source-free literal. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/5/content/query", + "querySha256": "1fd59e604c53e89e68e79492437b58352dad05c2a44a165056a653932c3b7412", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/5/content/query SHA256 1fd59e604c53e89e68e79492437b58352dad05c2a44a165056a653932c3b7412; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/6/content/items/2/content/query", + "querySha256": "a1eb72881852a12eabc2a4e37363a0520a5c4aaccb1e097ace271ca50e8a6674", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/6/content/items/2/content/query SHA256 a1eb72881852a12eabc2a4e37363a0520a5c4aaccb1e097ace271ca50e8a6674; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/6/content/items/4/content/query", + "querySha256": "16d0ddfd2281229a57f0213b0c71fdee484fd1ce15b8992838ab99c69a595c38", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/6/content/items/4/content/query SHA256 16d0ddfd2281229a57f0213b0c71fdee484fd1ce15b8992838ab99c69a595c38; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/6/content/items/8/content/query", + "querySha256": "ddd5a7b2f07acbb2d84ca0dc89914b9f9ddc7f535c41e33aa91935489274b85e", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/6/content/items/8/content/query SHA256 ddd5a7b2f07acbb2d84ca0dc89914b9f9ddc7f535c41e33aa91935489274b85e; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/6/content/items/9/content/query", + "querySha256": "81cc0526ceb03ef05cb2fbe47616c4a345f2a417d517a6677ad6177d152f6ecf", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/6/content/items/9/content/query SHA256 81cc0526ceb03ef05cb2fbe47616c4a345f2a417d517a6677ad6177d152f6ecf; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/6/content/items/10/content/query", + "querySha256": "d68a7f96d43935aec5025b38ac8131bfd1d3c0837ec91420c2cbdb973c9fa347", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/6/content/items/10/content/query SHA256 d68a7f96d43935aec5025b38ac8131bfd1d3c0837ec91420c2cbdb973c9fa347; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/7/content/items/2/content/query", + "querySha256": "a3b8e175fb3ff34541f46d149a29711925d5c482a9f9a14d3e5e56f0519e8faf", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/7/content/items/2/content/query SHA256 a3b8e175fb3ff34541f46d149a29711925d5c482a9f9a14d3e5e56f0519e8faf; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/7/content/items/4/content/query", + "querySha256": "ea45ad99cb7085ff2484337c2af41b5f3afd1e84af0f00116d84c2357866a972", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/7/content/items/4/content/query SHA256 ea45ad99cb7085ff2484337c2af41b5f3afd1e84af0f00116d84c2357866a972; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/7/content/items/5/content/query", + "querySha256": "f7b64dc5f98dfd385c0290d39bc1dfc121067b1f882585a454e846d26e593a75", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/7/content/items/5/content/query SHA256 f7b64dc5f98dfd385c0290d39bc1dfc121067b1f882585a454e846d26e593a75; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/7/content/items/7/content/query", + "querySha256": "de21119c9350ed8012e9d56b9475896ed6a277ddc4d58d82498528462c86f523", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/7/content/items/7/content/query SHA256 de21119c9350ed8012e9d56b9475896ed6a277ddc4d58d82498528462c86f523; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/7/content/items/8/content/query", + "querySha256": "248b79ce9222fc7113a366302ad0ae54dbc8b1b66c1fe05c66642d477a537621", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/7/content/items/8/content/query SHA256 248b79ce9222fc7113a366302ad0ae54dbc8b1b66c1fe05c66642d477a537621; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/8/content/items/2/content/query", + "querySha256": "02debf99cc2c7a9ebd4aeee5dbd979ab4b7fa66aba6f9735d97d6a9b8d85eee8", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/8/content/items/2/content/query SHA256 02debf99cc2c7a9ebd4aeee5dbd979ab4b7fa66aba6f9735d97d6a9b8d85eee8; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/8/content/items/4/content/query", + "querySha256": "26285dadd9f5d6729ee69b02f40cae580343f7d64ba34be7561a557015bf71f7", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/8/content/items/4/content/query SHA256 26285dadd9f5d6729ee69b02f40cae580343f7d64ba34be7561a557015bf71f7; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/10/content/query", + "querySha256": "fd37ee40dbe163b31caf52d4916ff7bb4feb10641478cd97cb31eae0f8073381", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/10/content/query SHA256 fd37ee40dbe163b31caf52d4916ff7bb4feb10641478cd97cb31eae0f8073381; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/11/content/items/2/content/query", + "querySha256": "22eeb06bdd1b73c37db5b37e411b66901b8c19dabd2331ad63989fc967dbded0", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/11/content/items/2/content/query SHA256 22eeb06bdd1b73c37db5b37e411b66901b8c19dabd2331ad63989fc967dbded0; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/11/content/items/4/content/query", + "querySha256": "e2139803441267d6d5a75748527dae86ec2356277870279716138ce6249f943b", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/11/content/items/4/content/query SHA256 e2139803441267d6d5a75748527dae86ec2356277870279716138ce6249f943b; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/11/content/items/7/content/query", + "querySha256": "3be6f32b1bea4e814d3af53af70937deae7fe43a38787044f0d9aaa62b82a3e8", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/11/content/items/7/content/query SHA256 3be6f32b1bea4e814d3af53af70937deae7fe43a38787044f0d9aaa62b82a3e8; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/11/content/items/8/content/query", + "querySha256": "8e13aacf6471de483b3d738bc1059c5b4827ea403e259262b6b9d4d40c50575c", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/11/content/items/8/content/query SHA256 8e13aacf6471de483b3d738bc1059c5b4827ea403e259262b6b9d4d40c50575c; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/11/content/items/10/content/query", + "querySha256": "05d1791b6b26ff87d2d0fcce94f77886a64e67fb5833619e961bc1fe838c7eb9", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/11/content/items/10/content/query SHA256 05d1791b6b26ff87d2d0fcce94f77886a64e67fb5833619e961bc1fe838c7eb9; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/12/content/items/2/content/query", + "querySha256": "a350de491b28676fcbbcec5c504cb3ca4a1db5ae48d8c97aa987f59490874575", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/12/content/items/2/content/query SHA256 a350de491b28676fcbbcec5c504cb3ca4a1db5ae48d8c97aa987f59490874575; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/12/content/items/4/content/query", + "querySha256": "9d9d374c3e06afb3823fffd4bb0baed757cc16db6eccfa43861ceb816b1937f4", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/12/content/items/4/content/query SHA256 9d9d374c3e06afb3823fffd4bb0baed757cc16db6eccfa43861ceb816b1937f4; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/12/content/items/5/content/query", + "querySha256": "183eb747b5a3e5ee38cdb0646009188239f08691ecb6b880734bf1f4b43ea273", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/12/content/items/5/content/query SHA256 183eb747b5a3e5ee38cdb0646009188239f08691ecb6b880734bf1f4b43ea273; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/12/content/items/7/content/query", + "querySha256": "6e4843db67a97358acb924a864ec43d2e272004210b1434b1b59eb5637bf768c", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/12/content/items/7/content/query SHA256 6e4843db67a97358acb924a864ec43d2e272004210b1434b1b59eb5637bf768c; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/12/content/items/8/content/query", + "querySha256": "e22a42e2a2616c1db95f3b9835e72d66cf7970467d685eb93f809b3dfa7ec2ff", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/12/content/items/8/content/query SHA256 e22a42e2a2616c1db95f3b9835e72d66cf7970467d685eb93f809b3dfa7ec2ff; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/13/content/items/2/content/query", + "querySha256": "0812c949bb0b46ba42d3e3ec829df7f982196eca2b0229a93cfaa5be2364d28a", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/13/content/items/2/content/query SHA256 0812c949bb0b46ba42d3e3ec829df7f982196eca2b0229a93cfaa5be2364d28a; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/13/content/items/4/content/query", + "querySha256": "d836b1df0d0b4884a6160c9fc03c03c79bf537737fbf3f403b07c08467d4987a", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/13/content/items/4/content/query SHA256 d836b1df0d0b4884a6160c9fc03c03c79bf537737fbf3f403b07c08467d4987a; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/15/content/query", + "querySha256": "6b196b757eb3f8aeef37ebdc74006b81a1a30b2d070a678ba80b8765f7c5143b", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/15/content/query SHA256 6b196b757eb3f8aeef37ebdc74006b81a1a30b2d070a678ba80b8765f7c5143b; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/16/content/items/1/content/items/0/content/query", + "querySha256": "a28e74bfbbd4ebedca74681ae5fb0ce2a86f234832b90e21cb0c4e5e7b007f65", + "tables": [ + "CloudAppEvents", + "EmailEvents", + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/16/content/items/1/content/items/0/content/query SHA256 a28e74bfbbd4ebedca74681ae5fb0ce2a86f234832b90e21cb0c4e5e7b007f65; complete discovered native inputs: CloudAppEvents, EmailEvents, EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/16/content/items/1/content/items/1/content/query", + "querySha256": "238ae09c435a5406518596dc18426054e6d6dfc9d7c4df50704b41b1780cd2bf", + "tables": [ + "CloudAppEvents", + "EmailEvents", + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/16/content/items/1/content/items/1/content/query SHA256 238ae09c435a5406518596dc18426054e6d6dfc9d7c4df50704b41b1780cd2bf; complete discovered native inputs: CloudAppEvents, EmailEvents, EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/16/content/items/3/content/query", + "querySha256": "fe5a749c7e0a653d852395156da4cd7e7ce7ff1762e665d4cd777999277abeea", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/16/content/items/3/content/query SHA256 fe5a749c7e0a653d852395156da4cd7e7ce7ff1762e665d4cd777999277abeea; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/17/content/items/2/content/query", + "querySha256": "c0470a13c60b55b6e4ce12d21e152594a1a40feb0185e87be6b806d9bb639e2b", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/17/content/items/2/content/query SHA256 c0470a13c60b55b6e4ce12d21e152594a1a40feb0185e87be6b806d9bb639e2b; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/17/content/items/4/content/query", + "querySha256": "01dd1fe6bc4a32ab61b2b9850669c2026f1acca5ebbbdb9b26ba708a81f1af1e", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/17/content/items/4/content/query SHA256 01dd1fe6bc4a32ab61b2b9850669c2026f1acca5ebbbdb9b26ba708a81f1af1e; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/17/content/items/5/content/query", + "querySha256": "084647209d37f116cf1a204d17143575d79adf54e3f8450baca8fd358dc9b509", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/17/content/items/5/content/query SHA256 084647209d37f116cf1a204d17143575d79adf54e3f8450baca8fd358dc9b509; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/17/content/items/7/content/query", + "querySha256": "a7de4ffc8f7eb27db97b364965b34b9ec8a07e8fcfe5d069b5bf7a8d34a22b4d", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/17/content/items/7/content/query SHA256 a7de4ffc8f7eb27db97b364965b34b9ec8a07e8fcfe5d069b5bf7a8d34a22b4d; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/17/content/items/8/content/query", + "querySha256": "abe3f3e14822dc6298e344ededd703ec24e2997b07a30f795a42767adc476f0b", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/17/content/items/8/content/query SHA256 abe3f3e14822dc6298e344ededd703ec24e2997b07a30f795a42767adc476f0b; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/17/content/items/10/content/query", + "querySha256": "8a63fd07272a42368011810f1c3cb00be81d94a86868e94a0fc0747bda98aa3f", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/17/content/items/10/content/query SHA256 8a63fd07272a42368011810f1c3cb00be81d94a86868e94a0fc0747bda98aa3f; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/17/content/items/11/content/query", + "querySha256": "51704280a4a6d8449a6de591364095c8ac023580aad92e90748958c6811c2326", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/17/content/items/11/content/query SHA256 51704280a4a6d8449a6de591364095c8ac023580aad92e90748958c6811c2326; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/18/content/items/2/content/query", + "querySha256": "78adf2f996597251405ce011ccd04e54e1dda00c5b7d4912c5e05cd125f7609d", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/18/content/items/2/content/query SHA256 78adf2f996597251405ce011ccd04e54e1dda00c5b7d4912c5e05cd125f7609d; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/18/content/items/4/content/query", + "querySha256": "bc7b742b68f85605fbb44ce79e3a721dbf9258eb6bf68430e710e92e5f704da3", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/18/content/items/4/content/query SHA256 bc7b742b68f85605fbb44ce79e3a721dbf9258eb6bf68430e710e92e5f704da3; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/20/content/query", + "querySha256": "c4f105af76862707cad18ad90f0cc5ca9122667bdb580b6150b0a122ab85fb8b", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/20/content/query SHA256 c4f105af76862707cad18ad90f0cc5ca9122667bdb580b6150b0a122ab85fb8b; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/21/content/items/2/content/query", + "querySha256": "19c8169c55a32ba881163427e6775f54646e428c4c7d3f183237dfc4f5b80122", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/21/content/items/2/content/query SHA256 19c8169c55a32ba881163427e6775f54646e428c4c7d3f183237dfc4f5b80122; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/21/content/items/4/content/query", + "querySha256": "0a348831425415001b2848be6a4ab1393cd02e0d34042fca75837862b9f42dd8", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/21/content/items/4/content/query SHA256 0a348831425415001b2848be6a4ab1393cd02e0d34042fca75837862b9f42dd8; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/21/content/items/5/content/query", + "querySha256": "222ae168c6cb938f7b93b895788a390fb029a32e1664cb2789bc5fab6aeb11b5", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/21/content/items/5/content/query SHA256 222ae168c6cb938f7b93b895788a390fb029a32e1664cb2789bc5fab6aeb11b5; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/21/content/items/7/content/query", + "querySha256": "7230d3dec852957a1977bc5cbd58bddca882e80fe7bdbecaeed68093d065df5e", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/21/content/items/7/content/query SHA256 7230d3dec852957a1977bc5cbd58bddca882e80fe7bdbecaeed68093d065df5e; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/21/content/items/8/content/query", + "querySha256": "5b2791d69e5d49a1e94edfbf28e6131f53002bb9255f81ba6d9f55db046704d8", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/21/content/items/8/content/query SHA256 5b2791d69e5d49a1e94edfbf28e6131f53002bb9255f81ba6d9f55db046704d8; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/21/content/items/10/content/query", + "querySha256": "83698c8e41887bef4abd2fe97ab3f556741c929628fb05d4d18e88a223c9df41", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/21/content/items/10/content/query SHA256 83698c8e41887bef4abd2fe97ab3f556741c929628fb05d4d18e88a223c9df41; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/21/content/items/12/content/query", + "querySha256": "37a68140432a447f5c7af8dbdfda9bca62395fb84ec1e8a0ae8f005d73404490", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/21/content/items/12/content/query SHA256 37a68140432a447f5c7af8dbdfda9bca62395fb84ec1e8a0ae8f005d73404490; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/21/content/items/13/content/query", + "querySha256": "4c9ff00bc3a99712b53534750ac48fda121b96ced9fbcdfaaa69da335fc6d14a", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/21/content/items/13/content/query SHA256 4c9ff00bc3a99712b53534750ac48fda121b96ced9fbcdfaaa69da335fc6d14a; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/21/content/items/15/content/query", + "querySha256": "6d4e09079b6dccedc1d063269c18eeb986714a2bc0117b85d554b879415d29d3", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/21/content/items/15/content/query SHA256 6d4e09079b6dccedc1d063269c18eeb986714a2bc0117b85d554b879415d29d3; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/21/content/items/16/content/query", + "querySha256": "c1be2cd17e75ae46d3684fbb36345ffe412cf242cd59f72b21e72389fbf833ba", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/21/content/items/16/content/query SHA256 c1be2cd17e75ae46d3684fbb36345ffe412cf242cd59f72b21e72389fbf833ba; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/21/content/items/18/content/query", + "querySha256": "8de5a8ad15b74c19ef2783d043cf7c817e8c56340e9adbcf8abe387915d09ae6", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/21/content/items/18/content/query SHA256 8de5a8ad15b74c19ef2783d043cf7c817e8c56340e9adbcf8abe387915d09ae6; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/21/content/items/20/content/query", + "querySha256": "c0d35624bc2b22f0fae34301c14aa1cddba46b1c14c9ba76ae471c7de9f59f39", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/21/content/items/20/content/query SHA256 c0d35624bc2b22f0fae34301c14aa1cddba46b1c14c9ba76ae471c7de9f59f39; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/22/content/items/2/content/query", + "querySha256": "58b9016775f366c2cf992c083592ff71ae2135da153677b3f824c46f7a957ae1", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/22/content/items/2/content/query SHA256 58b9016775f366c2cf992c083592ff71ae2135da153677b3f824c46f7a957ae1; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/22/content/items/3/content/query", + "querySha256": "a28a9af539c2397ac3fd1c84ef7c2783d5a479e471df73be7ca43caace84e681", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/22/content/items/3/content/query SHA256 a28a9af539c2397ac3fd1c84ef7c2783d5a479e471df73be7ca43caace84e681; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/22/content/items/4/content/query", + "querySha256": "41d09c9e789532d07dc69ecc411bc68133aafd96989cf4e02eeb42b33d2c8d01", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/22/content/items/4/content/query SHA256 41d09c9e789532d07dc69ecc411bc68133aafd96989cf4e02eeb42b33d2c8d01; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/22/content/items/5/content/query", + "querySha256": "ea61c1a26e95808521fbe8cbdbdcf1d04ea9085ee24a39412cb680dc728a73c3", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/22/content/items/5/content/query SHA256 ea61c1a26e95808521fbe8cbdbdcf1d04ea9085ee24a39412cb680dc728a73c3; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/22/content/items/7/content/query", + "querySha256": "c77a0ff030a3dd2b738f7fd66ac24d6eabd640f0edcfad21a2e4de669dff53f7", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/22/content/items/7/content/query SHA256 c77a0ff030a3dd2b738f7fd66ac24d6eabd640f0edcfad21a2e4de669dff53f7; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/22/content/items/9/content/query", + "querySha256": "47768c7215fdf1bf634a0a9b52fe50f8e37e04820aed240d40b792a2e944cd9f", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/22/content/items/9/content/query SHA256 47768c7215fdf1bf634a0a9b52fe50f8e37e04820aed240d40b792a2e944cd9f; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/22/content/items/11/content/query", + "querySha256": "7dce088cd958bf29049a469802daad4299c5cba83a4f3703a93131ee18525824", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/22/content/items/11/content/query SHA256 7dce088cd958bf29049a469802daad4299c5cba83a4f3703a93131ee18525824; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/23/content/items/2/content/query", + "querySha256": "c5790761884246424b5b0bb4f99d1c87fc14a5ba40d87397d14df2e97c4c963c", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/23/content/items/2/content/query SHA256 c5790761884246424b5b0bb4f99d1c87fc14a5ba40d87397d14df2e97c4c963c; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/23/content/items/4/content/query", + "querySha256": "3b57a1805ed80603ed532a37c949b325e6089df1020df9f12dc3173efc2de493", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/23/content/items/4/content/query SHA256 3b57a1805ed80603ed532a37c949b325e6089df1020df9f12dc3173efc2de493; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/25/content/query", + "querySha256": "b4352c617373ee0d8c94c692bce5613e67cb7612fa7922e78ac78634aa714714", + "tables": [ + "EmailUrlInfo", + "UrlClickEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/25/content/query SHA256 b4352c617373ee0d8c94c692bce5613e67cb7612fa7922e78ac78634aa714714; complete discovered native inputs: EmailUrlInfo, UrlClickEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/26/content/items/2/content/query", + "querySha256": "9daabfabfcb9f9a343c05b6a9a3628be01341908ce2121be22d85a4883057a46", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/26/content/items/2/content/query SHA256 9daabfabfcb9f9a343c05b6a9a3628be01341908ce2121be22d85a4883057a46; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/26/content/items/4/content/query", + "querySha256": "c6bcb12df3ef848861601923d5e929e0aca00db63f4ee330eca357d9ad0d23f3", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/26/content/items/4/content/query SHA256 c6bcb12df3ef848861601923d5e929e0aca00db63f4ee330eca357d9ad0d23f3; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/26/content/items/7/content/query", + "querySha256": "136feab1afc6191911f3781f8201b9e02054f87628fe384f51b0053e4b212071", + "tables": [ + "EmailEvents", + "EmailUrlInfo" + ], + "decision": "accept", + "evidence": "User approved exact query /items/26/content/items/7/content/query SHA256 136feab1afc6191911f3781f8201b9e02054f87628fe384f51b0053e4b212071; complete discovered native inputs: EmailEvents, EmailUrlInfo. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/26/content/items/8/content/query", + "querySha256": "3629b626438ea9a517079ccccb7998cfa0f2f23d6b901a435b17db6fa975f169", + "tables": [ + "EmailUrlInfo" + ], + "decision": "accept", + "evidence": "User approved exact query /items/26/content/items/8/content/query SHA256 3629b626438ea9a517079ccccb7998cfa0f2f23d6b901a435b17db6fa975f169; complete discovered native inputs: EmailUrlInfo. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/27/content/items/2/content/query", + "querySha256": "de9936de60014beaf4994b55a62748796df10357de12757d8a45935de883aa77", + "tables": [ + "EmailEvents", + "UrlClickEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/27/content/items/2/content/query SHA256 de9936de60014beaf4994b55a62748796df10357de12757d8a45935de883aa77; complete discovered native inputs: EmailEvents, UrlClickEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/27/content/items/3/content/query", + "querySha256": "d64b0ab24acbc83afb51a6cdd483334e3fa2104a6254214d051b53905d37212d", + "tables": [ + "UrlClickEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/27/content/items/3/content/query SHA256 d64b0ab24acbc83afb51a6cdd483334e3fa2104a6254214d051b53905d37212d; complete discovered native inputs: UrlClickEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/27/content/items/6/content/query", + "querySha256": "744fd3158cce723e09e1dc24686787d492bae7d213699246837e5936806f0197", + "tables": [ + "EmailEvents", + "UrlClickEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/27/content/items/6/content/query SHA256 744fd3158cce723e09e1dc24686787d492bae7d213699246837e5936806f0197; complete discovered native inputs: EmailEvents, UrlClickEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/27/content/items/7/content/query", + "querySha256": "8429ae089810f55dc95903d431c16664edf954083e661b7a073a232c8f4eba90", + "tables": [ + "UrlClickEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/27/content/items/7/content/query SHA256 8429ae089810f55dc95903d431c16664edf954083e661b7a073a232c8f4eba90; complete discovered native inputs: UrlClickEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/27/content/items/10/content/query", + "querySha256": "eaf620ac0615ffcdfc3897483b5032a495ab79fd549ab9632890d43ff5829b7d", + "tables": [ + "EmailEvents", + "UrlClickEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/27/content/items/10/content/query SHA256 eaf620ac0615ffcdfc3897483b5032a495ab79fd549ab9632890d43ff5829b7d; complete discovered native inputs: EmailEvents, UrlClickEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/27/content/items/11/content/query", + "querySha256": "0bf2451c7dfd76eee94ff4124828ce2b680dbd19e088d2349a438a86a150e1d1", + "tables": [ + "UrlClickEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/27/content/items/11/content/query SHA256 0bf2451c7dfd76eee94ff4124828ce2b680dbd19e088d2349a438a86a150e1d1; complete discovered native inputs: UrlClickEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/27/content/items/13/content/query", + "querySha256": "38b2d7e0174c44ebdbf8a4c715c5adfbd101c732af0b9d346b36583eeee59f5a", + "tables": [ + "UrlClickEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/27/content/items/13/content/query SHA256 38b2d7e0174c44ebdbf8a4c715c5adfbd101c732af0b9d346b36583eeee59f5a; complete discovered native inputs: UrlClickEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/28/content/items/2/content/query", + "querySha256": "db5f05baf90ec7c16a38f3233a08b5a6e7269dce3e582c57e664ddc428032b2c", + "tables": [ + "UrlClickEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/28/content/items/2/content/query SHA256 db5f05baf90ec7c16a38f3233a08b5a6e7269dce3e582c57e664ddc428032b2c; complete discovered native inputs: UrlClickEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/28/content/items/4/content/query", + "querySha256": "07a9bf36177e24ca6af9f2a2db7e5a2de3717ae986fee891f6a70908ec57aad0", + "tables": [ + "UrlClickEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/28/content/items/4/content/query SHA256 07a9bf36177e24ca6af9f2a2db7e5a2de3717ae986fee891f6a70908ec57aad0; complete discovered native inputs: UrlClickEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/28/content/items/6/content/query", + "querySha256": "ed27048ae55d9fc1d918d46c209d96cb434835c7cac40c7ebb48ad64b1f8529d", + "tables": [ + "UrlClickEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/28/content/items/6/content/query SHA256 ed27048ae55d9fc1d918d46c209d96cb434835c7cac40c7ebb48ad64b1f8529d; complete discovered native inputs: UrlClickEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/30/content/query", + "querySha256": "7112638b0b50795d443ced8d00eaa0c220c8aa565ac8be30f20061f075662eaf", + "tables": [ + "MessageEvents", + "MessagePostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/30/content/query SHA256 7112638b0b50795d443ced8d00eaa0c220c8aa565ac8be30f20061f075662eaf; complete discovered native inputs: MessageEvents, MessagePostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/31/content/items/2/content/query", + "querySha256": "addfc8701d3b8ad0712bae67511363b79bc36017bc20156253fc121355e30cb2", + "tables": [ + "MessageEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/31/content/items/2/content/query SHA256 addfc8701d3b8ad0712bae67511363b79bc36017bc20156253fc121355e30cb2; complete discovered native inputs: MessageEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/31/content/items/5/content/query", + "querySha256": "115d80895a5be2c85508f27e76a48f554b8cd9365d1d7821be31df99aeff3468", + "tables": [ + "MessageEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/31/content/items/5/content/query SHA256 115d80895a5be2c85508f27e76a48f554b8cd9365d1d7821be31df99aeff3468; complete discovered native inputs: MessageEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/31/content/items/6/content/query", + "querySha256": "0b301a80d30871d06c44e6d360d25e6e9e7d0385f8f0f6ab0cde02431fb234ce", + "tables": [ + "MessageEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/31/content/items/6/content/query SHA256 0b301a80d30871d06c44e6d360d25e6e9e7d0385f8f0f6ab0cde02431fb234ce; complete discovered native inputs: MessageEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/32/content/items/1/content/query", + "querySha256": "01f7e898b2228c641a96135b46d26b76ebd38ccb2cc77194e679106c0154294a", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/32/content/items/1/content/query SHA256 01f7e898b2228c641a96135b46d26b76ebd38ccb2cc77194e679106c0154294a; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/32/content/items/3/content/query", + "querySha256": "45ae98d1a73726b46e2511bc40a832e3d6d221c4c29c58d4a43fb54689e57a3c", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/32/content/items/3/content/query SHA256 45ae98d1a73726b46e2511bc40a832e3d6d221c4c29c58d4a43fb54689e57a3c; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/32/content/items/5/content/query", + "querySha256": "f7d325b8dc2aa51f9d96727937d73c8db51a5767cac539e81286497ec8653911", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/32/content/items/5/content/query SHA256 f7d325b8dc2aa51f9d96727937d73c8db51a5767cac539e81286497ec8653911; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/32/content/items/7/content/query", + "querySha256": "adea6f30b1b69be99c7f0316549d391e7bcb33b5e633f0574119f2d9214996e1", + "tables": [ + "CloudAppEvents", + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/32/content/items/7/content/query SHA256 adea6f30b1b69be99c7f0316549d391e7bcb33b5e633f0574119f2d9214996e1; complete discovered native inputs: CloudAppEvents, EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/33/content/items/1/content/query", + "querySha256": "f15fa2300c726b24caf7db43d4483d40bfa9c508dad7d012d13d0689566276dc", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/33/content/items/1/content/query SHA256 f15fa2300c726b24caf7db43d4483d40bfa9c508dad7d012d13d0689566276dc; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/33/content/items/3/content/query", + "querySha256": "e4967734b2d441e44f883920b0ec6cee9b07bcd3dd1722796181f6cc8d7b4a72", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/33/content/items/3/content/query SHA256 e4967734b2d441e44f883920b0ec6cee9b07bcd3dd1722796181f6cc8d7b4a72; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/33/content/items/5/content/query", + "querySha256": "da62afa3f1cca75722bef666f99f46a05ef7fda8f457f474bb01ca554ca4fd09", + "tables": [ + "MessageEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/33/content/items/5/content/query SHA256 da62afa3f1cca75722bef666f99f46a05ef7fda8f457f474bb01ca554ca4fd09; complete discovered native inputs: MessageEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/33/content/items/7/content/query", + "querySha256": "4d3ec85cc0801652beb4defc4e3777955efe5ec50549c942a5a385a9b752862e", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/33/content/items/7/content/query SHA256 4d3ec85cc0801652beb4defc4e3777955efe5ec50549c942a5a385a9b752862e; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/33/content/items/9/content/query", + "querySha256": "661bce15fae66ae69300a1fda934232c266282b027c5336106bc81493c8db7a5", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/33/content/items/9/content/query SHA256 661bce15fae66ae69300a1fda934232c266282b027c5336106bc81493c8db7a5; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/33/content/items/11/content/query", + "querySha256": "9aa119251148521f6bf62b87e883cb0d526be3da9dff9369bb312a8b9b8038fa", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/33/content/items/11/content/query SHA256 9aa119251148521f6bf62b87e883cb0d526be3da9dff9369bb312a8b9b8038fa; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/33/content/items/13/content/query", + "querySha256": "200ad476ad60916ec0c869e71215911864f3e643c551fe8c5f061b783620c30f", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/33/content/items/13/content/query SHA256 200ad476ad60916ec0c869e71215911864f3e643c551fe8c5f061b783620c30f; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/33/content/items/15/content/query", + "querySha256": "987795e44176c715791378d800d09c992d12ec43b3c5821dacdabb5729189bc3", + "tables": [ + "CloudAppEvents", + "MessageEvents", + "MessageUrlInfo" + ], + "decision": "accept", + "evidence": "User approved exact query /items/33/content/items/15/content/query SHA256 987795e44176c715791378d800d09c992d12ec43b3c5821dacdabb5729189bc3; complete discovered native inputs: CloudAppEvents, MessageEvents, MessageUrlInfo. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/34/content/items/1/content/query", + "querySha256": "de4a3cd15b54b7bc12fceea891f3299f9d34e1ac844bcec0579f42f31b1f608a", + "tables": [ + "MessageEvents", + "MessageUrlInfo" + ], + "decision": "accept", + "evidence": "User approved exact query /items/34/content/items/1/content/query SHA256 de4a3cd15b54b7bc12fceea891f3299f9d34e1ac844bcec0579f42f31b1f608a; complete discovered native inputs: MessageEvents, MessageUrlInfo. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/34/content/items/4/content/query", + "querySha256": "c8b131c029c45551133d982f401722e3b74a3c7c21d34a1d6825bab48599ad96", + "tables": [ + "UrlClickEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/34/content/items/4/content/query SHA256 c8b131c029c45551133d982f401722e3b74a3c7c21d34a1d6825bab48599ad96; complete discovered native inputs: UrlClickEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/34/content/items/5/content/query", + "querySha256": "6204df8da919ae7f5bd8f4e048027dad32c967701d8b6e1e34e0ab741503f1e4", + "tables": [ + "UrlClickEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/34/content/items/5/content/query SHA256 6204df8da919ae7f5bd8f4e048027dad32c967701d8b6e1e34e0ab741503f1e4; complete discovered native inputs: UrlClickEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/34/content/items/7/content/query", + "querySha256": "36ec75051923aaa5623d7d1a4b2d36e0e93f54392269c6d32de58db718c0866a", + "tables": [ + "MessageUrlInfo" + ], + "decision": "accept", + "evidence": "User approved exact query /items/34/content/items/7/content/query SHA256 36ec75051923aaa5623d7d1a4b2d36e0e93f54392269c6d32de58db718c0866a; complete discovered native inputs: MessageUrlInfo. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/35/content/items/2/content/query", + "querySha256": "62029ecfef97ec15504028257c2a5d2f94ce8a1d9764529436f166426143fd61", + "tables": [ + "MessageEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/35/content/items/2/content/query SHA256 62029ecfef97ec15504028257c2a5d2f94ce8a1d9764529436f166426143fd61; complete discovered native inputs: MessageEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/35/content/items/5/content/query", + "querySha256": "dffcadfd238a9e7b7648a27145cc7af9367c36cac839e2a0d4d5da8f0429a048", + "tables": [ + "MessageEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/35/content/items/5/content/query SHA256 dffcadfd238a9e7b7648a27145cc7af9367c36cac839e2a0d4d5da8f0429a048; complete discovered native inputs: MessageEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/35/content/items/6/content/query", + "querySha256": "d6b04c158fd6f88e4f82f99f6e2b0ab2819bdef7f05cabd7eedb790785f672ef", + "tables": [ + "MessageEvents", + "MessageUrlInfo" + ], + "decision": "accept", + "evidence": "User approved exact query /items/35/content/items/6/content/query SHA256 d6b04c158fd6f88e4f82f99f6e2b0ab2819bdef7f05cabd7eedb790785f672ef; complete discovered native inputs: MessageEvents, MessageUrlInfo. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/35/content/items/8/content/query", + "querySha256": "95180a15fb5a1004fcd60cd3fe6ba3b87f78e527c750d1d34c9dd1479c5b7bca", + "tables": [ + "MessageEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/35/content/items/8/content/query SHA256 95180a15fb5a1004fcd60cd3fe6ba3b87f78e527c750d1d34c9dd1479c5b7bca; complete discovered native inputs: MessageEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/35/content/items/10/content/query", + "querySha256": "a4b746884de5bb6d00bda9112992bd181df314fcbd1fc660bf27f346bc48659f", + "tables": [ + "MessageEvents", + "MessageUrlInfo" + ], + "decision": "accept", + "evidence": "User approved exact query /items/35/content/items/10/content/query SHA256 a4b746884de5bb6d00bda9112992bd181df314fcbd1fc660bf27f346bc48659f; complete discovered native inputs: MessageEvents, MessageUrlInfo. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/35/content/items/12/content/query", + "querySha256": "f2a08f578478be075836e68925004bcec49cde95c39255ae9e47d528567de15a", + "tables": [ + "MessageEvents", + "MessageUrlInfo" + ], + "decision": "accept", + "evidence": "User approved exact query /items/35/content/items/12/content/query SHA256 f2a08f578478be075836e68925004bcec49cde95c39255ae9e47d528567de15a; complete discovered native inputs: MessageEvents, MessageUrlInfo. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/35/content/items/14/content/query", + "querySha256": "60927037752038d2fd6d87c837a755835d795e4167f2d549413e0ea05e8bcb21", + "tables": [ + "MessageUrlInfo" + ], + "decision": "accept", + "evidence": "User approved exact query /items/35/content/items/14/content/query SHA256 60927037752038d2fd6d87c837a755835d795e4167f2d549413e0ea05e8bcb21; complete discovered native inputs: MessageUrlInfo. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/36/content/items/1/content/query", + "querySha256": "4b63c2185466fb2c0dbb2ac9cf40db7e8cc9937e1fe634739b699730519de15f", + "tables": [ + "FileMaliciousContentInfo" + ], + "decision": "accept", + "evidence": "User approved exact query /items/36/content/items/1/content/query SHA256 4b63c2185466fb2c0dbb2ac9cf40db7e8cc9937e1fe634739b699730519de15f; complete discovered native inputs: FileMaliciousContentInfo. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/36/content/items/3/content/query", + "querySha256": "dcb287d16b575c18bc08e9b93108034de2a21143f6c2cffc4d6afb357f0467c9", + "tables": [ + "FileMaliciousContentInfo" + ], + "decision": "accept", + "evidence": "User approved exact query /items/36/content/items/3/content/query SHA256 dcb287d16b575c18bc08e9b93108034de2a21143f6c2cffc4d6afb357f0467c9; complete discovered native inputs: FileMaliciousContentInfo. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/37/content/items/1/content/query", + "querySha256": "d56012dfdfeab7ea980d7397bb06f4dc4f525632b6e855c3f630cb3bdfe53004", + "tables": [ + "MessagePostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/37/content/items/1/content/query SHA256 d56012dfdfeab7ea980d7397bb06f4dc4f525632b6e855c3f630cb3bdfe53004; complete discovered native inputs: MessagePostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/37/content/items/4/content/query", + "querySha256": "b2e02ff93ae4800c4296fa4e53f2e91f2124a861d267f8c3f37eeac9bf1406f0", + "tables": [ + "MessagePostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/37/content/items/4/content/query SHA256 b2e02ff93ae4800c4296fa4e53f2e91f2124a861d267f8c3f37eeac9bf1406f0; complete discovered native inputs: MessagePostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/37/content/items/5/content/query", + "querySha256": "6797ba254b49a324742a1644fa0f7b25f1ca5ec2dbcc89de72f01557f3fa6e51", + "tables": [ + "MessagePostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/37/content/items/5/content/query SHA256 6797ba254b49a324742a1644fa0f7b25f1ca5ec2dbcc89de72f01557f3fa6e51; complete discovered native inputs: MessagePostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/37/content/items/7/content/query", + "querySha256": "5b242c6518220d383b9aaf3c3c322115b22b7599436fa6aa50afb33584cd5ca7", + "tables": [ + "MessagePostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/37/content/items/7/content/query SHA256 5b242c6518220d383b9aaf3c3c322115b22b7599436fa6aa50afb33584cd5ca7; complete discovered native inputs: MessagePostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/38/content/items/1/content/query", + "querySha256": "74c47338b18595934a5cd4d8876022224fd7af6ac94bd7800a49d61c645afbcb", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/38/content/items/1/content/query SHA256 74c47338b18595934a5cd4d8876022224fd7af6ac94bd7800a49d61c645afbcb; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/38/content/items/4/content/query", + "querySha256": "6afdeb4bbcf6ec7dab9d2f4a84fad1abc3b552b5228a31eb14a60f5e6ec0e6ee", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/38/content/items/4/content/query SHA256 6afdeb4bbcf6ec7dab9d2f4a84fad1abc3b552b5228a31eb14a60f5e6ec0e6ee; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/38/content/items/5/content/query", + "querySha256": "d5f5be5c1701660a6b52e02e0a43917c49bed7cc2745efdb9436e3b7ca68aebd", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/38/content/items/5/content/query SHA256 d5f5be5c1701660a6b52e02e0a43917c49bed7cc2745efdb9436e3b7ca68aebd; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/38/content/items/8/content/query", + "querySha256": "20e3b3ec8989478391f8c351684f4697b1865b0cce1f6b155f62529395a26344", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/38/content/items/8/content/query SHA256 20e3b3ec8989478391f8c351684f4697b1865b0cce1f6b155f62529395a26344; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/38/content/items/9/content/query", + "querySha256": "0acd8c2aa4ba1955856bf9c4c749ddee5d172f2f6d549331427e5e7ea4978fd6", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/38/content/items/9/content/query SHA256 0acd8c2aa4ba1955856bf9c4c749ddee5d172f2f6d549331427e5e7ea4978fd6; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/38/content/items/12/content/query", + "querySha256": "04d009f7216f66a76abb64250089d8989722f096714424cc35cb7b9e3c1590bf", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/38/content/items/12/content/query SHA256 04d009f7216f66a76abb64250089d8989722f096714424cc35cb7b9e3c1590bf; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/38/content/items/13/content/query", + "querySha256": "d9fc4429458d6768986d75534c7e5b287febb131f98df1013b36157ec0453cdf", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/38/content/items/13/content/query SHA256 d9fc4429458d6768986d75534c7e5b287febb131f98df1013b36157ec0453cdf; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/38/content/items/16/content/query", + "querySha256": "2b779b661ef05861dc698417ce4c3ace11bf5e24c7112b669570d79957640189", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/38/content/items/16/content/query SHA256 2b779b661ef05861dc698417ce4c3ace11bf5e24c7112b669570d79957640189; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/38/content/items/17/content/query", + "querySha256": "97fd2970619fa0b5a172a616deaa5a9f27f21eab634de028226e1114c1adfefa", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/38/content/items/17/content/query SHA256 97fd2970619fa0b5a172a616deaa5a9f27f21eab634de028226e1114c1adfefa; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/39/content/items/2/content/query", + "querySha256": "0fb110cc01724b5f264e5aaa5c0a3e6b4be6050260a6e29a9a0d2c7fe21ed919", + "tables": [ + "MessageEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/39/content/items/2/content/query SHA256 0fb110cc01724b5f264e5aaa5c0a3e6b4be6050260a6e29a9a0d2c7fe21ed919; complete discovered native inputs: MessageEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/39/content/items/4/content/query", + "querySha256": "4b9639f39ccb32743e168a2b1d02e8703a134387a8f8e80a368b383c8f831333", + "tables": [ + "MessageEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/39/content/items/4/content/query SHA256 4b9639f39ccb32743e168a2b1d02e8703a134387a8f8e80a368b383c8f831333; complete discovered native inputs: MessageEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/41/content/items/2/content/query", + "querySha256": "9d59f8c46ce5618c306f4f088c16dcdfa3d0640dea57a088b167b93dd2a8ea24", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/41/content/items/2/content/query SHA256 9d59f8c46ce5618c306f4f088c16dcdfa3d0640dea57a088b167b93dd2a8ea24; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/41/content/items/4/content/query", + "querySha256": "ac961ffab2badfb22671c80ef61f1487dcf566403fc4dce05933d1e41062b334", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/41/content/items/4/content/query SHA256 ac961ffab2badfb22671c80ef61f1487dcf566403fc4dce05933d1e41062b334; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/41/content/items/6/content/query", + "querySha256": "fceefa84bd5d3373ad7b9ec5550c32752c299351566c94db662127b239a08d89", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/41/content/items/6/content/query SHA256 fceefa84bd5d3373ad7b9ec5550c32752c299351566c94db662127b239a08d89; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/42/content/items/3/content/query", + "querySha256": "5e0116bf9f5d0bc3393442882c18bcbcb7c7de3552a08ca36ca34e74b571b4ca", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/42/content/items/3/content/query SHA256 5e0116bf9f5d0bc3393442882c18bcbcb7c7de3552a08ca36ca34e74b571b4ca; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/42/content/items/4/content/query", + "querySha256": "7dbef8b884dd43cc125e9c117b67264abeaae9d61cfd118b9d6716b4651bafad", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/42/content/items/4/content/query SHA256 7dbef8b884dd43cc125e9c117b67264abeaae9d61cfd118b9d6716b4651bafad; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/42/content/items/6/content/query", + "querySha256": "17f3884ff63e526609f3cf6853e35fae3eb67888c3b17c22d44641353f4c1886", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/42/content/items/6/content/query SHA256 17f3884ff63e526609f3cf6853e35fae3eb67888c3b17c22d44641353f4c1886; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/42/content/items/9/content/query", + "querySha256": "0051da9da84fd58c4227dfa6801a0fc16a44d77c2e336d0b1aad7995862f15bf", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/42/content/items/9/content/query SHA256 0051da9da84fd58c4227dfa6801a0fc16a44d77c2e336d0b1aad7995862f15bf; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/42/content/items/10/content/query", + "querySha256": "63f1fbdcafb468c66e1febf1482a7f3463d594eeb4394214aafb0e20b6df5551", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/42/content/items/10/content/query SHA256 63f1fbdcafb468c66e1febf1482a7f3463d594eeb4394214aafb0e20b6df5551; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/42/content/items/12/content/query", + "querySha256": "7a240719dc0518ec4cd9fbb8458bdba5043dc188e73ccc4079238ff38a3f5ded", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/42/content/items/12/content/query SHA256 7a240719dc0518ec4cd9fbb8458bdba5043dc188e73ccc4079238ff38a3f5ded; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/42/content/items/15/content/query", + "querySha256": "f419065f15e2b1933db7f5ad38dcbc907dc999bbe3c10400a02732e1b85ef9e9", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/42/content/items/15/content/query SHA256 f419065f15e2b1933db7f5ad38dcbc907dc999bbe3c10400a02732e1b85ef9e9; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/42/content/items/16/content/query", + "querySha256": "4e4912f05c0a6b730d36f0571fe9b520d19c6cc77048e7a7d827ac38cde51ece", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/42/content/items/16/content/query SHA256 4e4912f05c0a6b730d36f0571fe9b520d19c6cc77048e7a7d827ac38cde51ece; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/44/content/items/2/content/query", + "querySha256": "98841a54452a812aa4fb1d340d18cc6ad07db86fec6ead416e83493936120eec", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/44/content/items/2/content/query SHA256 98841a54452a812aa4fb1d340d18cc6ad07db86fec6ead416e83493936120eec; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/44/content/items/5/content/query", + "querySha256": "08eb36cc6b166e767c0298ceac0436bd7dcd8ee1529950c0900e62f533436c43", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/44/content/items/5/content/query SHA256 08eb36cc6b166e767c0298ceac0436bd7dcd8ee1529950c0900e62f533436c43; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/44/content/items/6/content/query", + "querySha256": "479581dfceba4451dbdf7519a43485982e518fc2508e7008a552d26c58474d10", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/44/content/items/6/content/query SHA256 479581dfceba4451dbdf7519a43485982e518fc2508e7008a552d26c58474d10; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/44/content/items/8/content/query", + "querySha256": "605f590cbbd6fdc3484113461d66c5d0b477e6bb4bcb108ce19b4a38d770fc97", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/44/content/items/8/content/query SHA256 605f590cbbd6fdc3484113461d66c5d0b477e6bb4bcb108ce19b4a38d770fc97; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/44/content/items/9/content/query", + "querySha256": "fd049e88fa8087c8310c7c8f5921ae01ae9d30c2f378b8dfc0c987bc882bdc55", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/44/content/items/9/content/query SHA256 fd049e88fa8087c8310c7c8f5921ae01ae9d30c2f378b8dfc0c987bc882bdc55; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/45/content/items/2/content/query", + "querySha256": "0191481702bf99320c3c3ad445bb2e8a562c98b46d86efa5a17bcf9b1ef9eb94", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/45/content/items/2/content/query SHA256 0191481702bf99320c3c3ad445bb2e8a562c98b46d86efa5a17bcf9b1ef9eb94; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/45/content/items/5/content/query", + "querySha256": "01b0947f0335fa298b8afea14dcc5e146680f766523ab941ff94b982afb7d45c", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/45/content/items/5/content/query SHA256 01b0947f0335fa298b8afea14dcc5e146680f766523ab941ff94b982afb7d45c; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/45/content/items/6/content/query", + "querySha256": "5308d5b51d6cc5c05ec341e7da32f8f3291d9f0a9c86842f71f9522be78e0d26", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/45/content/items/6/content/query SHA256 5308d5b51d6cc5c05ec341e7da32f8f3291d9f0a9c86842f71f9522be78e0d26; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/46/content/items/2/content/query", + "querySha256": "8eb5d94e482fa58347a8ce7121a05ac0d42d087646d610ed7268b982f821a6df", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/46/content/items/2/content/query SHA256 8eb5d94e482fa58347a8ce7121a05ac0d42d087646d610ed7268b982f821a6df; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/46/content/items/5/content/query", + "querySha256": "634ea17d6cce9c0c9779764b703ddc1cfce8f66aa5d6c9124e913e33f368e4e3", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/46/content/items/5/content/query SHA256 634ea17d6cce9c0c9779764b703ddc1cfce8f66aa5d6c9124e913e33f368e4e3; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/46/content/items/6/content/query", + "querySha256": "39177dbcea32c9061429809d0735bb1ff809bc2050b5c20fe60cba294737ba07", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/46/content/items/6/content/query SHA256 39177dbcea32c9061429809d0735bb1ff809bc2050b5c20fe60cba294737ba07; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/47/content/items/2/content/query", + "querySha256": "98ae122b7b16d93a3b04c8c4bff31071fe303ddbb0395a629a7c77f0d4094a4e", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/47/content/items/2/content/query SHA256 98ae122b7b16d93a3b04c8c4bff31071fe303ddbb0395a629a7c77f0d4094a4e; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/47/content/items/5/content/query", + "querySha256": "038df3e31a9bd7d87478d0db455c54d07eb82935fe7f53a11faaddaefd310858", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/47/content/items/5/content/query SHA256 038df3e31a9bd7d87478d0db455c54d07eb82935fe7f53a11faaddaefd310858; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/47/content/items/6/content/query", + "querySha256": "11597c350853d749382e4f898978edbdfc528bb6930690b985201cd197737a43", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/47/content/items/6/content/query SHA256 11597c350853d749382e4f898978edbdfc528bb6930690b985201cd197737a43; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/48/content/items/1/content/query", + "querySha256": "dab1d4deeaa36005a3c935359196c47841107592a702f815bfca3087aecfa108", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/48/content/items/1/content/query SHA256 dab1d4deeaa36005a3c935359196c47841107592a702f815bfca3087aecfa108; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/48/content/items/2/content/query", + "querySha256": "cfe62517a4c1056dead45ef4655eb3a7bd13844272f2e92522e92c06be146eed", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/48/content/items/2/content/query SHA256 cfe62517a4c1056dead45ef4655eb3a7bd13844272f2e92522e92c06be146eed; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/50/content/items/2/content/query", + "querySha256": "6020e0927daa1fef5e01740cf193e8b6b53be2df55ce4d097d1b9e9af8fe5603", + "tables": [ + "CloudAppEvents", + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/50/content/items/2/content/query SHA256 6020e0927daa1fef5e01740cf193e8b6b53be2df55ce4d097d1b9e9af8fe5603; complete discovered native inputs: CloudAppEvents, EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/50/content/items/5/content/query", + "querySha256": "07335ac977d13181fb7d411d158bfab30b680d3644e16c8211f384e3413e14a9", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/50/content/items/5/content/query SHA256 07335ac977d13181fb7d411d158bfab30b680d3644e16c8211f384e3413e14a9; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/50/content/items/6/content/query", + "querySha256": "ae9cfa969dc3fa98eecab3e33895123d8ebe2e0ea45d848719aa31ccee2930e5", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/50/content/items/6/content/query SHA256 ae9cfa969dc3fa98eecab3e33895123d8ebe2e0ea45d848719aa31ccee2930e5; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/50/content/items/9/content/query", + "querySha256": "c117a2d84bd97df6b74b225278f0777be5c7fc23787241ed897c31080ddccf20", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/50/content/items/9/content/query SHA256 c117a2d84bd97df6b74b225278f0777be5c7fc23787241ed897c31080ddccf20; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/50/content/items/10/content/query", + "querySha256": "d5c27998417b90d3c5b0a62e92cb1ec067b53953072483c45c3702ea26d0128f", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/50/content/items/10/content/query SHA256 d5c27998417b90d3c5b0a62e92cb1ec067b53953072483c45c3702ea26d0128f; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/50/content/items/12/content/query", + "querySha256": "1cdb86b390d21c72e50df9d4bf8b62fe908de31edb727f5e9a63b5f4917a9f4b", + "tables": [ + "CloudAppEvents", + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/50/content/items/12/content/query SHA256 1cdb86b390d21c72e50df9d4bf8b62fe908de31edb727f5e9a63b5f4917a9f4b; complete discovered native inputs: CloudAppEvents, EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/50/content/items/14/content/query", + "querySha256": "747ee111c8ee30f787f5d503bfcead7f08e4c84dbc62cc750e1dddae76ee1f70", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/50/content/items/14/content/query SHA256 747ee111c8ee30f787f5d503bfcead7f08e4c84dbc62cc750e1dddae76ee1f70; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/51/content/items/2/content/query", + "querySha256": "190c560e0a844d97439beaa78531501c980cbc57205552ed4d3aa74a75432544", + "tables": [ + "CloudAppEvents", + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/51/content/items/2/content/query SHA256 190c560e0a844d97439beaa78531501c980cbc57205552ed4d3aa74a75432544; complete discovered native inputs: CloudAppEvents, EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/51/content/items/5/content/query", + "querySha256": "4ec67e14891fb4eaee26027655c919bee250246646f01f91837f1d93fcf5b17a", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/51/content/items/5/content/query SHA256 4ec67e14891fb4eaee26027655c919bee250246646f01f91837f1d93fcf5b17a; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/51/content/items/6/content/query", + "querySha256": "bbbfd512ecfb4772f33fb2eda6f71e470f9a2e5e6c6d87a727113a0d863b8e53", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/51/content/items/6/content/query SHA256 bbbfd512ecfb4772f33fb2eda6f71e470f9a2e5e6c6d87a727113a0d863b8e53; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/51/content/items/8/content/query", + "querySha256": "17b36c25f276a7ff82978008d44a8988234315b3d3762b20f04960e92adafd3f", + "tables": [ + "CloudAppEvents", + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/51/content/items/8/content/query SHA256 17b36c25f276a7ff82978008d44a8988234315b3d3762b20f04960e92adafd3f; complete discovered native inputs: CloudAppEvents, EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/51/content/items/9/content/query", + "querySha256": "87241ae8c69a092670d36b458c788b767ceb248dfa85cc4bf364e80f6eb9757d", + "tables": [ + "CloudAppEvents", + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/51/content/items/9/content/query SHA256 87241ae8c69a092670d36b458c788b767ceb248dfa85cc4bf364e80f6eb9757d; complete discovered native inputs: CloudAppEvents, EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/51/content/items/12/content/query", + "querySha256": "7bca4d4dd4db1c3c3789edf2817216821aa859846d5291dac6f29c0cce09a15d", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/51/content/items/12/content/query SHA256 7bca4d4dd4db1c3c3789edf2817216821aa859846d5291dac6f29c0cce09a15d; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/51/content/items/13/content/query", + "querySha256": "0a164920cbdf7d1d27cb8a5e2753d3e3ba1565f10f2476c9daf3732e7f4e51ca", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/51/content/items/13/content/query SHA256 0a164920cbdf7d1d27cb8a5e2753d3e3ba1565f10f2476c9daf3732e7f4e51ca; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/51/content/items/15/content/query", + "querySha256": "2ff628e131399a7d636349ebdd421d29f7a21434c2690d04e68577c870b425ed", + "tables": [ + "CloudAppEvents", + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/51/content/items/15/content/query SHA256 2ff628e131399a7d636349ebdd421d29f7a21434c2690d04e68577c870b425ed; complete discovered native inputs: CloudAppEvents, EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/51/content/items/17/content/query", + "querySha256": "5a3bd5ba09ef5bdeb326e9c37633cca5ab76566d5e0023bdbca7ba8ba22b9ed2", + "tables": [ + "CloudAppEvents", + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/51/content/items/17/content/query SHA256 5a3bd5ba09ef5bdeb326e9c37633cca5ab76566d5e0023bdbca7ba8ba22b9ed2; complete discovered native inputs: CloudAppEvents, EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/51/content/items/19/content/query", + "querySha256": "4242a874bb7bfd3b4571641f2f448a2cfabd00415c8cdb14a2da887b60e8c94d", + "tables": [ + "CloudAppEvents", + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/51/content/items/19/content/query SHA256 4242a874bb7bfd3b4571641f2f448a2cfabd00415c8cdb14a2da887b60e8c94d; complete discovered native inputs: CloudAppEvents, EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/51/content/items/21/content/query", + "querySha256": "076baa0f569360603bcad7368056a253218abf225d4fa285b14ac64612a7793d", + "tables": [ + "CloudAppEvents", + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/51/content/items/21/content/query SHA256 076baa0f569360603bcad7368056a253218abf225d4fa285b14ac64612a7793d; complete discovered native inputs: CloudAppEvents, EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/51/content/items/23/content/query", + "querySha256": "a64a3faaafc023d58d21107ed15f6257956f5c6120e99ca38ec9259db46d029f", + "tables": [ + "CloudAppEvents", + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/51/content/items/23/content/query SHA256 a64a3faaafc023d58d21107ed15f6257956f5c6120e99ca38ec9259db46d029f; complete discovered native inputs: CloudAppEvents, EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/51/content/items/25/content/query", + "querySha256": "dc2fe8fc6f590d33ed0ddb60662f0fb9b243333bfecd10a332b96772a03ee33c", + "tables": [ + "CloudAppEvents", + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/51/content/items/25/content/query SHA256 dc2fe8fc6f590d33ed0ddb60662f0fb9b243333bfecd10a332b96772a03ee33c; complete discovered native inputs: CloudAppEvents, EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/51/content/items/27/content/query", + "querySha256": "ce551d10e6dee3b5d32931fbe168fbc33bdd09db68897a54df679c31dd10ab25", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/51/content/items/27/content/query SHA256 ce551d10e6dee3b5d32931fbe168fbc33bdd09db68897a54df679c31dd10ab25; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/51/content/items/29/content/query", + "querySha256": "2435d71ca693e67251e18f93be23b59a6e745fe1ab1559e8ce1cbaae6aa797a2", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/51/content/items/29/content/query SHA256 2435d71ca693e67251e18f93be23b59a6e745fe1ab1559e8ce1cbaae6aa797a2; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/53/content/items/2/content/query", + "querySha256": "1ec8d0bdae64ae23b8670d90f62e063d73e0a031c151d4f3f9881998ee3b677e", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/53/content/items/2/content/query SHA256 1ec8d0bdae64ae23b8670d90f62e063d73e0a031c151d4f3f9881998ee3b677e; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/53/content/items/3/content/query", + "querySha256": "84ff7dba1257d1b322d0a5fcb61924e0e174fd65efd56c5b916de7f53ef8a1c1", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/53/content/items/3/content/query SHA256 84ff7dba1257d1b322d0a5fcb61924e0e174fd65efd56c5b916de7f53ef8a1c1; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/53/content/items/6/content/query", + "querySha256": "a127712060a9efb1387daff4836de6b7b66b5b366fa16c37da5d5145c0241908", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/53/content/items/6/content/query SHA256 a127712060a9efb1387daff4836de6b7b66b5b366fa16c37da5d5145c0241908; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/53/content/items/7/content/query", + "querySha256": "e47978375215d7dd1f8eab2a73be26e59388ded6590c4d3e051fa81fb53b4076", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/53/content/items/7/content/query SHA256 e47978375215d7dd1f8eab2a73be26e59388ded6590c4d3e051fa81fb53b4076; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/53/content/items/9/content/query", + "querySha256": "4e0eebac5a1e8e0252ddc22b1f32bbb64c350e4bd68c5be2f2b372eb332793eb", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/53/content/items/9/content/query SHA256 4e0eebac5a1e8e0252ddc22b1f32bbb64c350e4bd68c5be2f2b372eb332793eb; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/53/content/items/11/content/query", + "querySha256": "942f49b9d76b441e429e52472521cf70bea50866823f8deeed6b466b36bfc6cd", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/53/content/items/11/content/query SHA256 942f49b9d76b441e429e52472521cf70bea50866823f8deeed6b466b36bfc6cd; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/53/content/items/13/content/query", + "querySha256": "e3d2d9612489838c00ae7aa00cdb34680ec8f9305ff4207e31683850c63bb299", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/53/content/items/13/content/query SHA256 e3d2d9612489838c00ae7aa00cdb34680ec8f9305ff4207e31683850c63bb299; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/53/content/items/16/content/query", + "querySha256": "cca5d9e2b3d5e82f36d0925d5f0729efbb674450d043ae44c758063734b8c1a9", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/53/content/items/16/content/query SHA256 cca5d9e2b3d5e82f36d0925d5f0729efbb674450d043ae44c758063734b8c1a9; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/53/content/items/17/content/query", + "querySha256": "5bcc51c8dd3bc4ca8453963c5fda413933c9c7797654ac4e6870c319eb5cb597", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/53/content/items/17/content/query SHA256 5bcc51c8dd3bc4ca8453963c5fda413933c9c7797654ac4e6870c319eb5cb597; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/54/content/items/2/content/query", + "querySha256": "67eab6668c5bbeaedd89ff5dd96d450db4dbb474face6b42c169077a2131f8bc", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/54/content/items/2/content/query SHA256 67eab6668c5bbeaedd89ff5dd96d450db4dbb474face6b42c169077a2131f8bc; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/54/content/items/5/content/query", + "querySha256": "8fa077a5e7acb929d4f838162f74ec00683d1dc97909896cd41a43f6095193e1", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/54/content/items/5/content/query SHA256 8fa077a5e7acb929d4f838162f74ec00683d1dc97909896cd41a43f6095193e1; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/54/content/items/6/content/query", + "querySha256": "06dfd0f0530c4081e868b6e444c344f00b01c0da62fbeaf59b1819d0ebfbdd56", + "tables": [ + "CloudAppEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/54/content/items/6/content/query SHA256 06dfd0f0530c4081e868b6e444c344f00b01c0da62fbeaf59b1819d0ebfbdd56; complete discovered native inputs: CloudAppEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/54/content/items/8/content/query", + "querySha256": "74d2514387026a9cbca80d7c6632732f497e6a9326931485517d26a115bc1098", + "tables": [ + "CloudAppEvents", + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/54/content/items/8/content/query SHA256 74d2514387026a9cbca80d7c6632732f497e6a9326931485517d26a115bc1098; complete discovered native inputs: CloudAppEvents, EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/54/content/items/10/content/query", + "querySha256": "0a98d004faf373375334191fda0147f3af0812c7ae871251a5728f1ffa5e72cd", + "tables": [ + "CloudAppEvents", + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/54/content/items/10/content/query SHA256 0a98d004faf373375334191fda0147f3af0812c7ae871251a5728f1ffa5e72cd; complete discovered native inputs: CloudAppEvents, EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/54/content/items/12/content/query", + "querySha256": "3ef8df7f0af5e964483dd0d200d7015e761031dc4284f6c843af47858e0b56f0", + "tables": [ + "CloudAppEvents", + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/54/content/items/12/content/query SHA256 3ef8df7f0af5e964483dd0d200d7015e761031dc4284f6c843af47858e0b56f0; complete discovered native inputs: CloudAppEvents, EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/54/content/items/14/content/query", + "querySha256": "01d2c3a9084d16561d96d52b2a9f43158cd0b5805f1bd1503f19bd79fc1fd0b1", + "tables": [ + "CloudAppEvents", + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/54/content/items/14/content/query SHA256 01d2c3a9084d16561d96d52b2a9f43158cd0b5805f1bd1503f19bd79fc1fd0b1; complete discovered native inputs: CloudAppEvents, EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/54/content/items/16/content/query", + "querySha256": "dee4810b520a32ee3eda3665ec91442f6b1b94e403bf850472313c0b0b92cc89", + "tables": [ + "CloudAppEvents", + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/54/content/items/16/content/query SHA256 dee4810b520a32ee3eda3665ec91442f6b1b94e403bf850472313c0b0b92cc89; complete discovered native inputs: CloudAppEvents, EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/54/content/items/18/content/query", + "querySha256": "e855970dd652ea06edb6c39d05056de221c92079455389ff1c874c674260434e", + "tables": [ + "CloudAppEvents", + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/54/content/items/18/content/query SHA256 e855970dd652ea06edb6c39d05056de221c92079455389ff1c874c674260434e; complete discovered native inputs: CloudAppEvents, EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/54/content/items/20/content/query", + "querySha256": "574a57a292b61a545e06d553089b20c675d2deeebd757cc4041f71ee296658f2", + "tables": [ + "CloudAppEvents", + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/54/content/items/20/content/query SHA256 574a57a292b61a545e06d553089b20c675d2deeebd757cc4041f71ee296658f2; complete discovered native inputs: CloudAppEvents, EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/56/content/query", + "querySha256": "ee6b26c853c749ddefdc422e3bf84d8957cfc20ec68caf97ea50c45a86fe6b8b", + "tables": [ + "FileMaliciousContentInfo" + ], + "decision": "accept", + "evidence": "User approved exact query /items/56/content/query SHA256 ee6b26c853c749ddefdc422e3bf84d8957cfc20ec68caf97ea50c45a86fe6b8b; complete discovered native inputs: FileMaliciousContentInfo. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/57/content/items/2/content/query", + "querySha256": "3f30b8073c8b9cfd3304c7294b4171f12b9760e27160c598bcf9843a95234022", + "tables": [ + "FileMaliciousContentInfo" + ], + "decision": "accept", + "evidence": "User approved exact query /items/57/content/items/2/content/query SHA256 3f30b8073c8b9cfd3304c7294b4171f12b9760e27160c598bcf9843a95234022; complete discovered native inputs: FileMaliciousContentInfo. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/57/content/items/4/content/query", + "querySha256": "87a79048564af89105306f9f0eb6e49d2877f0cb1fe9e4fdbe325666b51b4ff7", + "tables": [ + "FileMaliciousContentInfo" + ], + "decision": "accept", + "evidence": "User approved exact query /items/57/content/items/4/content/query SHA256 87a79048564af89105306f9f0eb6e49d2877f0cb1fe9e4fdbe325666b51b4ff7; complete discovered native inputs: FileMaliciousContentInfo. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/57/content/items/6/content/query", + "querySha256": "9ea07eb7836f2e2b1040b6b6e44a86a4c61d61e49c16dc1428c6fc2bb7b6d9d6", + "tables": [ + "FileMaliciousContentInfo" + ], + "decision": "accept", + "evidence": "User approved exact query /items/57/content/items/6/content/query SHA256 9ea07eb7836f2e2b1040b6b6e44a86a4c61d61e49c16dc1428c6fc2bb7b6d9d6; complete discovered native inputs: FileMaliciousContentInfo. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/57/content/items/9/content/query", + "querySha256": "83eaddab2b108a2803044a325510009d0047dd94858008d869c8659b7ceb14cf", + "tables": [ + "FileMaliciousContentInfo" + ], + "decision": "accept", + "evidence": "User approved exact query /items/57/content/items/9/content/query SHA256 83eaddab2b108a2803044a325510009d0047dd94858008d869c8659b7ceb14cf; complete discovered native inputs: FileMaliciousContentInfo. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/57/content/items/10/content/query", + "querySha256": "ddfe37ebdf81dc3035d9491a0fc453cd230d183059224a86193e44f1e852f98f", + "tables": [ + "FileMaliciousContentInfo" + ], + "decision": "accept", + "evidence": "User approved exact query /items/57/content/items/10/content/query SHA256 ddfe37ebdf81dc3035d9491a0fc453cd230d183059224a86193e44f1e852f98f; complete discovered native inputs: FileMaliciousContentInfo. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/57/content/items/12/content/query", + "querySha256": "c0af2e879bb305a1ab536cf7aa9a94c0da845893774b6af9441c54e7e26c20d8", + "tables": [ + "FileMaliciousContentInfo" + ], + "decision": "accept", + "evidence": "User approved exact query /items/57/content/items/12/content/query SHA256 c0af2e879bb305a1ab536cf7aa9a94c0da845893774b6af9441c54e7e26c20d8; complete discovered native inputs: FileMaliciousContentInfo. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/59/content/items/3/content/query", + "querySha256": "edac2c04a18e08b3c8a7fdfe6e239e2d594008e09c07b78183ace649b0afcd49", + "tables": [ + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/59/content/items/3/content/query SHA256 edac2c04a18e08b3c8a7fdfe6e239e2d594008e09c07b78183ace649b0afcd49; complete discovered native inputs: EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/59/content/items/4/content/query", + "querySha256": "81205f70e013612c81806cbd61ce60b78f4bbfaf406cc4b71f15d729ffe318ed", + "tables": [ + "EmailEvents", + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/59/content/items/4/content/query SHA256 81205f70e013612c81806cbd61ce60b78f4bbfaf406cc4b71f15d729ffe318ed; complete discovered native inputs: EmailEvents, EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/59/content/items/6/content/query", + "querySha256": "b092296adbbd8f13d3ba1dd7ce16b3d4430acf7e0c5b9245dcb65e8305634561", + "tables": [ + "EmailEvents", + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/59/content/items/6/content/query SHA256 b092296adbbd8f13d3ba1dd7ce16b3d4430acf7e0c5b9245dcb65e8305634561; complete discovered native inputs: EmailEvents, EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/60/content/items/2/content/query", + "querySha256": "f80a170b71ca7aea90a853d397c7cc66efc0727f7e8b1136c999be841598810a", + "tables": [ + "EmailEvents", + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/60/content/items/2/content/query SHA256 f80a170b71ca7aea90a853d397c7cc66efc0727f7e8b1136c999be841598810a; complete discovered native inputs: EmailEvents, EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/60/content/items/5/content/query", + "querySha256": "b9a2ddf63c5404a5073a9d0a9707bd5adfe06254d526136d9c94310279a51965", + "tables": [ + "EmailEvents", + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/60/content/items/5/content/query SHA256 b9a2ddf63c5404a5073a9d0a9707bd5adfe06254d526136d9c94310279a51965; complete discovered native inputs: EmailEvents, EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/60/content/items/6/content/query", + "querySha256": "3bc615d6bc4814e663b33dee2194e9c20b3664fea51cf465413b5931bebbb30e", + "tables": [ + "EmailEvents", + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/60/content/items/6/content/query SHA256 3bc615d6bc4814e663b33dee2194e9c20b3664fea51cf465413b5931bebbb30e; complete discovered native inputs: EmailEvents, EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/60/content/items/8/content/query", + "querySha256": "613f59e248e2eab9ad627bc17fd671a48892e3ba03cd55291062e0247cffde9b", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/60/content/items/8/content/query SHA256 613f59e248e2eab9ad627bc17fd671a48892e3ba03cd55291062e0247cffde9b; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/60/content/items/9/content/query", + "querySha256": "f038b8c64ee2b6006197ae4f79bfbcaa804bded2a217d5a1cb1cbdb9fe7c3ea2", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/60/content/items/9/content/query SHA256 f038b8c64ee2b6006197ae4f79bfbcaa804bded2a217d5a1cb1cbdb9fe7c3ea2; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/60/content/items/11/content/query", + "querySha256": "25b86347cd154b8e771535c9325c88198b601d431805ca0e7ed7ff6ab2c07f74", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/60/content/items/11/content/query SHA256 25b86347cd154b8e771535c9325c88198b601d431805ca0e7ed7ff6ab2c07f74; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/60/content/items/12/content/query", + "querySha256": "d60acc2675082cf943ddec5d9e20e15c2062248cd551c8496e15c7eace2fbe40", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/60/content/items/12/content/query SHA256 d60acc2675082cf943ddec5d9e20e15c2062248cd551c8496e15c7eace2fbe40; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/60/content/items/14/content/query", + "querySha256": "b16218774694e423515732434466775a515223c7db107d015853617ad6951203", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/60/content/items/14/content/query SHA256 b16218774694e423515732434466775a515223c7db107d015853617ad6951203; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/60/content/items/15/content/query", + "querySha256": "c48959232f63cbd06ace85302b75f0cb07dda479598e7c91e8d8b2cb01080ddc", + "tables": [ + "EmailEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/60/content/items/15/content/query SHA256 c48959232f63cbd06ace85302b75f0cb07dda479598e7c91e8d8b2cb01080ddc; complete discovered native inputs: EmailEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/63/content/items/2/content/query", + "querySha256": "db26d96be276c8946212e0211434d4267fdf79ce1261ad7974477d966fb1c7f9", + "tables": [ + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/63/content/items/2/content/query SHA256 db26d96be276c8946212e0211434d4267fdf79ce1261ad7974477d966fb1c7f9; complete discovered native inputs: EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/63/content/items/4/content/query", + "querySha256": "ba98b4288543b6bc2c36341afad18fd44fddec3ef80da5315adaf5fb63391815", + "tables": [ + "EmailEvents", + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/63/content/items/4/content/query SHA256 ba98b4288543b6bc2c36341afad18fd44fddec3ef80da5315adaf5fb63391815; complete discovered native inputs: EmailEvents, EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/63/content/items/7/content/query", + "querySha256": "5014049df6a062e39d058ec8a8dd718242035db12af272e5181956a41da6fadd", + "tables": [ + "AlertEvidence", + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/63/content/items/7/content/query SHA256 5014049df6a062e39d058ec8a8dd718242035db12af272e5181956a41da6fadd; complete discovered native inputs: AlertEvidence, EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/63/content/items/8/content/query", + "querySha256": "0226dd4221a3b939b75d850f4478883a00977f3e7d87c446a924b2cfb3ceded0", + "tables": [ + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/63/content/items/8/content/query SHA256 0226dd4221a3b939b75d850f4478883a00977f3e7d87c446a924b2cfb3ceded0; complete discovered native inputs: EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/63/content/items/9/content/items/1/content/query", + "querySha256": "914013b498753b6c0292c45e127dae55a5c25f727e651e9cd6a17c5cd31f6f9c", + "tables": [ + "EmailEvents", + "EmailPostDeliveryEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/63/content/items/9/content/items/1/content/query SHA256 914013b498753b6c0292c45e127dae55a5c25f727e651e9cd6a17c5cd31f6f9c; complete discovered native inputs: EmailEvents, EmailPostDeliveryEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/64/content/items/1/content/query", + "querySha256": "aef89150f39c48e8af94fb3ed7258e8e02bf8d0af7ec1ad00cdecc1db1758fa7", + "tables": [ + "EmailEvents", + "EmailUrlInfo", + "UrlClickEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/64/content/items/1/content/query SHA256 aef89150f39c48e8af94fb3ed7258e8e02bf8d0af7ec1ad00cdecc1db1758fa7; complete discovered native inputs: EmailEvents, EmailUrlInfo, UrlClickEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + }, + { + "path": "/items/64/content/items/3/content/query", + "querySha256": "0af7c322d60d2eaebbf2682473849eb391620da706669fd90fe8d98a4cd85070", + "tables": [ + "EmailEvents", + "EmailUrlInfo", + "UrlClickEvents" + ], + "decision": "accept", + "evidence": "User approved exact query /items/64/content/items/3/content/query SHA256 0af7c322d60d2eaebbf2682473849eb391620da706669fd90fe8d98a4cd85070; complete discovered native inputs: EmailEvents, EmailUrlInfo, UrlClickEvents. Preserve existing Advanced Hunting KQL; no Sentinel connector or workspace function prerequisite. Runtime visibility and parity not verified.", + "blockers": [] + } + ] + }, + "requiredWorkloads": [ + { + "workload": "mda", + "dataTypes": [ + "CloudAppEvents" + ] + }, + { + "workload": "mdo", + "dataTypes": [ + "EmailEvents", + "EmailPostDeliveryEvents", + "EmailUrlInfo", + "FileMaliciousContentInfo", + "MessageEvents", + "MessagePostDeliveryEvents", + "MessageUrlInfo", + "UrlClickEvents" + ] + }, + { + "workload": "mtp", + "dataTypes": [ + "AlertEvidence" + ] + } + ], + "requiredDataConnectors": [], + "dependencyReviewRequired": false + } +} From 0021ebea04b49521467f61872cf99681b28460d0 Mon Sep 17 00:00:00 2001 From: kingwil <5839248+kingwil@users.noreply.github.com> Date: Thu, 15 Oct 2026 09:34:04 +0100 Subject: [PATCH 5/6] Remove redundant native O365 workbook source copy Validate the reviewed canonical Notebook and query inventory directly from the native XDR artifact. Preserve historical import provenance and all stable identities; no separate source file or Sentinel parent is required. Rebuilt with corrected V3.1 tooling; deployed package JSON is unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- ...nderForOffice365DetectionsAndInsights.json | 14895 ---------------- ...nderForOffice365DetectionsAndInsights.json | 2 + 2 files changed, 2 insertions(+), 14895 deletions(-) delete mode 100644 Solutions/Microsoft Defender for Office 365/Workbook Sources/Native/MicrosoftDefenderForOffice365DetectionsAndInsights.json diff --git a/Solutions/Microsoft Defender for Office 365/Workbook Sources/Native/MicrosoftDefenderForOffice365DetectionsAndInsights.json b/Solutions/Microsoft Defender for Office 365/Workbook Sources/Native/MicrosoftDefenderForOffice365DetectionsAndInsights.json deleted file mode 100644 index b9f238cd60c..00000000000 --- a/Solutions/Microsoft Defender for Office 365/Workbook Sources/Native/MicrosoftDefenderForOffice365DetectionsAndInsights.json +++ /dev/null @@ -1,14895 +0,0 @@ -{ - "version": "Notebook/1.0", - "items": [ - { - "type": 1, - "content": { - "json": "# Microsoft Defender for Office 365 Detections and Insights\n\nThis workbook provides email and collaboration security insights directly in Microsoft Defender using Advanced Hunting. It is designed for customers using workspace-less Workbooks in the Integrated Security Operations Center (ISOC) and does not require Microsoft Sentinel or a Log Analytics workspace.\n\n[Learn about Integrated Security Operations Center in Microsoft Defender](https://techcommunity.microsoft.com/blog/microsoftthreatprotectionblog/integrated-security-operations-center-in-microsoft-defender/4559097)\n\n- The time selector is bounded by the Defender data available to this tenant.\n- The default range is 7 days and the maximum selectable range is 90 days.\n- Subscription, workspace, cross-workspace, and MSSP selectors are not available in the workspace-less experience.\n- Incident visuals that depend on Microsoft Sentinel tables show an explicit ISOC workspace-required notice." - }, - "name": "text - 2", - "id": "d2b45ab8-a1c1-43d2-853d-290640bf4c94" - }, - { - "type": 9, - "content": { - "version": "KqlParameterItem/1.0", - "parameters": [ - { - "id": "2e238f92-709c-410b-93e0-60eab6150a75", - "version": "KqlParameterItem/1.0", - "name": "TimeRange", - "type": 4, - "isRequired": true, - "isGlobal": true, - "typeSettings": { - "selectableValues": [ - { - "durationMs": 3600000 - }, - { - "durationMs": 14400000 - }, - { - "durationMs": 43200000 - }, - { - "durationMs": 86400000 - }, - { - "durationMs": 172800000 - }, - { - "durationMs": 259200000 - }, - { - "durationMs": 604800000 - }, - { - "durationMs": 1209600000 - }, - { - "durationMs": 2592000000 - }, - { - "durationMs": 5184000000 - }, - { - "durationMs": 7776000000 - } - ], - "allowCustom": true - }, - "timeContext": { - "durationMs": 86400000 - }, - "value": { - "durationMs": 604800000 - }, - "key": "2e238f92-709c-410b-93e0-60eab6150a75" - }, - { - "id": "165f2f4a-e49f-4561-adc5-d0527a4caf32", - "version": "KqlParameterItem/1.0", - "name": "Granularity", - "label": "Trend interval", - "type": 2, - "isRequired": true, - "typeSettings": { - "additionalResourceOptions": [], - "showDefault": false - }, - "jsonData": "[{\"value\":\"1d\",\"label\":\"Daily (1d)\",\"selected\":true},{\"value\":\"7d\",\"label\":\"Weekly (7d)\",\"selected\":false},{\"value\":\"30d\",\"label\":\"Monthly (30d)\",\"selected\":false},{\"value\":\"90d\",\"label\":\"Quarterly (90d)\",\"selected\":false}]", - "timeContext": { - "durationMs": 86400000 - }, - "value": "1d" - } - ], - "style": "pills" - }, - "name": "parameters - 1", - "id": "0021e733-42b4-461f-8f6c-14e6e765389d" - }, - { - "type": 11, - "content": { - "version": "LinkItem/1.0", - "style": "tabs", - "links": [ - { - "id": "3d26d949-bba8-486c-9af7-2b85bd5c8ab0", - "cellValue": "Tab", - "linkTarget": "parameter", - "linkLabel": "Executive Summary", - "subTarget": "1", - "style": "link", - "key": "3d26d949-bba8-486c-9af7-2b85bd5c8ab0" - }, - { - "id": "a5f95467-84c1-4d8b-858c-7819339af748", - "cellValue": "Tab", - "linkTarget": "parameter", - "linkLabel": "Email - Malware", - "subTarget": "2", - "style": "link", - "key": "a5f95467-84c1-4d8b-858c-7819339af748" - }, - { - "id": "b6c93de8-16d9-4c90-999b-837935de5645", - "cellValue": "Tab", - "linkTarget": "parameter", - "linkLabel": "Email - Phish", - "subTarget": "3", - "style": "link", - "key": "b6c93de8-16d9-4c90-999b-837935de5645" - }, - { - "id": "9e006e81-4fd4-40b9-9d20-3705dd6c17ad", - "cellValue": "Tab", - "linkTarget": "parameter", - "linkLabel": "Email - Impersonation & BEC", - "subTarget": "15", - "style": "link", - "key": "75f1e28f-e95a-4810-af40-6b47b35cda46" - }, - { - "id": "df2c53b4-b6ed-4151-95fb-b3f08b849b84", - "cellValue": "Tab", - "linkTarget": "parameter", - "linkLabel": "Email - Spam", - "subTarget": "4", - "style": "link", - "key": "df2c53b4-b6ed-4151-95fb-b3f08b849b84" - }, - { - "id": "fd2006c9-39b5-43ac-b05d-47309ee22deb", - "cellValue": "Tab", - "linkTarget": "parameter", - "linkLabel": "Teams & Collaboration", - "subTarget": "14", - "style": "link", - "key": "fd2006c9-39b5-43ac-b05d-47309ee22deb" - }, - { - "id": "ee01f95a-c5f7-4864-82e8-54a164741ba2", - "cellValue": "Tab", - "linkTarget": "parameter", - "linkLabel": "File - Malware (SharePoint, Teams and OneDrive)", - "subTarget": "9", - "style": "link", - "key": "ee01f95a-c5f7-4864-82e8-54a164741ba2" - }, - { - "id": "9df30067-3266-48a8-b9e3-d65952098d46", - "cellValue": "Tab", - "linkTarget": "parameter", - "linkLabel": "URL & Clicks", - "subTarget": "5", - "style": "link", - "key": "9df30067-3266-48a8-b9e3-d65952098d46" - }, - { - "id": "b4be0ac3-3f48-44a8-b4b6-b46e17c710cd", - "cellValue": "Tab", - "linkTarget": "parameter", - "linkLabel": "Top Users & Exfiltration", - "subTarget": "6", - "style": "link", - "key": "b4be0ac3-3f48-44a8-b4b6-b46e17c710cd" - }, - { - "id": "e1d34091-7b3c-4e2d-a032-8be82a989313", - "cellValue": "Tab", - "linkTarget": "parameter", - "linkLabel": "Email - Detection Overrides", - "subTarget": "7", - "style": "link", - "key": "e1d34091-7b3c-4e2d-a032-8be82a989313" - }, - { - "id": "a1e6264d-8f85-4a94-9ffd-eee36c04a0d5", - "cellValue": "Tab", - "linkTarget": "parameter", - "linkLabel": "Post-Delivery & Quarantine", - "subTarget": "11", - "style": "link", - "key": "a1e6264d-8f85-4a94-9ffd-eee36c04a0d5" - }, - { - "id": "08c43a4f-f502-4813-9b8d-3f6b0b62b2fd", - "cellValue": "Tab", - "linkTarget": "parameter", - "linkLabel": "False Negative(FN) Submissions", - "subTarget": "8", - "style": "link", - "key": "08c43a4f-f502-4813-9b8d-3f6b0b62b2fd" - }, - { - "id": "638d931f-f319-4914-b72d-8d68e914c7d4", - "cellValue": "Tab", - "linkTarget": "parameter", - "linkLabel": "False Positive(FP) Submissions", - "subTarget": "10", - "style": "link", - "key": "638d931f-f319-4914-b72d-8d68e914c7d4" - }, - { - "id": "b2920bee-c32a-4fdd-9d32-b004db2f3ac8", - "cellValue": "Tab", - "linkTarget": "parameter", - "linkLabel": "Security Operations Center (SOC) Insights", - "subTarget": "13", - "style": "link", - "key": "b2920bee-c32a-4fdd-9d32-b004db2f3ac8" - } - ] - }, - "name": "links - 14", - "id": "5c9a1d6b-c248-432b-a1c0-496337635775" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Defender for Office 365 - Protection Insights\r\n
\r\n\r\n**Microsoft Defender for Office 365** is a comprehensive security solution designed to protect organizations from advanced threats targeting their email and collaboration tools. It leverages a multi-layered approach to safeguard against phishing, malware, business email compromise (BEC), and other sophisticated attacks.\r\n" - }, - "name": "text - 13", - "styleSettings": { - "margin": "0", - "padding": "0" - }, - "id": "46119f93-fad9-413c-8e10-7615c6fdde2f" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query shows the number behind the effectiveness of phish and malware false positives including post delivery events but without edge data detections.\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\n\r\n// Get all mailflow detected as clean at time of delivery \r\nlet EmailEventsClean = materialize( \r\n EmailEvents \r\n | where Timestamp between (toscalar(minTime) .. toscalar(maxTime)) and EmailDirection == \"Inbound\" \r\n // | where ThreatTypes !contains \"Phish\" and ThreatTypes !contains \"Malware\" // Streaming-SIEM branch disabled for Advanced Hunting current-state semantics.\r\n // this alteration is due to the threat types being updated directly within advanced hunting.\r\n | where DeliveryLocation != \"Quarantine\" // Advanced Hunting current-state branch.\r\n | project NetworkMessageId,ThreatTypes \r\n); \r\n// Get all mailflow detected as phish or malware at time of delivery \r\nlet EmailEventsThreats = materialize( \r\n EmailEvents \r\n | where Timestamp between (toscalar(minTime) .. toscalar(maxTime)) and EmailDirection == \"Inbound\" \r\n | where ThreatTypes contains \"Phish\" or ThreatTypes contains \"Malware\" \r\n | extend MDO_detection = parse_json(DetectionMethods) \r\n | extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n | extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n | project NetworkMessageId,FirstDetection,FirstSubcategory,MDO_detection,ThreatTypes \r\n); \r\n// Get all post delivery ZAP / Redelivery events, and arg_max them to ensure we have the latest verdict to work with for each \r\nlet EmailPostDeliveryFiltered = materialize( \r\n EmailPostDeliveryEvents \r\n | where Timestamp between (toscalar(minTime) .. datetime_add('day', 7, toscalar(maxTime))) \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") or Action has_any (\"Redelivery\",\"Reprocessed\") \r\n | extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n | summarize arg_max(Timestamp, *) by Key \r\n | project Action,ActionType,ActionResult,ThreatTypes,NetworkMessageId \r\n); \r\n// Optional - get all admin submissions for malware or phish, so we can also count these in the miss bucket. \r\nlet CloudAppEventsFiltered = materialize( \r\n CloudAppEvents \r\n | where Timestamp between (toscalar(minTime) .. datetime_add('day', 7, toscalar(maxTime)))\r\n | where ActionType == \"AdminSubmissionSubmitted\" \r\n | extend SubmissionType = tostring(parse_json(RawEventData).SubmissionType) \r\n | extend NetworkMessageId = tostring(parse_json(RawEventData).ObjectId) \r\n | where SubmissionType in (\"1\", \"2\") \r\n | project SubmissionType,NetworkMessageId \r\n); \r\n// get the number of threats caught in mailflow \r\nlet Mal_Phish_Mailflow = toscalar( \r\n EmailEventsThreats \r\n | summarize count() \r\n); \r\n// get the number of threats caught in mailflow which turned out to be false positives (FPs) so we can correct the calculation \r\nlet FP_ZAP = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ThreatTypes !contains \"Phish\" and ThreatTypes !contains \"Malware\" and Action has_any (\"Redelivery\",\"Reprocessed\") \r\n | join kind=leftsemi (EmailEventsThreats) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// get the number of threats successfully cleaned up post delivery, ignoring where administrative policy stopped action \r\nlet FN_ZAP_Successful = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") and ActionResult in (\"Success\",\"AdminPolicy\") \r\n | join kind=leftsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// get the number of threats unsuccessfully cleaned up post delivery. \r\nlet FN_ZAP_Unsuccessful = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") and ActionResult !in (\"Success\",\"AdminPolicy\") \r\n | join kind=leftsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// join the administrative submissions to clean mailflow to find the additional miss \r\nlet FN_Admin_Submissions = toscalar( \r\n CloudAppEventsFiltered \r\n | join kind=rightsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n ); \r\n // print each result, and run the calculation to work out effectiveness at time of delivery and post delivery. \r\n\r\nprint StatisticName=\"Effectiveness Post Delivery\", Value=abs(round(((toreal(toscalar(FN_Admin_Submissions))+toreal(toscalar(FN_ZAP_Unsuccessful)))/(toreal(toscalar(Mal_Phish_Mailflow))+toreal(toscalar(FN_ZAP_Successful))+toreal(toscalar(FN_ZAP_Unsuccessful))+toreal(toscalar(FN_Admin_Submissions))-toreal(toscalar(FP_ZAP)))*100-100),2))", - "size": 1, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "stat", - "tileSettings": { - "showBorder": false, - "titleContent": { - "columnMatch": "StatisticName", - "formatter": 1 - }, - "leftContent": { - "columnMatch": "Value", - "formatter": 12, - "formatOptions": { - "palette": "auto" - }, - "numberFormat": { - "unit": 17, - "options": { - "maximumSignificantDigits": 3, - "maximumFractionDigits": 2 - } - } - } - }, - "graphSettings": { - "type": 0, - "topContent": { - "columnMatch": "StatisticName", - "formatter": 1 - }, - "centerContent": { - "columnMatch": "Value", - "formatter": 1, - "numberFormat": { - "unit": 17, - "options": { - "maximumSignificantDigits": 3, - "maximumFractionDigits": 2 - } - } - } - }, - "statSettings": { - "valueField": "Value", - "valueAggregation": "None", - "colorSettings": { - "type": "thresholds", - "mode": "foreground", - "heatmapPalette": "greenRed", - "thresholdsGrid": [ - { - "operator": ">", - "thresholdValue": "95", - "representation": "green" - }, - { - "operator": "<=", - "thresholdValue": "95", - "representation": "orange" - }, - { - "operator": "<=", - "thresholdValue": "90", - "representation": "red" - } - ] - }, - "iconSettings": { - "thresholdsGrid": [] - }, - "numberFormatSettings": { - "unit": 1, - "options": { - "style": "decimal" - } - }, - "tagText": "Phish / Malware Effectiveness - Post Delivery", - "valueFontStyle": "superLarge", - "tagTextPosition": "bottom" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 5", - "id": "62de2a91-a809-48ec-a111-e697d556b2b3" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the percentage of emails released from quarantine out of the total ammount of quarantined emails\r\nlet Quarantine_Releases = toscalar(EmailPostDeliveryEvents\r\n| where Action == \"Quarantine release\"\r\n| join kind=leftouter (EmailEvents | where DeliveryLocation == \"Quarantine\") on NetworkMessageId\r\n| summarize count());\r\nlet Quarantined_Mailflow = toscalar(EmailEvents | where DeliveryLocation == \"Quarantine\"\r\n| summarize count());\r\nprint\r\nQuarantine_Releases = toreal(Quarantine_Releases),\r\nQuarantined_Mailflow = toreal(Quarantined_Mailflow),\r\nRelease_Percentage = abs(round(((toreal(Quarantine_Releases)/toreal(Quarantined_Mailflow))*100),2))", - "size": 1, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "stat", - "tileSettings": { - "titleContent": { - "columnMatch": "Release_Percentage", - "formatter": 12, - "formatOptions": { - "palette": "none" - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - }, - "showBorder": true, - "sortCriteriaField": "Release_Percentage", - "size": "auto" - }, - "graphSettings": { - "type": 0, - "topContent": { - "columnMatch": "StatisticName", - "formatter": 1 - }, - "centerContent": { - "columnMatch": "Value", - "formatter": 1, - "numberFormat": { - "unit": 17, - "options": { - "maximumSignificantDigits": 3, - "maximumFractionDigits": 2 - } - } - } - }, - "statSettings": { - "valueField": "Release_Percentage", - "valueAggregation": "None", - "colorSettings": { - "type": "thresholds", - "mode": "foreground", - "heatmapPalette": "greenRed", - "thresholdsGrid": [ - { - "operator": "<", - "thresholdValue": "5", - "representation": "green" - }, - { - "operator": ">", - "thresholdValue": "5", - "representation": "redDark" - } - ] - }, - "iconSettings": { - "thresholdsGrid": [] - }, - "numberFormatSettings": { - "unit": 1, - "options": { - "style": "decimal" - } - }, - "tagText": "Quarantine Release Percentage", - "valueFontStyle": "superLarge", - "tagTextPosition": "bottom" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 1", - "id": "858ac1a4-8828-45e9-968c-d3cfc1216c64" - } - ] - }, - "name": "TopNr", - "id": "1369c97e-848b-475a-b447-3a435cb7a1f1" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "**Effectiveness visually represents the protection given by Defender for Office 365 against phishing and malware in email messages.**
\r\nWe consider messages that your users report, as well as decisions that are made after delivery." - }, - "name": "text - 9", - "styleSettings": { - "margin": "1px" - }, - "id": "25e2e19e-aefb-4e37-b28f-b4138d63e109" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query shows the number behind the effectiveness of phish and malware false positives including post delivery events but without edge data detections.\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\n\r\n// Get all mailflow detected as clean at time of delivery \r\nlet EmailEventsClean = materialize( \r\n EmailEvents \r\n | where Timestamp between (toscalar(minTime) .. toscalar(maxTime)) and EmailDirection == \"Inbound\" \r\n // | where ThreatTypes !contains \"Phish\" and ThreatTypes !contains \"Malware\" // Streaming-SIEM branch disabled for Advanced Hunting current-state semantics.\r\n // this alteration is due to the threat types being updated directly within advanced hunting.\r\n | where DeliveryLocation != \"Quarantine\" // Advanced Hunting current-state branch.\r\n | project NetworkMessageId,ThreatTypes \r\n); \r\n// Get all mailflow detected as phish or malware at time of delivery \r\nlet EmailEventsThreats = materialize( \r\n EmailEvents \r\n | where Timestamp between (toscalar(minTime) .. toscalar(maxTime)) and EmailDirection == \"Inbound\" \r\n | where ThreatTypes contains \"Phish\" or ThreatTypes contains \"Malware\" \r\n | extend MDO_detection = parse_json(DetectionMethods) \r\n | extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n | extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n | project NetworkMessageId,FirstDetection,FirstSubcategory,MDO_detection,ThreatTypes \r\n); \r\n// Get all post delivery ZAP / Redelivery events, and arg_max them to ensure we have the latest verdict to work with for each \r\nlet EmailPostDeliveryFiltered = materialize( \r\n EmailPostDeliveryEvents \r\n | where Timestamp between (toscalar(minTime) .. datetime_add('day', 7, toscalar(maxTime))) \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") or Action has_any (\"Redelivery\",\"Reprocessed\") \r\n | extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n | summarize arg_max(Timestamp, *) by Key \r\n | project Action,ActionType,ActionResult,ThreatTypes,NetworkMessageId \r\n); \r\n// Optional - get all admin submissions for malware or phish, so we can also count these in the miss bucket. \r\nlet CloudAppEventsFiltered = materialize( \r\n CloudAppEvents \r\n | where Timestamp between (toscalar(minTime) .. datetime_add('day', 7, toscalar(maxTime)))\r\n | where ActionType == \"AdminSubmissionSubmitted\" \r\n | extend SubmissionType = tostring(parse_json(RawEventData).SubmissionType) \r\n | extend NetworkMessageId = tostring(parse_json(RawEventData).ObjectId) \r\n | where SubmissionType in (\"1\", \"2\") \r\n | project SubmissionType,NetworkMessageId \r\n); \r\n// get the number of threats caught in mailflow \r\nlet Mal_Phish_Mailflow = toscalar( \r\n EmailEventsThreats \r\n | summarize count() \r\n); \r\n// get the number of threats caught in mailflow which turned out to be false positives (FPs) so we can correct the calculation \r\nlet FP_ZAP = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ThreatTypes !contains \"Phish\" and ThreatTypes !contains \"Malware\" and Action has_any (\"Redelivery\",\"Reprocessed\") \r\n | join kind=leftsemi (EmailEventsThreats) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// get the number of threats successfully cleaned up post delivery, ignoring where administrative policy stopped action \r\nlet FN_ZAP_Successful = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") and ActionResult in (\"Success\",\"AdminPolicy\") \r\n | join kind=leftsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// get the number of threats unsuccessfully cleaned up post delivery. \r\nlet FN_ZAP_Unsuccessful = toscalar( \r\n EmailPostDeliveryFiltered \r\n | where ActionType in (\"Malware ZAP\",\"Phish ZAP\") and ActionResult !in (\"Success\",\"AdminPolicy\") \r\n | join kind=leftsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n); \r\n// join the administrative submissions to clean mailflow to find the additional miss \r\nlet FN_Admin_Submissions = toscalar( \r\n CloudAppEventsFiltered \r\n | join kind=rightsemi (EmailEventsClean) on NetworkMessageId \r\n | summarize count() \r\n ); \r\n // print each result, and run the calculation to work out effectiveness at time of delivery and post delivery. \r\nunion withsource=Table \r\n (print StatisticName=\"Mal/Phish Mailflow totals - Minus FPs\", Value=toreal(Mal_Phish_Mailflow) - toreal(FP_ZAP)), \r\n (print StatisticName=\"Admin Mal/Phish FNs Submitted\", Value=toreal(FN_Admin_Submissions)), \r\n (print StatisticName=\"Mal/Phish FPs Reverse Zapped\", Value=toreal(FP_ZAP)), \r\n (print StatisticName=\"Mal / Phish Successfully Zapped\", Value=toreal(FN_ZAP_Successful)), \r\n (print StatisticName=\"Mal / Phish UN-Successfully Zapped\", Value=toreal(FN_ZAP_Unsuccessful)), \r\n (print StatisticName=\"Effectiveness Post Delivery (%)\", Value=abs(round(((toreal(FN_Admin_Submissions)+toreal(FN_ZAP_Unsuccessful))/(toreal(Mal_Phish_Mailflow)+toreal(FN_ZAP_Successful)+toreal(FN_ZAP_Unsuccessful)+toreal(FN_Admin_Submissions)-toreal(FP_ZAP))*100-100),2))), \r\n (print StatisticName=\"Effectiveness Pre-Delivery (%)\", Value=abs(round(((toreal(FN_Admin_Submissions)+toreal(FN_ZAP_Unsuccessful)+toreal(FN_ZAP_Successful))/(toreal(Mal_Phish_Mailflow)+toreal(FN_ZAP_Successful)+toreal(FN_ZAP_Unsuccessful)+toreal(FN_Admin_Submissions)-toreal(FP_ZAP))*100-100),2))) \r\n| project StatisticName, Value", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Value", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ] - }, - "tileSettings": { - "showBorder": false, - "titleContent": { - "columnMatch": "StatisticName", - "formatter": 1 - }, - "leftContent": { - "columnMatch": "Value", - "formatter": 12, - "formatOptions": { - "palette": "auto" - }, - "numberFormat": { - "unit": 17, - "options": { - "maximumSignificantDigits": 3, - "maximumFractionDigits": 2 - } - } - } - }, - "graphSettings": { - "type": 2, - "topContent": { - "columnMatch": "StatisticName", - "formatter": 1 - }, - "centerContent": { - "columnMatch": "Value", - "formatter": 1, - "numberFormat": { - "unit": 17, - "options": { - "maximumSignificantDigits": 3, - "maximumFractionDigits": 2 - } - } - }, - "nodeIdField": "StatisticName", - "sourceIdField": "Value", - "targetIdField": "Value", - "graphOrientation": 3, - "showOrientationToggles": false, - "nodeSize": null, - "staticNodeSize": 100, - "colorSettings": null, - "hivesMargin": 5, - "edgeColorSettings": null - }, - "timeContext": { - "durationMs": 0 - } - }, - "name": "query - 7", - "id": "9e09ff94-8092-49c7-860f-341049e1398c" - } - ] - }, - "customWidth": "50", - "name": "Effectiveness Nr", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "31081a73-9a54-4668-9e26-ad7347f1e06e" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "**Quarantine release rate by detection technology.** \r\n
\r\nFor each detector, the share of its quarantined mail that was later released (Release % = released / quarantined). A high rate can indicate false positives worth reviewing." - }, - "name": "text - 1", - "styleSettings": { - "margin": "1px" - }, - "id": "e9848043-03dd-4ada-9e73-238067463f74" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Per detection technology: the share of its quarantined emails later released from quarantine (a high rate can indicate false positives). Top 7 by release rate; detectors with <10 quarantined excluded so the rate is meaningful.\r\nEmailEvents\r\n| where DeliveryLocation == \"Quarantine\"\r\n| extend MDO_detection = parse_json(DetectionMethods)\r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0]))\r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\")\r\n| where FirstSubcategory contains \"Malware\" or FirstSubcategory contains \"Phish\"\r\n| join kind=leftouter (\r\n EmailPostDeliveryEvents\r\n | where Action == \"Quarantine release\"\r\n | distinct NetworkMessageId\r\n | extend ReleasedFlag = \"yes\"\r\n ) on NetworkMessageId\r\n| summarize Quarantined = dcount(NetworkMessageId), Released = dcountif(NetworkMessageId, ReleasedFlag == \"yes\") by FirstSubcategory\r\n| where Quarantined >= 10 and Released > 0\r\n| extend ReleaseRate = round(Released * 100.0 / Quarantined, 2)\r\n| project ['Detection Technology']=FirstSubcategory, ['Quarantined Emails']=Quarantined, ['Released']=Released, ['Release %']=ReleaseRate\r\n| order by ['Release %'] desc\r\n| take 7", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Quarantined Emails", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Released", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "90px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Release %", - "formatter": 4, - "formatOptions": { - "palette": "red", - "min": 0, - "max": 20, - "customColumnWidthSetting": "90px" - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "name": "query - 2", - "id": "1bbae9d1-d6f8-446a-817c-8fdc2df83d4c" - } - ] - }, - "customWidth": "50", - "name": "Quarantine Overview Relese", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "36fd8f20-ece7-4889-9fb1-f5b85b97b45a" - } - ] - }, - "customWidth": "100", - "name": "group - Exec Protection Insights", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "1d8e22e0-22f7-453e-aed2-9e56ace1363a" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Protection details\r\n
\r\n\r\nThis Overview provides an executive summary of your Microsoft Defender for Office 365 email security posture: the volume of mail processed, threats detected and filtered (phishing, malware, spam), overall protection effectiveness, and the mix of threats targeting your organization. Use it as a starting point, then drill into the dedicated tabs for detailed investigation." - }, - "name": "text - 13", - "id": "24cf577c-e12a-4747-95a7-1c19bee17397" - }, - { - "type": 9, - "content": { - "version": "KqlParameterItem/1.0", - "parameters": [ - { - "id": "5c0f0101-0a11-4b22-9c33-000000000101", - "version": "KqlParameterItem/1.0", - "name": "ProtectionView", - "label": "Protection view", - "type": 2, - "isRequired": true, - "typeSettings": { - "additionalResourceOptions": [], - "showDefault": false - }, - "jsonData": "[{ \"value\": \"Table\", \"label\": \"Summary table\", \"selected\": true }, { \"value\": \"Tiles\", \"label\": \"Detailed tiles\" }]", - "value": "Tiles" - } - ], - "style": "pills" - }, - "name": "Protection view selector", - "id": "5c0f0102-0a11-4b22-9c33-000000000102" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "let base = materialize(EmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| summarize arg_max(Timestamp, ThreatTypes, DeliveryAction, OrgLevelPolicy, OrgLevelAction, UserLevelAction) by Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress));\r\nlet agg = materialize(base | summarize\r\n Total = count(),\r\n Filtered = countif(isnotempty(ThreatTypes) and DeliveryAction != \"Delivered\" and OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")),\r\n FMal = countif(ThreatTypes has \"Malware\" and OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")),\r\n FPhish = countif(ThreatTypes has \"Phish\" and not(ThreatTypes has \"Malware\") and DeliveryAction != \"Delivered\" and OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")),\r\n FSpam = countif(ThreatTypes == \"Spam\" and DeliveryAction != \"Delivered\" and OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")),\r\n Deliv = countif(isnotempty(ThreatTypes) and DeliveryAction == \"Delivered\" and (isnotempty(OrgLevelAction) or isnotempty(UserLevelAction))),\r\n Blocked = countif(isempty(ThreatTypes) and DeliveryAction != \"Delivered\" and (isnotempty(OrgLevelAction) or isnotempty(UserLevelAction))),\r\n Clean = countif(isempty(ThreatTypes) and DeliveryAction == \"Delivered\"));\r\nlet pd = materialize(EmailPostDeliveryEvents | where ActionResult == \"Success\" | summarize MalZap = countif(ActionType == \"Malware ZAP\"), PhishZap = countif(ActionType == \"Phish ZAP\"), SpamZap = countif(ActionType == \"Spam ZAP\"));\r\nlet sub = materialize(CloudAppEvents | extend R = tostring(parse_json(RawEventData).RecordType), SCT = tostring(parse_json(RawEventData).SubmissionContentType) | where R == \"29\" | summarize Adm = countif(ActionType == \"AdminSubmissionSubmitted\" and SCT == \"Mail\"), Usr = countif(ActionType == \"UserSubmission\"));\r\nlet Total = toscalar(agg | project Total);\r\nlet Filtered = toscalar(agg | project Filtered);\r\nlet FMal = toscalar(agg | project FMal);\r\nlet FPhish = toscalar(agg | project FPhish);\r\nlet FSpam = toscalar(agg | project FSpam);\r\nlet Deliv = toscalar(agg | project Deliv);\r\nlet Blocked = toscalar(agg | project Blocked);\r\nlet Clean = toscalar(agg | project Clean);\r\nlet MalZap = toscalar(pd | project MalZap);\r\nlet PhishZap = toscalar(pd | project PhishZap);\r\nlet SpamZap = toscalar(pd | project SpamZap);\r\nlet Adm = toscalar(sub | project Adm);\r\nlet Usr = toscalar(sub | project Usr);\r\nunion\r\n (print o = 1, Name = \"Total Inbound Emails\", Count = Total),\r\n (print o = 2, Name = \"    Filtering Totals\", Count = Filtered),\r\n (print o = 3, Name = \"        Filtered as Malware\", Count = FMal),\r\n (print o = 4, Name = \"        Filtered as Phish\", Count = FPhish),\r\n (print o = 5, Name = \"        Filtered as Spam\", Count = FSpam),\r\n (print o = 6, Name = \"    Delivered with Detection\", Count = Deliv),\r\n (print o = 7, Name = \"    User/Admin Blocked\", Count = Blocked),\r\n (print o = 8, Name = \"    Clean Emails\", Count = Clean),\r\n (print o = 9, Name = \"Post-Delivery ZAP Removals\", Count = MalZap + PhishZap + SpamZap),\r\n (print o = 10, Name = \"    Removed by Malware ZAP\", Count = MalZap),\r\n (print o = 11, Name = \"    Removed by Phish ZAP\", Count = PhishZap),\r\n (print o = 12, Name = \"    Removed by Spam ZAP\", Count = SpamZap),\r\n (print o = 13, Name = \"User/Admin Reported\", Count = Adm + Usr),\r\n (print o = 14, Name = \"    Reported by Admins\", Count = Adm),\r\n (print o = 15, Name = \"    Reported by Users\", Count = Usr)\r\n| sort by o asc\r\n| extend [\"% of Inbound\"] = round(Count * 100.0 / Total, 1)\r\n| project Name, Count, [\"% of Inbound\"]", - "size": 3, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Name", - "formatter": 1, - "formatOptions": { - "customColumnWidthSetting": "3fr" - } - }, - { - "columnMatch": "Count", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "3fr" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "% of Inbound", - "formatter": 3, - "formatOptions": { - "palette": "green", - "min": 0, - "max": 100, - "customColumnWidthSetting": "2fr" - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "conditionalVisibility": { - "parameterName": "ProtectionView", - "comparison": "isEqualTo", - "value": "Table" - }, - "name": "query - option 1 grid", - "id": "5c0f0005-0a11-4b22-9c33-000000000005" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "title": "Total Emails", - "items": [ - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "EmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| summarize Count = count()\r\n| extend Details = \"Total Inbound Emails\";", - "size": 3, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Count", - "formatter": 4, - "formatOptions": { - "palette": "greenRed" - } - } - ] - }, - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1, - "formatOptions": { - "compositeBarSettings": { - "labelText": "" - } - } - }, - "secondaryContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 1, - "palette": "blue", - "compositeBarSettings": { - "labelText": "" - } - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "showBorder": true, - "size": "full", - "styleSettings": { - "borderStyle": "rounded", - "backgroundColor": "colorGray100" - } - }, - "chartSettings": { - "xAxis": "Count", - "createOtherGroup": 0 - }, - "mapSettings": { - "locInfo": "LatLong", - "sizeSettings": "Count", - "sizeAggregation": "Sum", - "legendMetric": "Count", - "legendAggregation": "Sum", - "itemColorSettings": { - "type": "heatmap", - "colorAggregation": "Sum", - "nodeColorField": "Count", - "heatmapPalette": "greenRed" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "name": "query - 1", - "id": "84e8d60b-7937-46f5-b2f4-a1a4adf06c9f" - } - ] - }, - "name": "Total Inbound", - "id": "1aeed046-9ea5-4583-b966-722847997fc7" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "title": "Filtering Totals", - "items": [ - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "EmailEvents\r\n| where isnotempty(ThreatTypes) and EmailDirection == \"Inbound\" and DeliveryAction != 'Delivered'\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| summarize Count = count()\r\n| extend Details = \"Filtering Totals\";", - "size": 3, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1, - "formatOptions": { - "compositeBarSettings": { - "labelText": "" - } - } - }, - "secondaryContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 1, - "palette": "redDark", - "compositeBarSettings": { - "labelText": "" - } - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "showBorder": true, - "size": "full", - "styleSettings": { - "borderStyle": "rounded", - "backgroundColor": "colorGray100" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "name": "query - 1", - "id": "bae9a200-589f-4ca6-a3cf-f1110f644c49" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises Total emails detected as Malware\r\nEmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| where ThreatTypes has ('Malware') and EmailDirection == \"Inbound\"\r\n| summarize Count= count()\r\n| extend Details = \"Emails Filtered as Malware\"", - "size": 3, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "secondaryContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 1, - "palette": "red" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "showBorder": true, - "size": "full", - "styleSettings": { - "borderStyle": "rounded", - "backgroundColor": "colorGray100" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "33.3", - "name": "query - 4", - "id": "0984d05b-fd2c-48e1-835f-41afc5a2385a" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises Total emails detected as Phish\r\nEmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| where ThreatTypes has \"Phish\" and not(ThreatTypes has \"Malware\") and EmailDirection == \"Inbound\" and DeliveryAction != 'Delivered'\r\n| summarize Count= count()\r\n| extend Details = \"Emails Filtered as Phish\"", - "size": 3, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "secondaryContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 1, - "palette": "orange" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "showBorder": true, - "size": "full", - "styleSettings": { - "borderStyle": "rounded", - "backgroundColor": "colorGray100" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "33.3", - "name": "query - 4", - "id": "ced2d054-76d1-40df-a412-0bc86a6c3336" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises Total emails by detected as Spam\r\nEmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| where ThreatTypes == 'Spam' and EmailDirection == \"Inbound\" and DeliveryAction != 'Delivered'\r\n| summarize Count= count()\r\n| extend Details = \"Emails Filtered as Spam\"", - "size": 3, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "secondaryContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 1, - "palette": "yellow" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "showBorder": true, - "size": "full", - "styleSettings": { - "borderStyle": "rounded", - "backgroundColor": "colorGray100" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "33.3", - "name": "query - 4", - "id": "14456a0d-f5ac-46a0-a007-c72c7c40c58f" - } - ] - }, - "customWidth": "50", - "name": "group - 9", - "id": "d4e69885-f1b2-4c2b-85c2-188a6708dc4b" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "title": " ", - "items": [ - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "EmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and DeliveryAction == 'Delivered'\r\n| where isnotempty(OrgLevelAction) or isnotempty(UserLevelAction)\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| summarize Count= count()\r\n| extend Details = \"Delivered with Detection\"", - "size": 3, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "secondaryContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 0, - "palette": "red" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "showBorder": true, - "size": "full", - "styleSettings": { - "borderStyle": "rounded", - "backgroundColor": "colorGray100" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "33.3", - "name": "query - 3", - "id": "394d1ed4-7089-4291-bc80-f9948e3be6a9" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "EmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\" and isempty(ThreatTypes) \r\n| where isnotempty(OrgLevelAction) or isnotempty(UserLevelAction)\r\n| where DeliveryAction != 'Delivered'\r\n| summarize Count= count()\r\n| extend Details = \"User/Admin Blocked\"", - "size": 3, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "secondaryContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 1, - "palette": "gray" - }, - "tooltipFormat": { - "tooltip": "Emails blocked from being delivered because of User or Admin overriddes" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "showBorder": true, - "size": "full", - "styleSettings": { - "borderStyle": "rounded", - "backgroundColor": "colorGray100" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "33.3", - "name": "query - 3", - "id": "c29a2268-67d1-4958-a9a3-696384075987" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "EmailEvents\r\n| where isempty(ThreatTypes) and EmailDirection == \"Inbound\" and DeliveryAction == 'Delivered'\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key \r\n| summarize Count= count()\r\n| extend Details = \"Clean Emails\"", - "size": 3, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "secondaryContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 1, - "palette": "gray" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "showBorder": true, - "size": "full", - "styleSettings": { - "borderStyle": "rounded", - "backgroundColor": "colorGray100" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "33.3", - "name": "query - 3", - "id": "89a02ac7-971c-4672-bf5d-64709c479536" - } - ] - }, - "customWidth": "50", - "name": "group - 8", - "id": "761e74d4-279e-465f-ba47-5eeec4cf05d2" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "title": "Post-Delivery ZAP Removals", - "items": [ - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "EmailPostDeliveryEvents\r\n| where ActionResult == \"Success\"\r\n| where ActionType == \"Malware ZAP\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Removed by Malware ZAP\"\r\n", - "size": 3, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "secondaryContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 1, - "palette": "red" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "showBorder": true, - "size": "full", - "styleSettings": { - "borderStyle": "rounded", - "backgroundColor": "colorGray100" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "33.3", - "name": "query - 3", - "id": "b06666bc-6ec0-49e7-a332-77e278d2320f" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "EmailPostDeliveryEvents\r\n| where ActionResult == \"Success\"\r\n| where ActionType == \"Phish ZAP\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Removed by Phish ZAP\"", - "size": 3, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "secondaryContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 1, - "palette": "orange" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "showBorder": true, - "size": "full", - "styleSettings": { - "borderStyle": "rounded", - "backgroundColor": "colorGray100" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "33.3", - "name": "query - 3", - "id": "6fbac01b-0c42-46dc-8ca8-68e285593a45" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "EmailPostDeliveryEvents\r\n| where ActionResult == \"Success\"\r\n| where ActionType == \"Spam ZAP\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Removed by Spam ZAP\"", - "size": 3, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "secondaryContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 1, - "palette": "yellow" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "showBorder": true, - "size": "full", - "styleSettings": { - "borderStyle": "rounded", - "backgroundColor": "colorGray100" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "33.3", - "name": "query - 3", - "id": "7bd27a3b-be13-4ca0-9964-0f872f826b45" - } - ] - }, - "name": "Post Delivery", - "id": "4d20339e-5215-4edf-99d6-728cac183d16" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails reported by user and total emails reported by Admins as false positive or false negative detection\r\nCloudAppEvents\r\n| extend Record= (parse_json(RawEventData)).RecordType\r\n| extend SubmissionState = (parse_json(RawEventData)).SubmissionState,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Reported by Admins\"", - "size": 3, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "secondaryContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "palette": "none" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "showBorder": true, - "size": "full", - "styleSettings": { - "borderStyle": "rounded", - "backgroundColor": "colorGray100" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 3", - "id": "7490fa3a-e287-4fc3-b025-8772b9edb601" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails reported by user and total emails reported by Admins as false positive or false negative detection\r\nCloudAppEvents\r\n| extend Record= (parse_json(RawEventData)).RecordType\r\n| extend SubmissionState = (parse_json(RawEventData)).SubmissionState\r\n| where Record == 29 and ActionType == \"UserSubmission\"\r\n| summarize Count= count()\r\n| extend Details = \"Total Emails Reported by Users\"\r\n", - "size": 3, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "secondaryContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "palette": "none" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "showBorder": true, - "size": "full", - "styleSettings": { - "borderStyle": "rounded", - "backgroundColor": "colorGray100" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 2", - "id": "7af222dc-fd74-40ec-8ab7-741e179c07bf" - } - ] - }, - "name": "Reported", - "id": "8151e242-1c30-4550-ae9c-83f159e1a456" - } - ] - }, - "conditionalVisibility": { - "parameterName": "ProtectionView", - "comparison": "isEqualTo", - "value": "Tiles" - }, - "name": "Protection - Tiles view", - "id": "5c0f0103-0a11-4b22-9c33-000000000103" - }, - { - "type": 1, - "content": { - "json": "## Most Attacked Users
\r\n\r\n**The users most targeted by inbound email threats across all threat types (malware, phishing, and spam) in the selected period. Concentrated targeting of a few individuals is a strong signal of deliberate campaigns.**

**Recommended action:** Prioritise these users for security awareness training, tighter protection policies (for example the Strict preset), and closer monitoring - they are your highest-risk people." - }, - "name": "exec vap banner", - "id": "1fe431fb-cc96-4e81-b164-3a1a3823ebeb" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query surfaces the users most targeted by inbound email threats across all threat types (malware, phishing, spam) for the selected period, so SecOps can prioritise the highest-risk individuals. Similar to a \"Most Attacked People\" view.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| where isnotempty(ThreatTypes)\r\n| summarize\r\n ['Total Threats'] = count(),\r\n Malware = countif(ThreatTypes has \"Malware\"),\r\n Phish = countif(ThreatTypes has \"Phish\"),\r\n Spam = countif(ThreatTypes has \"Spam\"),\r\n ['Last Seen'] = max(Timestamp)\r\n by ['User']=RecipientEmailAddress\r\n| top 10 by ['Total Threats']\r\n| project ['User'], ['Total Threats'], Malware, Phish, Spam, ['Last Seen']", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true, - "formatters": [ - { - "columnMatch": "Malware", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "145px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Phish", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "145px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Spam", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "145px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Total Threats", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "145px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "exec vap table", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "2dfd91b1-b8d3-4a72-aaf4-a30a1886bed7" - }, - { - "type": 1, - "content": { - "json": "## Detection trend over time - grouped by {Granularity}\r\n**Represents total emails, total detections, total user submissions and admin email submissions over time summarizing the data per {Granularity} interval**" - }, - "name": "text - 14", - "id": "ddbbdaef-b374-42a8-821c-7fcd7ee53ba9" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails, total detections, total user, and admin email submissions over time summarizing the data daily\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet scaffold = range Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran;\r\nlet baseQuery = materialize(EmailEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where isnotempty(Timestamp));\r\nlet sub = materialize(CloudAppEvents\r\n| extend Record = (parse_json(RawEventData)).RecordType, SubmissionContentType = tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29);\r\nlet zapbase = EmailPostDeliveryEvents\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ActionResult == \"Success\"\r\n| where ActionType == \"Phish ZAP\" or ActionType == \"Malware ZAP\" or ActionType == \"Spam ZAP\";\r\nunion\r\n(scaffold | join kind=leftouter (baseQuery | where EmailDirection == \"Inbound\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Inbound Emails\"),\r\n(scaffold | join kind=leftouter (baseQuery | where ThreatTypes has ('Phish') | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Emails Detected as Phish\"),\r\n(scaffold | join kind=leftouter (baseQuery | where ThreatTypes has ('Malware') | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Emails Detected as Malware\"),\r\n(scaffold | join kind=leftouter (baseQuery | where ThreatTypes has ('Spam') | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Emails Detected as Spam\"),\r\n(scaffold | join kind=leftouter (baseQuery | where EmailDirection == \"Intra-org\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Intra-org Emails\"),\r\n(scaffold | join kind=leftouter (baseQuery | where EmailDirection == \"Outbound\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Outbound Emails\"),\r\n(scaffold | join kind=leftouter (baseQuery | where isnotempty(ThreatTypes) | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Emails with Threat\"),\r\n(scaffold | join kind=leftouter (sub | where ActionType == \"UserSubmission\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Emails Reported by Users\"),\r\n(scaffold | join kind=leftouter (zapbase | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Emails Removed by ZAP\"),\r\n(scaffold | join kind=leftouter (sub | where ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType == \"Mail\" | summarize Count = count() by Timestamp = bin(Timestamp, gran)) on Timestamp | project Timestamp, Count = coalesce(Count, 0), Details = \"Total Emails Reported by Admins\")", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "chartSettings": { - "xAxis": "Timestamp", - "seriesLabelSettings": [ - { - "seriesName": "Total Inbound Emails", - "label": "Inbound Emails", - "color": "green" - }, - { - "seriesName": "Total Emails with Threat", - "label": "Emails with Threat", - "color": "redDark" - }, - { - "seriesName": "Emails Detected as Phish", - "label": "Emails with Phish", - "color": "redBright" - }, - { - "seriesName": "Emails Detected as Malware", - "label": "Emails with Malware", - "color": "red" - }, - { - "seriesName": "Total Intra-org Emails", - "label": "Intra-org Emails", - "color": "greenDark" - }, - { - "seriesName": "Emails Detected as Spam", - "label": "Emails with Spam", - "color": "gray" - }, - { - "seriesName": "Total Outbound Emails", - "label": "Outbound Emails", - "color": "greenDarkDark" - }, - { - "seriesName": "Total Emails Removed by ZAP", - "label": "Emails ZAP-d", - "color": "orangeDark" - }, - { - "seriesName": "Total Emails Reported by Users", - "label": "User Reported Emails", - "color": "lightBlue" - }, - { - "seriesName": "Total Emails Reported by Admins", - "color": "blueDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - 1", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "bcbefa48-f553-4290-acff-2691caf898ea" - }, - { - "type": 1, - "content": { - "json": "## Bad traffic (%) - Inbound Emails - grouped by {Granularity}\r\n**This represents bad traffic (% of emails with threats) compared to total inbound emails, summarized per {Granularity} interval over time.**" - }, - "name": "text - 15", - "id": "30761bcc-b1a5-45e2-8c0a-22388fbbf16c" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises bad traffic (% of emails with threats) compared to total inbound emails over time summarising the data daily.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalEmailCount = count(),\r\n BadEmailCount = countif(isnotempty(ThreatTypes)) by bin(Timestamp, {Granularity})\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(BadEmailCount / todouble(TotalEmailCount) * 100, 2))\r\n| project Timestamp, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", - "size": 0, - "aggregation": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - 4", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "508036a8-d969-44c2-b2d2-c62d99999197" - } - ] - }, - "customWidth": "100", - "name": "group - Exec Protection Details", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "e6edeeeb-dcde-41d0-88c7-97ef773403b1" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Collaboration Protection Posture\r\n
\r\n\r\nMicrosoft Defender for Office 365 protects Microsoft Teams and collaboration, not only email. This snapshot shows Teams threat activity for the period.

**Recommended action:** Review the dedicated **Teams & Collaboration** tab for impersonation, malicious URLs, risky senders and file threats in Teams." - }, - "name": "exec collab banner", - "id": "3d78a6aa-51d4-4cab-93d1-26dff86fd667" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Headline Microsoft Teams / collaboration protection metrics for the executive summary, with per-interval sparklines so the collaboration threat trend is visible at a glance. Messages and URLs are counted per distinct Teams message.\r\nlet gran = {Granularity};\r\nlet me = materialize(MessageEvents);\r\nlet cae = materialize(CloudAppEvents | where ActionType == \"TeamsImpersonationDetected\");\r\nlet mui = materialize(MessageUrlInfo);\r\nlet uce = materialize(UrlClickEvents | where Workload == \"Teams\" and ActionType in (\"ClickBlocked\",\"ClickBlockedByTenantPolicy\"));\r\nlet fmc = materialize(FileMaliciousContentInfo | where Workload == \"MicrosoftTeams\");\r\nunion\r\n(me | summarize Count = dcount(TeamsMessageId) | extend Details = \"Teams Messages Scanned\", Ord = 1, Trend = toscalar(me | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(me | where isnotempty(ThreatTypes) | summarize Count = count() | extend Details = \"Teams Threat Messages\", Ord = 2, Trend = toscalar(me | where isnotempty(ThreatTypes) | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(cae | summarize Count = count() | extend Details = \"Teams Impersonation Detections\", Ord = 3, Trend = toscalar(cae | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(mui | summarize Count = dcount(TeamsMessageId) | extend Details = \"URLs Shared in Teams\", Ord = 4, Trend = toscalar(mui | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(uce | summarize Count = count() | extend Details = \"Malicious Clicks Blocked\", Ord = 5, Trend = toscalar(uce | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(fmc | summarize Count = count() | extend Details = \"Teams Files Scanned\", Ord = 6, Trend = toscalar(fmc | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(fmc | where isnotempty(ThreatTypes) | summarize Count = count() | extend Details = \"Malicious Teams Files\", Ord = 7, Trend = toscalar(fmc | where isnotempty(ThreatTypes) | make-series S = count() default = 0 on Timestamp step gran | project S))\r\n| sort by Ord asc\r\n| project Details, Count, Trend", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "leftContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 0, - "palette": "blue" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "secondaryContent": { - "columnMatch": "Trend", - "formatter": 21 - }, - "showBorder": true, - "size": "auto" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "exec collab tiles", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "3175aee5-56d2-4cb1-b1c3-75be683e6ffb" - } - ] - }, - "customWidth": "100", - "name": "group - Exec Collaboration Posture", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "39b0921f-fcef-49f4-8d52-0dcd1f33045b" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Emerging Threats\r\n
\r\n\r\n

With more sophisticated adversaries and new threats emerging frequently and prevalently, it's critical to be able to quickly identify and react to these threats.

\r\n\r\n[

🛡️Activity Profile: Email threat landscape

](https://security.microsoft.com/threatanalytics3/f186e4b0-28df-499a-901e-c64768b6d0dc/overview?filters=tags%253DPhishing)\r\n[

🛡️Activity Profile: Automated business email impersonation campaign uses parallel aging report and payroll diversion lures

](https://security.microsoft.com/threatanalytics3/3eb53378-892d-4695-a497-25d0a54181ee)\r\n[

🛡️Tool Profile: StealC

](https://security.microsoft.com/threatanalytics3/4d837c12-1db4-49c8-8466-219198d40b9b)\r\n[

🛡️OSINT Profile: UNC1151/Ghostwriter phishing campaign targeting Gmail accounts

](https://security.microsoft.com/threatanalytics3/b1a7e5e7-4b43-4758-8805-f714a131161a)\r\n[

🛡️Activity Profile: Encrypted message campaign targets real estate/financial sectors

](https://security.microsoft.com/threatanalytics3/651d669a-4721-42ab-bb96-509e94b5bfd9)\r\n\r\n
\r\n\r\nView all\r\n \r\n\r\n" - }, - "name": "text - 10", - "styleSettings": { - "margin": "0", - "padding": "0" - }, - "id": "0c781e85-af9a-41a6-9cf7-b3bb9a09d5d0" - } - ] - }, - "customWidth": "100", - "name": "group - Exec Emerging Threats", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "4f8886d3-882a-4c14-ab7f-a37bd302e32f" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Microsoft 365 Secure Email Gateway Performance\r\n
\r\n\r\n

Using multiple vendor email security products can offer diverse detections. However, our comprehensive end-to-end approach—spanning prevention, detection, posture, investigation, response, and user training—delivers a unified and effective defense that matches or exceeds the efficacy of siloed Secure Email Gateway solutions.

\r\n\r\n[

Learn more

](https://www.microsoft.com/en-us/security/blog/2026/06/15/microsoft-defender-email-security-benchmarking-key-insights-from-one-year-of-data/) \r\n\r\n
\r\n

High-severity email threats missed per 1,000 users protected - February–April 2026 (Microsoft Defender email security benchmarking)

" - }, - "name": "text - 12", - "id": "94c804f9-2860-4768-be59-fb31a4ff22d7" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "datatable(Index:int, Name:string, Value:int)\r\n[\r\n 1, \"Defender for Office 365\", 194,\r\n 2, \"Mimecast\", 478,\r\n 3, \"ProofPoint\", 483,\r\n 4, \"HornetSecurity\", 813,\r\n 5, \"TrendMicro\", 1151,\r\n 6, \"IronPort\", 1274,\r\n 7, \"Barracuda\", 1585,\r\n 8, \"FireEye\", 2107\r\n]\r\n| project [\"Email security solution\"] = Name, [\"High-severity threats missed / 1K users\"] = Value\r\n| order by [\"High-severity threats missed / 1K users\"] asc\r\n", - "size": 0, - "timeContext": { - "durationMs": 86400000 - }, - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Email security solution", - "formatter": 1, - "formatOptions": { - "customColumnWidthSetting": "40%" - } - }, - { - "columnMatch": "High-severity threats missed / 1K users", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "min": 0, - "max": 2107, - "customColumnWidthSetting": "60%" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "useGrouping": true - } - } - } - ], - "rowLimit": 10, - "sortBy": [ - { - "itemKey": "High-severity threats missed / 1K users", - "sortOrder": 1 - } - ] - } - }, - "name": "query - 11", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "e54fd5bd-17e2-40dc-897d-8a3bb21116ff" - } - ] - }, - "customWidth": "100", - "name": "group - Exec SEG Performance", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "1f3a7e2b-0a1f-48ba-9da3-e7531d500938" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "id": "ab3756d3-3f60-4024-9376-0f1a7d47ac13", - "type": 1, - "name": "text - 18", - "content": { - "json": "\r\n\r\n\r\n\r\n
Stay Current\r\n
\r\n\r\n
\r\n\r\n- **Threat Analytics (Defender XDR)** — live, tenant-specific threat intelligence and recommended actions: aka.ms/threatanalytics\r\n- **Microsoft Security Blog** — campaign write-ups and threat research: microsoft.com/security/blog\r\n- **Microsoft Defender for Office 365 Tech Community blog** — product updates and reporting guidance: Tech Community\r\n- **Latest features in Microsoft Defender for Office 365** — What's new in Microsoft Defender for Office 365 \r\n- **Share reporting feedback**: aka.ms/mdoreportingfeedback\r\n" - } - } - ] - }, - "customWidth": "100", - "name": "group - Exec Stay Current", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "5e22c565-cd2e-41f3-8d5a-0735af67c93f" - } - ], - "exportParameters": true - }, - "customWidth": "100", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "1" - }, - "name": "Detection Overview", - "styleSettings": { - "margin": "0", - "padding": "0" - }, - "id": "3f2cc277-9eb3-486d-a1f8-9fa5374a3d80" - }, - { - "type": 1, - "content": { - "json": "# Malware detection insights\r\n\r\n---\r\n\r\nThis tab provides insights into email message **detections** by Microsoft Defender for Office 365 where the message contained a **malware threat** (such as viruses, spyware, or ransomware) within its **URLs** or **attachments**." - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "2" - }, - "name": "text - 13", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "81f28ffc-b69e-4960-a61c-cac17a012ed6" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//KPI summary of inbound email malware detections for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet mal = EmailEvents | where EmailDirection == \"Inbound\" | where ThreatTypes has \"Malware\";\r\nlet inbox = mal | where DeliveryLocation has \"Inbox\";\r\nlet malTrend = toscalar(mal | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet inboxTrend = toscalar(inbox | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(mal | summarize count()), Details = \"Malware Emails\", Ord = 1, Trend = malTrend),\r\n(print Count = toscalar(mal | summarize dcount(RecipientEmailAddress)), Details = \"Users Targeted\", Ord = 2, Trend = malTrend),\r\n(print Count = toscalar(mal | summarize dcount(SenderFromDomain)), Details = \"Sender Domains\", Ord = 3, Trend = malTrend),\r\n(print Count = toscalar(inbox | summarize count()), Details = \"Delivered to Inbox\", Ord = 4, Trend = inboxTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "leftContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 0, - "palette": "blue" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "secondaryContent": { - "columnMatch": "Trend", - "formatter": 21, - "formatOptions": { - "min": 0, - "palette": "blue" - } - }, - "showBorder": true, - "size": "auto" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "2" - }, - "name": "malware kpi strip", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "20c06dd3-5025-4b2b-960e-ff012f5d2343" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Malware Detection Trends, Threat Classes, and Malware Names\r\n
\r\n\r\nThis section consolidates key visuals that track and explain malware detections in inbound email as identified by Microsoft Defender for Office 365 focusing on per-{Granularity} trend, threat classes and Malware types. \r\n

**Recommended action:** If malware volume spikes, confirm Safe Attachments (Block mode) is enabled for all users and investigate the top malware families below." - }, - "name": "text - 14", - "id": "1f09c6ec-b2de-4aa9-bd8e-81d11c92ebd4" - }, - { - "type": 1, - "content": { - "json": "### Malware Detection Trend\r\n**This visual displays a per-{Granularity} trend of email malware detections identified by Microsoft Defender for Office 365. The area chart summarises the number of messages flagged for malware threats.**" - }, - "name": "text - Malware Trend header", - "id": "e90b714f-de84-4571-9a60-b3b2f3bd09dd" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Malware detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents \r\n| where ThreatTypes has \"Malware\" \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize MalwareDetections = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, MalwareDetections = coalesce(MalwareDetections, 0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "areachart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "MalwareDetections", - "color": "blueDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "2" - }, - "name": "query - 0", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "350d0aa3-c093-4105-a150-c20111ac2912" - }, - { - "type": 1, - "content": { - "json": "### Malware Detection Trend - Advanced Threats\r\n**Not all threats are going to be easily recognisable, that's why Microsoft Defender for Office 365 has advanced threat detection methods, that use virtual sandbox environments to detonate URLs and Files. These virtual sandbox technologies look for known patterns, such as a recognisable login page in a URL, or a file accessing command and control infrastructure. This visual displays a per-{Granularity} trend of Malware detections of these advanced threats**" - }, - "name": "text - Malware Advanced Threats header", - "id": "12e07248-ada4-41d9-99cc-824eb65cff79" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Malware detections over time summarizing the data daily by Malware detection technologies/controls used for detecting unknown-unique malware.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Malware'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand MalwareMethod = ParsedMethods.Malware\r\n| where MalwareMethod in ('File detonation','URL detonation')\r\n| summarize Count = count() by MalwareMethod = tostring(MalwareMethod), Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct MalwareMethod | extend d = 1) on d | project Timestamp, MalwareMethod\r\n| join kind=leftouter (agg) on Timestamp, MalwareMethod\r\n| project Timestamp, MalwareMethod, Count = coalesce(Count, 0)\r\n| sort by MalwareMethod asc, Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "File detonation", - "color": "redDark" - }, - { - "seriesName": "URL detonation", - "color": "orangeDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "2" - }, - "name": "query - 9", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "ebcb6f29-02be-4dd0-b792-cd99285c29d4" - }, - { - "type": 1, - "content": { - "json": "### Malware Detections by Threat Classification\r\n**Summary of email messages detected by Microsoft Defender for Office 365 as malware, grouped by type of malware (Adware, Downloader, HackTool, Ransomware, Remote access trojan, Spyware).**" - }, - "customWidth": "33", - "name": "text - 15", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "5638fc51-0830-4675-87d4-82f03df17bbf" - }, - { - "type": 1, - "content": { - "json": "### Top Attacked Users by Malware Threat Classification\r\n**Displays the recipient most frequently targeted for each malware type (Adware, Downloader, HackTool, Ransomware, Remote access trojan, Spyware) in inbound email detections.**" - }, - "customWidth": "33", - "name": "text - 15 - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "d2e3903b-4984-40da-a437-3d6a2b121e23" - }, - { - "type": 1, - "content": { - "json": "### Malware Detections by Threat Name\r\n**Summarises email messages flagged by Microsoft Defender for Office 365, grouped by specific malware names detected in URLs or attachments.**" - }, - "customWidth": "33", - "name": "text - 15 - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "6c0bebcf-9838-4385-ab3a-30db6c994284" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Malware detections summarizing the data by threat classification of the malware threat in the message.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where ThreatTypes has 'Malware' and ThreatClassification has_any(\"Adware\",\"Downloader\",\"HackTool\",\"Ransomware\",\"Remote access trojan\",\"Spyware\")\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Count = count(Key) by ThreatClassification\r\n| sort by Count desc", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "chartSettings": { - "createOtherGroup": 10 - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "33", - "name": "query - 11", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "acb98530-8e3a-4383-b42f-8fd74b1c3fbe" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises Malware detections in emails summarizing by various Threat classes showing the top attacked user for each threat classification type.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where ThreatTypes has \"Malware\" and EmailDirection == \"Inbound\" and ThreatClassification has_any(\"Adware\",\"Downloader\",\"HackTool\",\"Ransomware\",\"Remote access trojan\",\"Spyware\")\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize EmailCount=count() by ThreatClassification, RecipientEmailAddress\r\n| summarize Count = arg_max(EmailCount, RecipientEmailAddress) by ThreatClassification\r\n| sort by Count desc\r\n| project ['Threat Classification'] = ThreatClassification, ['Top Recipient'] = RecipientEmailAddress, ['Emails'] = Count", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "TopEmailCount", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ], - "filter": true - }, - "statSettings": { - "valueField": "RecipientEmailAddress", - "valueAggregation": "None", - "colorSettings": { - "type": "static", - "mode": "background", - "heatmapPalette": "greenRed", - "thresholdsGrid": [] - }, - "iconSettings": { - "thresholdsGrid": [] - }, - "tagText": "", - "valueFontStyle": "auto" - }, - "chartSettings": { - "xAxis": "RecipientEmailAddress" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "33", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "2" - }, - "name": "query - 5 - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "d9b46c97-91ce-4d64-aca6-3126ac49c0ff" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Malware detections summarizing the data by ThreatNames of the malware detected.\r\nEmailEvents \r\n| where isnotempty(ThreatNames) and ThreatTypes has \"Malware\" \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , \"-\", RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| mv-expand ThreatName = split(ThreatNames, \",\") to typeof(string)\r\n| where isnotempty(ThreatName)\r\n| distinct Key, ThreatName\r\n| summarize Count = count() by ThreatName\r\n| top 15 by Count\r\n| project ['Threat Name'] = ThreatName, Count", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Count", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "chartSettings": { - "xAxis": "ThreatNames", - "yAxis": [ - "count_" - ], - "createOtherGroup": 10 - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "33", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "2" - }, - "name": "query - 3", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "b9a4b34f-f54f-4d6e-bb20-81925d0f5540" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "2" - }, - "name": "group - 3", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "82853a93-e11f-4e4a-80f4-733850a1d3ff" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Malware Detections by Delivery Location, Detection Technology and Sender Infrastructure Insights\r\n
\r\n\r\nThis section consolidates key visuals that track and explain malware detections delivery locations, detection technologies used for detections, sender infrastructure insights in inbound email identified by Microsoft Defender for Office 365 as Malware. \r\n

**Recommended action:** For sender IPs or countries you do not do business with, consider connection filtering or geo-based rules; verify the detection technologies catching these are enabled." - }, - "name": "banner - Malware Delivery Detection Sender", - "id": "cba6403d-e2b1-4fe8-af52-57e5c2aa8e54" - }, - { - "type": 1, - "content": { - "json": "### Malware Detections by delivery location\r\n**Visualizes counts (per {Granularity}) of malware detections of inbound emails by delivery location: Quarantine or Failed (rejected with or without NDR)**" - }, - "name": "text - Malware Delivery Location header", - "id": "95be7f48-40eb-4154-91d8-20f7033f2ff5" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Malware detections over time summarizing the data daily by Delivery Location\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Malware' and EmailDirection == 'Inbound'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalMalwareDetections=count(), Quarantine=countif(DeliveryLocation == 'Quarantine'), Failed=countif(DeliveryLocation == 'Failed') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, TotalMalwareDetections=coalesce(TotalMalwareDetections,0), Quarantine=coalesce(Quarantine,0), Failed=coalesce(Failed,0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "TotalMalwareDetections", - "color": "blue" - }, - { - "seriesName": "Quarantine", - "color": "orangeDark" - }, - { - "seriesName": "Failed", - "color": "redDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "2" - }, - "name": "query - 10", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "b2c19e58-2123-490b-9631-c0b238c582e6" - }, - { - "type": 1, - "content": { - "json": "### Malware Detections by Detection Technology\r\n**Visualizes counts (per {Granularity}) of Malware detections of inbound emails by various Microsoft Defender for Office 365 detection technologies.**" - }, - "name": "text - Malware Detection Technology header", - "id": "f3c2691e-4f32-4109-9524-8a11719e4425" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Malware detections over time summarizing the data daily by various Malware detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Malware'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand MalwareMethod = ParsedMethods.Malware\r\n| summarize Count = count() by MalwareMethod = tostring(MalwareMethod), Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct MalwareMethod | extend d = 1) on d | project Timestamp, MalwareMethod\r\n| join kind=leftouter (agg) on Timestamp, MalwareMethod\r\n| project Timestamp, MalwareMethod, Count = coalesce(Count, 0)\r\n| sort by MalwareMethod asc, Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "66", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "2" - }, - "name": "query - 8", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "f00c1ce0-e55e-44c0-8bf0-4af662ccef89" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Malware detections summarizing the data by various Malware detection technologies/controls in Microsoft Defender for Office 365.\r\nEmailEvents \r\n| where DetectionMethods has 'Malware'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand MalwareMethod = ParsedMethods.Malware\r\n| summarize Count = count() by MalwareMethod = tostring(MalwareMethod)\r\n| sort by Count desc\r\n| project ['Detection Technology'] = MalwareMethod, ['Detections'] = Count", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Detections", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "34", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "2" - }, - "name": "query - 2", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "590880a9-1cf7-44ae-b4de-2f65bc700b5d" - }, - { - "type": 1, - "content": { - "json": "### Malware Detections by SenderIPv4 Geo Location\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Malware, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" - }, - "name": "text - Malware Geo Location header", - "id": "19d78b48-af58-4bee-abfe-57efb1eba125" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Malware detections summarizing the data by email sender IP address (SenderIPv4).\r\nEmailEvents \r\n| where ThreatTypes has 'Malware' and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_", - "size": 0, - "showAnalytics": true, - "title": "Malware Detections-Sender Heatmap (IPv4)", - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "map", - "gridSettings": { - "sortBy": [ - { - "itemKey": "count_", - "sortOrder": 2 - } - ] - }, - "sortBy": [ - { - "itemKey": "count_", - "sortOrder": 2 - } - ], - "mapSettings": { - "locInfo": "LatLong", - "locInfoColumn": "GeoInfo", - "latitude": "Latitude", - "longitude": "Longitude", - "sizeSettings": "count_", - "sizeAggregation": "Sum", - "labelSettings": "SenderIPv4", - "legendMetric": "count_", - "legendAggregation": "Sum", - "itemColorSettings": { - "nodeColorField": "count_", - "colorAggregation": "Sum", - "type": "none" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "2" - }, - "name": "query - 1", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "8cb46ec0-ac2a-41d1-bf8a-0b8585d1fefc" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Malware detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where ThreatTypes has 'Malware' and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Malware Emails'] = count_\r\n| sort by ['Malware Emails'] desc\r\n\r\n\r\n", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Malware Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "sortBy": [], - "mapSettings": { - "locInfo": "LatLong", - "locInfoColumn": "GeoInfo", - "latitude": "Latitude", - "longitude": "Longitude", - "sizeSettings": "count_", - "sizeAggregation": "Sum", - "labelSettings": "SenderIPv4", - "legendMetric": "count_", - "legendAggregation": "Sum", - "itemColorSettings": { - "nodeColorField": "count_", - "colorAggregation": "Sum", - "type": "heatmap", - "heatmapPalette": "red" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "2" - }, - "name": "query - 1 - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "b6a0355a-2b8f-48a5-8edc-58f4f7f8180a" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "2" - }, - "name": "Malware-Detectiontech-Deliverylocation-SendingInfra", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "2692cb5e-825c-45c1-bd3a-096b55e8d760" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Malware Detections Top attacked users and top senders\r\n
\r\n\r\nThis section consolidates key visuals that track and explain malware detections in inbound email as identified by Microsoft Defender for Office 365 focusing on top attacked users and top senders. \r\n

**Recommended action:** Apply the Strict preset security policy to the most-attacked users and consider adding persistent malicious sender domains to the Tenant Allow/Block List." - }, - "name": "banner - Malware Top Users Senders", - "id": "bc5b37a4-71e4-4a2f-b0ba-b3dd87333391" - }, - { - "type": 1, - "content": { - "json": "### Malware Detections top attacked users\r\n**Displays the top 10 recipient email addresses that received inbound emails flagged as Malware. These users may be at higher risk and should be prioritised for targeted cybersecurity awareness training. Training should cover the specific threat types and techniques they are exposed to, and reinforce best practices for promptly reporting any suspicious messages that might bypass security controls and reach their inbox.**" - }, - "customWidth": "100", - "name": "text - Malware Top Users header", - "id": "cb87a026-ad03-45cc-887e-ab460490d9a5" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total inbound emails with Malware detections summarizing the data by the top 15 recipient email address (RecipientEmailAddress).\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),MalwareEmailCount = countif(ThreatTypes has \"Malware\") by RecipientEmailAddress\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(MalwareEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| where MalwareEmailCount !=0\r\n| top 15 by MalwareEmailCount\r\n| project ['Recipient'] = RecipientEmailAddress, ['Malware Emails'] = MalwareEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Malware Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Total Inbound", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Bad Traffic %", - "formatter": 4, - "formatOptions": { - "palette": "red", - "min": 0, - "max": 20, - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "50ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "count_", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "50ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "sortBy": [], - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "2" - }, - "name": "query - Malware Top Recipients", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "e7ffef62-f85e-4188-8ab9-d90a5c666c30" - }, - { - "type": 1, - "content": { - "json": "### Top 10 Sender Domains with Malware Detections (Inbound)\r\n**Displays the top 10 sender domains sending inbound emails detected as Malware. Helps identify external sources most frequently associated with malicious content for prioritised threat monitoring and mitigation.**" - }, - "customWidth": "100", - "name": "text - Malware Top Senders header", - "id": "93390807-25b2-4bea-9648-98e821da8ec6" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Malware detections summarizing the data by the top 15 email sender P2 domain (SenderFromDomain). Adding additional insights for total inbound emails and bad traffic percentage for each sender domain.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount = count(), MalwareEmailCount = countif(ThreatTypes has \"Malware\") by SenderFromDomain\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(MalwareEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| where MalwareEmailCount !=0\r\n| top 15 by MalwareEmailCount\r\n| project ['Sender Domain'] = SenderFromDomain, ['Malware Emails'] = MalwareEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Malware Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Total Inbound", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Bad Traffic %", - "formatter": 4, - "formatOptions": { - "palette": "red", - "min": 0, - "max": 20, - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal", - "useGrouping": false - } - } - }, - { - "columnMatch": "BadEmailCount", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "50ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "count_", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "50ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "sortBy": [], - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "2" - }, - "name": "query - Malware Top Sender Domains", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "eaa45734-2df2-4a5e-b35b-1295e00cb46f" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "2" - }, - "name": "MalwareTopAttackedUser-TopSenders", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "4e0900ab-e7e4-4cf1-93a4-7e86bca20782" - }, - { - "type": 1, - "content": { - "json": "# Phishing Detection Insights\r\n\r\n---\r\nThis tab provides insights into email message **detections** by Microsoft Defender for Office 365 where the message contained a **Phishing threat** within its **email content**, **URLs**, or **attachments**." - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "3" - }, - "name": "text - 24", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "fe82d665-fa9e-4fc2-9ba9-7e2eabb9a04b" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//KPI summary of inbound email phishing detections for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet ph = EmailEvents | where EmailDirection == \"Inbound\" | where ThreatTypes has \"Phish\";\r\nlet inbox = ph | where DeliveryLocation has \"Inbox\";\r\nlet phTrend = toscalar(ph | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet inboxTrend = toscalar(inbox | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(ph | summarize count()), Details = \"Phish Emails\", Ord = 1, Trend = phTrend),\r\n(print Count = toscalar(ph | summarize dcount(RecipientEmailAddress)), Details = \"Users Targeted\", Ord = 2, Trend = phTrend),\r\n(print Count = toscalar(ph | summarize dcount(SenderFromDomain)), Details = \"Sender Domains\", Ord = 3, Trend = phTrend),\r\n(print Count = toscalar(inbox | summarize count()), Details = \"Delivered to Inbox\", Ord = 4, Trend = inboxTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "leftContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 0, - "palette": "blue" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "secondaryContent": { - "columnMatch": "Trend", - "formatter": 21, - "formatOptions": { - "min": 0, - "palette": "blue" - } - }, - "showBorder": true, - "size": "auto" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "3" - }, - "name": "phish kpi strip", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "5debf0b8-4384-485b-8a7f-71ead592718a" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Phishing Detection Trend, LLM Content Analysis, Advanced Threats, and Threat Classes\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Phish detections in inbound email as identified by Microsoft Defender for Office 365 focusing on per-{Granularity} trends, advanced threat detections, LLM-based content analysis, and threat classes.

**Recommended action:** Review the LLM-classified phishing themes; enable Safe Links and impersonation protection, and prioritise awareness training on the dominant lure types." - }, - "name": "text - Phish Section1 Banner", - "id": "ce5e489f-c83b-4bc8-9e63-b08dfb5ef31f" - }, - { - "type": 1, - "content": { - "json": "### Phish Detection Trend
\r\n\r\n**This visual displays a per-{Granularity} trend of email Phish detections identified by Microsoft Defender for Office 365. The area chart summarises the number of messages flagged for Phish threats.**" - }, - "name": "text - Phish Trend Header", - "id": "429ef4d2-61a9-40d0-940f-2212ddce22ce" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phish detections over time summarizing the data daily.\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has \"Phish\"\r\n| summarize PhishDetections = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, PhishDetections = coalesce(PhishDetections, 0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "areachart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "PhishDetections", - "color": "blueDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "3" - }, - "name": "query - Phish Trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "b0d170ec-331c-4ad0-8ce6-258704cc5345" - }, - { - "type": 1, - "content": { - "json": "### Phish Detection Trend - Advanced Threats
\r\n\r\n**Not all threats are easily recognizable, which is why Microsoft Defender for Office 365 uses advanced detection methods, including virtual sandbox environments to detonate URLs and files. These virtual sandbox technologies look for known patterns, such as a recognisable login page in a URL, or a file accessing command and control infrastructure. This visual displays a per-{Granularity} trend of Phish detections of these advanced threats.**" - }, - "name": "text - Phish AdvThreats Header", - "id": "425476e0-066a-42ee-afb9-5dabc612a3c8" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phish detections over time summarizing the data daily by Phish detection technologies/controls used for detecting unknown-unique phish.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| project Timestamp, RecipientEmailAddress, NetworkMessageId, DT=parse_json(DetectionMethods)\r\n| evaluate bag_unpack(DT)\r\n| summarize [\"File detonation\"]=countif(Phish has 'File detonation' and Phish !has 'File detonation reputation'), [\"URL detonation\"]=countif(Phish has 'URL detonation' and Phish !has 'URL detonation reputation') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, [\"File detonation\"]=coalesce([\"File detonation\"],0), [\"URL detonation\"]=coalesce([\"URL detonation\"],0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "URL detonation", - "color": "orangeDark" - }, - { - "seriesName": "File detonation", - "color": "redDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "3" - }, - "name": "query - Phish AdvThreats Trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "6b62347a-b162-49e6-891c-07697af22dd9" - }, - { - "type": 1, - "content": { - "json": "### Phish Detections - LLM content analysis
\r\n\r\n**Microsoft Defender for Office 365 uses Language AI for Phish and Business Email Compromise (BEC) detection. These models are progressively learning from thousands of real-world phishing attempts and analyzing all messages classified as phish. Furthermore, it incorporates advanced Machine Learning and Natural Language Processing (NLP) techniques to read, process, and understand email content the way a human analyst might, yet in a fraction of the time and at a large scale. [Learn more](https://techcommunity.microsoft.com/blog/microsoftdefenderforoffice365blog/microsoft-defender-for-office-365s-language-ai-for-phish-enhancing-email-securit/4410446)**" - }, - "customWidth": "50", - "name": "text - Phish LLM Content Header", - "id": "c23460b1-e025-4f6c-b2d5-3f78c0c9afc6" - }, - { - "type": 1, - "content": { - "json": "### Phish Detections - LLM Threat Classifications
\r\n\r\n**Microsoft Defender for Office 365 uses purpose-built Large Language Models (LLM) at scale to provide AI-powered email and collaboration security. Our solution now parses language to understand and identify attacker intent and classifies threats at machine speed – keeping malicious emails out of your inbox and giving security operations (SOC) teams a new level of insight into adversary techniques. [Learn more](https://techcommunity.microsoft.com/blog/microsoftdefenderforoffice365blog/microsoft-ignite-redefining-email-security-with-llms-to-tackle-a-new-era-of-soci/4302421)**" - }, - "customWidth": "50", - "name": "text - Phish LLM ThreatClass Header", - "id": "1d723c26-501f-4385-9331-957ab7ae5019" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the total ammount of emails detected as Phish by LLM content analysis detection technology in Microsoft Defender for Office 365. \r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has 'Phish' and DetectionMethods contains \"LLM content analysis\"\r\n| summarize count()\r\n| sort by count_ desc", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "stat", - "statSettings": { - "valueAggregation": "None", - "colorSettings": { - "type": "thresholds", - "mode": "foreground", - "thresholdsGrid": [ - { - "operator": ">", - "thresholdValue": "0", - "representation": "red" - }, - { - "operator": "<=", - "thresholdValue": "0", - "representation": "red" - } - ] - }, - "iconSettings": { - "thresholdsGrid": [] - }, - "tagText": "", - "valueFontStyle": "auto", - "tagTextPosition": "bottom" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - Phish LLM Content Count", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "86a301c5-2bc0-436a-982c-861beee7c9ab" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phish detections summarizing the data by intent of the message.\r\n// Microsoft Defender for Office 365 LLM analysis is analyzing email messages to understand the intent of the messages. These threat classifications are then used in filtering decisions.\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has 'Phish' and ThreatClassification has_any(\"Business intelligence\",\"Contact establishment\",\"Gift card\",\"Invoice\",\"Payroll\",\"PII gathering\",\"Task\")\r\n| summarize count() by ThreatClassification\r\n| sort by count_ desc", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "chartSettings": { - "yAxis": [ - "count_" - ], - "createOtherGroup": 10 - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - Phish LLM ThreatClass Pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "d547b730-f174-4f78-8998-02f24453304e" - }, - { - "type": 1, - "content": { - "json": "### Top Attacked Users by LLM Threat classes (Phish)
\r\n\r\n**Displays recipients most frequently targeted by inbound phishing emails, grouped by threat classification (e.g., Gift Card, Invoice, Payroll). Helps identify users at higher risk for phishing attacks. These users may be at higher risk and should be prioritised for targeted cybersecurity awareness training. Training should cover the specific threat types and techniques they are exposed to, and reinforce best practices for promptly reporting any suspicious messages that might bypass security controls and reach their inbox.**" - }, - "customWidth": "100", - "name": "text - Phish LLM TopUsers Header", - "id": "4ba9d9eb-d88d-4e5d-ba58-a740559677f7" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises Phish detections in emails summarizing by various Threat classes showing the top attacked user for each threat classification type.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has \"Phish\" and EmailDirection == \"Inbound\" and ThreatClassification has_any(\"Business intelligence\",\"Contact establishment\",\"Gift card\",\"Invoice\",\"Payroll\",\"PII gathering\",\"Task\")\r\n| summarize EmailCount=count() by ThreatClassification, RecipientEmailAddress\r\n| summarize Emails = arg_max(EmailCount, RecipientEmailAddress) by ThreatClassification\r\n| sort by Emails desc\r\n| project ['Threat Classification'] = ThreatClassification, ['Top Recipient'] = RecipientEmailAddress, ['Emails'] = Emails", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true, - "formatters": [ - { - "columnMatch": "Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "80px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - Phish LLM TopUsers", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "51599ab2-db69-4195-b4e9-2828729ec35b" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "3" - }, - "name": "group - 5", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "25c47f6a-3525-435e-90cf-357f02fb2fed" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Phish Detections by Delivery location, Detection technology and Sender infrastructure insights\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Phish detections delivery locations, detection technologies used for detections, sender infrastructure insights in inbound email identified by Microsoft Defender for Office 365 as Phish.

**Recommended action:** Verify anti-phishing and Safe Links policies cover these delivery paths; consider blocking sender infrastructure from regions you do not operate in, where appropriate." - }, - "name": "text - Phish Section2 Banner", - "id": "6876063e-6a4f-48ea-829d-4486922783dd" - }, - { - "type": 1, - "content": { - "json": "### Phish Detections by delivery location
\r\n\r\n**Visualizes counts (per {Granularity}) of Phish detections of inbound emails by various delivery locations: Quarantine, Junk folder or Failed (rejected with or without NDR)**" - }, - "name": "text - Phish DeliveryLoc Header", - "id": "b5045aab-1b4b-4d35-af41-a6315d36e864" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phish detections over time summarizing the data daily by Delivery Location.\r\n//The comment in the query excludes deliveries to the SecOps Mailboxes and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\" and EmailDirection == \"Inbound\"\r\n| summarize TotalPhishDetections=count(), Quarantine=countif(DeliveryLocation == \"Quarantine\"), Junkfolder=countif(DeliveryLocation == \"Junk folder\"), Inbox=countif(DeliveryLocation == \"Inbox/folder\"), Failed=countif(DeliveryLocation == \"Failed\"), Dropped=countif(DeliveryLocation == \"Dropped\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, TotalPhishDetections=coalesce(TotalPhishDetections,0), Quarantine=coalesce(Quarantine,0), Junkfolder=coalesce(Junkfolder,0), Inbox=coalesce(Inbox,0), Failed=coalesce(Failed,0), Dropped=coalesce(Dropped,0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "Quarantine", - "color": "greenDark" - }, - { - "seriesName": "Failed", - "color": "green" - }, - { - "seriesName": "Dropped", - "color": "green" - }, - { - "seriesName": "Junk folder", - "color": "orangeDark" - }, - { - "seriesName": "Inbox", - "color": "redBright" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "3" - }, - "name": "query - Phish DeliveryLoc Trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "e839848c-d176-4251-bbb4-1c2e1103ed2d" - }, - { - "type": 1, - "content": { - "json": "### Phish detections by Detection Technology
\r\n\r\n**Visualizes counts (per {Granularity}) of Phish detections of inbound emails by various Microsoft Defender for Office 365 detection technologies.**" - }, - "name": "text - Phish DetTech Header", - "id": "149bf1b3-80cc-4e82-ae5d-ddee0f6b0cd9" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phish detections over time summarizing the data daily by various Phish Detection technologies/controls in Microsoft Defender for Office 365.\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "chartSettings": { - "createOtherGroup": 15 - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "3" - }, - "name": "query - Phish DetTech Trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "b0b16329-e1a6-4138-871e-76d57a60b978" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phish detections summarized by individual Phish detection technology/control in Microsoft Defender for Office 365.\r\n//Each detection technology is counted individually via mv-expand over DetectionMethods.Phish (matching the sibling trend line chart), so a message flagged by multiple techniques counts once per technique.\r\n//The where clause excludes deliveries to the SecOps Mailbox and by the Phish Simulation system.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details\r\n| sort by Count desc\r\n| project ['Detection Technology'] = Details, ['Detections'] = Count", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Detections", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "3" - }, - "name": "query - Phish DetTech Pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "5270ba04-599f-4940-805b-687f7475bc70" - }, - { - "type": 1, - "content": { - "json": "### Phish Detections by SenderIPv4 Geo Location
\r\n\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Phish, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" - }, - "name": "text - Phish Geo Header", - "id": "ddd0c12f-1bb1-4d7d-afb4-f28bcfcd7c4b" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phish detections summarizing the data by email sender IP address (SenderIPv4).\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ThreatTypes has \"Phish\" and isnotempty(SenderIPv4)\r\n| summarize count() by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "map", - "mapSettings": { - "locInfo": "LatLong", - "latitude": "Latitude", - "longitude": "Longitude", - "sizeSettings": "count_", - "sizeAggregation": "Sum", - "labelSettings": "SenderIPv4", - "legendMetric": "count_", - "legendAggregation": "Sum", - "itemColorSettings": { - "nodeColorField": "count_", - "colorAggregation": "Sum", - "type": "none" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "3" - }, - "name": "query - Phish Geo Map", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "85ea7223-7d77-43f5-b0d9-e0de7c898758" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phish detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where ThreatTypes has 'Phish' and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Phish Emails'] = count_\r\n| sort by ['Phish Emails'] desc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Phish Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ] - }, - "mapSettings": { - "locInfo": "LatLong", - "latitude": "Latitude", - "longitude": "Longitude", - "sizeSettings": "count_", - "sizeAggregation": "Sum", - "labelSettings": "SenderIPv4", - "legendMetric": "count_", - "legendAggregation": "Sum", - "itemColorSettings": { - "nodeColorField": "count_", - "colorAggregation": "Sum", - "type": "heatmap", - "heatmapPalette": "red" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "3" - }, - "name": "query - Phish Country Table", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "f561209b-15a6-442e-af10-63e375088209" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "3" - }, - "name": "group - 25- Phish delivery locations-detecion tech-sender infra", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "10f3e3eb-b330-4955-952e-01eff69405e9" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Phish Detections Top attacked users and top senders\r\n
\r\n\r\nThis section consolidates key visuals that track and explain phish detections in inbound email as identified by Microsoft Defender for Office 365 focusing on top attacked users and top senders.

**Recommended action:** Enroll the most-targeted users in security awareness training and consider blocking persistent phishing sender domains." - }, - "name": "text - Phish Section3 Banner", - "id": "f46ed4a8-e2b5-4ccd-ae38-efc571bfc791" - }, - { - "type": 1, - "content": { - "json": "### Phish Detections top attacked users\r\n**Displays the top 10 recipient email addresses that received inbound emails flagged as Phish. These users may be at higher risk and should be prioritised for targeted cybersecurity awareness training. Training should cover the specific threat types and techniques they are exposed to, and reinforce best practices for promptly reporting any suspicious messages that might bypass security controls and reach their inbox.**" - }, - "customWidth": "100", - "name": "text - Phish TopUsers Header", - "id": "96d9b543-070a-42d4-bbed-3f5cf79ca7ce" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total inbound emails with Phish detections summarizing the data by the top 15 recipient email address (RecipientEmailAddress).\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),PhishEmailCount = countif(ThreatTypes has \"Phish\") by RecipientEmailAddress\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(PhishEmailCount / todouble(TotalEmailCount) * 100, 2))\r\n| where PhishEmailCount !=0\r\n| top 15 by PhishEmailCount\r\n| project ['Recipient'] = RecipientEmailAddress, ['Phish Emails'] = PhishEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Phish Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Total Inbound", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Bad Traffic %", - "formatter": 4, - "formatOptions": { - "palette": "red", - "min": 0, - "max": 20, - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "50ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "count_", - "formatter": 3, - "formatOptions": { - "palette": "redDark" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "sortBy": [], - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "3" - }, - "name": "query - Phish TopRecipients Table", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "25100115-78d3-4144-b44e-613b44f02484" - }, - { - "type": 1, - "content": { - "json": "### Top 10 Sender Domains with Phish Detections (Inbound)\r\n**Displays the top 10 sender domains sending inbound emails detected as Phish. Helps identify external sources most frequently associated with malicious content for prioritised threat monitoring and mitigation.**" - }, - "customWidth": "100", - "name": "text - Phish TopSenders Header", - "id": "e7fcb7fe-4bca-4153-a9b0-8ded135b1c64" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phish detections summarizing the data by the top 15 email sender P2 domain (SenderFromDomain), now including the Phish confidence split (High/Normal) and the aggregated phish detection methods seen per domain. Adding additional insights for total inbound emails and bad traffic percentage for each sender domain.\r\n//The comment in the query excludes deliveries to the SecOps Mailbox and by the Phish Simulation system. Remove the \"//\" to apply the exclusion.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where EmailDirection == \"Inbound\"\r\n| extend PhishConf = tostring(parse_json(ConfidenceLevel).Phish)\r\n| extend PhishMethods = parse_json(DetectionMethods).Phish\r\n| summarize TotalEmailCount = count(),\r\n PhishEmailCount = countif(ThreatTypes has \"Phish\"),\r\n Phish_High = countif(ThreatTypes has \"Phish\" and PhishConf == \"High\"),\r\n Phish_Normal = countif(ThreatTypes has \"Phish\" and PhishConf == \"Normal\"),\r\n PhishMethodSet = make_set_if(PhishMethods, ThreatTypes has \"Phish\") by SenderFromDomain\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(PhishEmailCount / todouble(TotalEmailCount) * 100, 2))\r\n| where PhishEmailCount != 0\r\n| top 15 by PhishEmailCount\r\n| mv-apply S = PhishMethodSet on ( mv-expand m = S to typeof(string) | summarize Methods = make_set(m) )\r\n| project ['Sender Domain'] = SenderFromDomain, ['Phish Emails'] = PhishEmailCount, ['Phish (High)'] = Phish_High, ['Phish (Normal)'] = Phish_Normal, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound, ['Detection Methods'] = strcat_array(Methods, \", \")", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Phish Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Phish (High)", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Phish (Normal)", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Total Inbound", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Bad Traffic %", - "formatter": 4, - "formatOptions": { - "palette": "red", - "min": 0, - "max": 20, - "customColumnWidthSetting": "50ch" - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "BadEmailCount", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "50ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "count_", - "formatter": 3, - "formatOptions": { - "palette": "redDark" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "sortBy": [], - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "3" - }, - "name": "query - Phish TopSenders Table", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "717bfce8-b5d4-4900-99db-4ba0c503591d" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "3" - }, - "name": "group - 26-PhishDetectionsTopattackedusers-topsenders", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "553afca2-caa1-45b1-bec0-dca426b5be46" - }, - { - "type": 1, - "content": { - "json": "# Spam Detection Insights\r\n\r\n---\r\nThis tab provides insights into email message **detections** by Microsoft Defender for Office 365 where the message contained a **Spam threat** within its **email content**, **URLs**, or **attachments**." - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "4" - }, - "name": "text - Spam Tab Intro", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "a693a05a-a772-4ac4-9863-07ad0d1b7092" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//KPI summary of inbound email spam detections for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet sp = EmailEvents | where EmailDirection == \"Inbound\" | where ThreatTypes has \"Spam\";\r\nlet junk = sp | where DeliveryLocation has \"Junk\";\r\nlet spTrend = toscalar(sp | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet junkTrend = toscalar(junk | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(sp | summarize count()), Details = \"Spam Emails\", Ord = 1, Trend = spTrend),\r\n(print Count = toscalar(sp | summarize dcount(RecipientEmailAddress)), Details = \"Users Targeted\", Ord = 2, Trend = spTrend),\r\n(print Count = toscalar(sp | summarize dcount(SenderFromDomain)), Details = \"Sender Domains\", Ord = 3, Trend = spTrend),\r\n(print Count = toscalar(junk | summarize count()), Details = \"Sent to Junk\", Ord = 4, Trend = junkTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "leftContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 0, - "palette": "blue" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "secondaryContent": { - "columnMatch": "Trend", - "formatter": 21, - "formatOptions": { - "min": 0, - "palette": "blue" - } - }, - "showBorder": true, - "size": "auto" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "4" - }, - "name": "spam kpi strip", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "cadd5331-1db8-4ac8-bc99-42cd5227ee51" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Spam Detection Effectiveness and Trends\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Spam detections in inbound email as identified by Microsoft Defender for Office 365 focusing on Effectiveness and per-{Granularity} trend. For effectiveness, we consider messages reported by your admins and decisions made post-delivery.

**Recommended action:** If legitimate mail is marked as spam, review the Spam and Bulk thresholds; if spam is leaking through, tighten them." - }, - "name": "text - Spam Section1 Banner", - "id": "1093f3b6-cea7-4f54-9029-f9aadd79ca9f" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query calculates the effectiveness of spam detections without edge data.\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\n// baseQuery _FN_Admin_Submissions_SPM\r\nlet _FN_Admin_Submissions_SPM = toscalar(\r\nCloudAppEvents\r\n| where Timestamp between (minTime .. maxTime)\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType)\r\n| extend NetworkMessageId = tostring((parse_json(RawEventData)).ObjectId)\r\n| where SubmissionType in (\"0\")\r\n| summarize count()\r\n);\r\n// baseQuery _FN_ZAP_Successful_Spam\r\nlet _FN_ZAP_Successful_Spam = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and ActionType == \"Spam ZAP\" and ActionResult == \"Success\" and Timestamp between (minTime .. maxTime)\r\n| summarize count()\r\n //Take all our Spam ZAP, and count how many messages we missed and successfully cleaned up.\r\n);\r\n// baseQuery _FN_ZAP_Unsuccessful_Spam\r\nlet _FN_ZAP_Unsuccessful_Spam = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and ActionType == \"Spam ZAP\" and ActionResult != \"Success\" and Timestamp between (minTime .. maxTime)\r\n| summarize count()\r\n//Take all our Spam ZAP, and count how many messages we failed to clean up due to error or users/admins/API vendors getting to the message first.\r\n);\r\n// baseQuery _SPAM_ZAP_FP\r\nlet _SPAM_ZAP_FP = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and Action has_any (\"Redelivery\",\"Reprocessed\") and Timestamp between (minTime .. maxTime)\r\n| join kind=leftsemi (\r\n EmailEvents\r\n | where Timestamp between (minTime ..maxTime )\r\n | where ThreatTypes contains \"Spam\"\r\n | project NetworkMessageId, ThreatTypes)\r\n on NetworkMessageId\r\n| summarize count()\r\n// count all the FPs which were originally Spam, and when we TT'd them were not so we can subtract that from our mailfow catch, and therefore the total true bad.\r\n);\r\n// baseQuery _Spam_Mailflow\r\nlet _Spam_Mailflow = toscalar(\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and ThreatTypes == \"Spam\" and Timestamp between (minTime .. maxTime)\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count()\r\n// Get all the mailflow detected as SPM, then count all the NMIDs (not distinct)\r\n);\r\nprint\r\nEffectiveness_PostDelivery = abs(round(((toreal(toscalar(_FN_Admin_Submissions_SPM))+toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)))/(toreal(toscalar(_Spam_Mailflow))+toreal(toscalar(_FN_ZAP_Successful_Spam))+toreal(toscalar(_FN_ZAP_Unsuccessful_Spam))+toreal(toscalar(_FN_Admin_Submissions_SPM))-toreal(toscalar(_SPAM_ZAP_FP)))*100-100),2))", - "size": 1, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "stat", - "statSettings": { - "valueAggregation": "None", - "colorSettings": { - "type": "thresholds", - "mode": "foreground", - "heatmapPalette": "greenRed", - "thresholdsGrid": [ - { - "operator": ">", - "thresholdValue": "95", - "representation": "green" - }, - { - "operator": "<=", - "thresholdValue": "95", - "representation": "orange" - }, - { - "operator": "<=", - "thresholdValue": "90", - "representation": "red" - } - ] - }, - "iconSettings": { - "thresholdsGrid": [] - }, - "numberFormatSettings": { - "unit": 1, - "options": { - "style": "decimal" - } - }, - "tagText": "Spam Effectiveness (without Edge data)", - "valueFontStyle": "superLarge", - "tagTextPosition": "bottom" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - Spam Effectiveness Stat", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "036851c1-489e-4fda-8059-850c161578b3" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "let minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\n// baseQuery _FN_Admin_Submissions_SPM\r\nlet _FN_Admin_Submissions_SPM = toscalar(\r\nCloudAppEvents\r\n| where Timestamp between (minTime .. maxTime)\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType)\r\n| extend NetworkMessageId = tostring((parse_json(RawEventData)).ObjectId)\r\n| where SubmissionType in (\"0\")\r\n| summarize count()\r\n);\r\n// baseQuery _FN_ZAP_Successful_Spam\r\nlet _FN_ZAP_Successful_Spam = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and ActionType == \"Spam ZAP\" and ActionResult == \"Success\" and Timestamp between (minTime .. maxTime)\r\n| summarize count()\r\n //Take all our Spam ZAP, and count how many messages we missed and successfully cleaned up.\r\n);\r\n// baseQuery _FN_ZAP_Unsuccessful_Spam\r\nlet _FN_ZAP_Unsuccessful_Spam = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and ActionType == \"Spam ZAP\" and ActionResult != \"Success\" and Timestamp between (minTime .. maxTime)\r\n| summarize count()\r\n//Take all our Spam ZAP, and count how many messages we failed to clean up due to error or users/admins/API vendors getting to the message first.\r\n);\r\n// baseQuery _SPAM_ZAP_FP\r\nlet _SPAM_ZAP_FP = toscalar(\r\nEmailPostDeliveryEvents\r\n| where ActionTrigger == \"SpecialAction\" and Action has_any (\"Redelivery\",\"Reprocessed\") and Timestamp between (minTime .. maxTime)\r\n| join kind=leftsemi (\r\n EmailEvents\r\n | where Timestamp between (minTime ..maxTime )\r\n | where ThreatTypes contains \"Spam\"\r\n | project NetworkMessageId, ThreatTypes)\r\n on NetworkMessageId\r\n| summarize count()\r\n// count all the FPs which were originally Spam, and when we TT'd them were not so we can subtract that from our mailfow catch, and therefore the total true bad.\r\n);\r\n// baseQuery _Spam_Mailflow\r\nlet _Spam_Mailflow = toscalar(\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and ThreatTypes == \"Spam\" and Timestamp between (minTime .. maxTime)\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count()\r\n// Get all the mailflow detected as SPM, then count all the NMIDs (not distinct)\r\n);\r\nprint StatisticName=\"Spam Mailflow Minus FPs\", Value=toreal((toscalar(_Spam_Mailflow)) - toreal(toscalar(_SPAM_ZAP_FP)))\r\n| union (print StatisticName=\"Spam Admin FNs Submitted\", Value=toreal(toscalar(_FN_Admin_Submissions_SPM)))\r\n| union (print StatisticName=\"Spam FPs Reverse Zapped\", Value=toreal(toscalar(_SPAM_ZAP_FP)))\r\n| union (print StatisticName=\"Spam Zapped Successfully\", Value=toreal(toscalar(_FN_ZAP_Successful_Spam)))\r\n| union (print StatisticName=\"Spam NotZapped\", Value=toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)))\r\n| union (print StatisticName=\"Spam Effectiveness Post Delivery %\", Value=abs(round(((toreal(toscalar(_FN_Admin_Submissions_SPM)) + toreal(toscalar(_FN_ZAP_Unsuccessful_Spam))) / (toreal(toscalar(_Spam_Mailflow)) + toreal(toscalar(_FN_ZAP_Successful_Spam)) + toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)) + toreal(toscalar(_FN_Admin_Submissions_SPM)) - toreal(toscalar(_SPAM_ZAP_FP)))) * 100 - 100, 2)))\r\n| union (print StatisticName=\"Spam Effectiveness Pre-Delivery %\", Value=abs(round(((toreal(toscalar(_FN_Admin_Submissions_SPM)) + toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)) + (toscalar(_FN_ZAP_Successful_Spam))) / (toreal(toscalar(_Spam_Mailflow)) + toreal(toscalar(_FN_ZAP_Successful_Spam)) + toreal(toscalar(_FN_ZAP_Unsuccessful_Spam)) + toreal(toscalar(_FN_Admin_Submissions_SPM)) - toreal(toscalar(_SPAM_ZAP_FP)))) * 100 - 100, 2 )))\r\n| project ['Statistic'] = StatisticName, Value", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "tileSettings": { - "showBorder": false, - "titleContent": { - "columnMatch": "StatisticName", - "formatter": 1 - }, - "leftContent": { - "columnMatch": "Value", - "formatter": 12, - "formatOptions": { - "palette": "auto" - }, - "numberFormat": { - "unit": 17, - "options": { - "maximumSignificantDigits": 3, - "maximumFractionDigits": 2 - } - } - } - }, - "gridSettings": { - "formatters": [ - { - "columnMatch": "Value", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 2 - } - } - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - Spam Effectiveness Table", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "8d456ea2-f04a-4d71-95c6-fbaad8c2d2f2" - } - ] - }, - "customWidth": "100", - "name": "Spam Effectiveness", - "id": "82812b88-e7f7-4be0-9d13-8e7a7d8c0c4e" - }, - { - "type": 1, - "content": { - "json": "### Spam Detection Trend
\r\n\r\n**This visual displays a per-{Granularity} trend of email Spam detections identified by Microsoft Defender for Office 365. The area chart summarises the number of messages flagged for Spam threats.**" - }, - "name": "text - Spam Trend Header", - "id": "b5574a88-430b-4cca-a76e-9a0b07e9da2e" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Spam detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where ThreatTypes has \"Spam\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, SpamDetections = coalesce(Count, 0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "areachart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "SpamDetections", - "color": "blueDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - Spam Trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "09b7d330-1683-45c4-ac0e-8141580d13b5" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "4" - }, - "name": "group - 6-Spam-detections-trend", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "25273f47-8201-4565-8815-1d059ee8abb6" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Spam Detections by Delivery location, Detection technology, Sender infrastructure and Bulk insights\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Spam detections delivery locations, detection technologies used for detections, sender infrastructure and Bulk insights in inbound email identified by Microsoft Defender for Office 365 as Spam.

**Recommended action:** Raise the Bulk Complaint Level (BCL) threshold for noisy sender domains and consider blocking high-volume, low-value bulk senders where appropriate." - }, - "name": "text - Spam Section2 Banner", - "id": "b82f442b-a3a0-44f7-82df-2fd4a9594992" - }, - { - "type": 1, - "content": { - "json": "### Spam Detections by delivery location
\r\n\r\n**Visualizes counts (per {Granularity}) of Spam detections of inbound emails by various delivery locations Quarantine, Junk folder or Failed (rejected with or without NDR)**" - }, - "name": "text - Spam DeliveryLoc Header", - "id": "a6326d97-56cc-45fb-8019-e0c3346968f2" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Spam detections over time summarizing the data daily by Delivery Location.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Spam\" and EmailDirection == \"Inbound\"\r\n| summarize TotalSpamDetections=count(), Quarantine=countif(DeliveryLocation == \"Quarantine\"), Junkfolder=countif(DeliveryLocation == \"Junk folder\"), Inbox=countif(DeliveryLocation == \"Inbox/folder\"), Failed=countif(DeliveryLocation == \"Failed\"), Dropped=countif(DeliveryLocation == \"Dropped\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, TotalSpamDetections=coalesce(TotalSpamDetections,0), Quarantine=coalesce(Quarantine,0), Junkfolder=coalesce(Junkfolder,0), Inbox=coalesce(Inbox,0), Failed=coalesce(Failed,0), Dropped=coalesce(Dropped,0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "TotalSpamDetections", - "color": "blue" - }, - { - "seriesName": "Quarantine", - "color": "greenDark" - }, - { - "seriesName": "Junkfolder", - "color": "orangeDark" - }, - { - "seriesName": "Inbox", - "color": "redBright" - }, - { - "seriesName": "Failed", - "color": "red" - }, - { - "seriesName": "Dropped", - "color": "redDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - Spam DeliveryLoc Trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "97f89032-34e3-40ff-bb88-42d195aea095" - }, - { - "type": 1, - "content": { - "json": "### Spam Detections Detection Technology
\r\n\r\n**Visualizes counts (per {Granularity}) of Spam detections of inbound emails by various Microsoft Defender for Office 365 detection technologies.**" - }, - "name": "text - Spam DetTech Header", - "id": "935ea90d-8430-49d5-b942-3a7b319a603e" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Spam detections over time summarizing the data daily by various Spam Detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where DetectionMethods has \"Spam\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| mv-expand Details = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - Spam DetTech Trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "f31ec0d1-04e1-4b2b-9b98-27289ca34b84" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Spam detections summarized by individual Spam detection technology/control in Microsoft Defender for Office 365.\r\n//Each technique is counted individually via mv-expand over DetectionMethods.Spam (matching the sibling trend line chart), so a message flagged by multiple techniques counts once per technique.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Spam\"\r\n| mv-expand Details = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details\r\n| sort by Count desc\r\n| project ['Detection Technology'] = Details, ['Detections'] = Count", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Detections", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - Spam DetTech Pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "95e40479-f0bc-41ff-8191-634b606d3632" - }, - { - "type": 1, - "content": { - "json": "### Spam Detections by SenderIPv4 Geo Location
\r\n\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Spam, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" - }, - "name": "text - Spam Geo Header", - "id": "614d1c3f-df6a-4659-b170-7b466c66d66f" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Spam detections summarizing the data by email sender IP address (SenderIPv4).\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where ThreatTypes has \"Spam\" and isnotempty(SenderIPv4)\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_ ", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "map", - "mapSettings": { - "locInfo": "LatLong", - "locInfoColumn": "SenderIPv4", - "latitude": "Latitude", - "longitude": "Longitude", - "sizeSettings": "count_", - "sizeAggregation": "Sum", - "labelSettings": "SenderIPv4", - "legendMetric": "count_", - "legendAggregation": "Sum", - "itemColorSettings": { - "nodeColorField": "count_", - "colorAggregation": "Sum", - "type": "none" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - Spam Geo Map", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "5519d715-dc79-45f8-8ed5-a63a253c45e3" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Spam detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where ThreatTypes has 'Spam' and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Spam Emails'] = count_\r\n| sort by ['Spam Emails'] desc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Spam Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "50ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ] - }, - "mapSettings": { - "locInfo": "LatLong", - "locInfoColumn": "SenderIPv4", - "latitude": "Latitude", - "longitude": "Longitude", - "sizeSettings": "count_", - "sizeAggregation": "Sum", - "labelSettings": "SenderIPv4", - "legendMetric": "count_", - "legendAggregation": "Sum", - "itemColorSettings": { - "nodeColorField": "count_", - "colorAggregation": "Sum", - "type": "heatmap", - "heatmapPalette": "red" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - Spam Country Table", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "5078dc24-e8be-4943-98fc-6527968e1e3d" - }, - { - "type": 1, - "content": { - "json": "### Spam Detections Bulk Insights
\r\n\r\n**Displays the distribution of inbound emails across different Bulk Complaint Levels together with Top 10 domains sending Bulk email (grey mail). Helps identify patterns in bulk email complaints and assess potential spam or unwanted message trends.**" - }, - "name": "text - Spam Bulk Header", - "id": "cd7b3cbe-a6c1-422c-ab37-4afc26002d5d" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total inbound emails which has any Bulk complaint level. It is summarizing the data by the various Bulk Complaint levels to understand how many messages are detected with each Bulk Complaint level.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\" and isnotnull(BulkComplaintLevel)\r\n| summarize count() by BulkComplaintLevel\r\n| sort by BulkComplaintLevel desc\r\n| project ['Bulk Complaint Level'] = BulkComplaintLevel, Emails=count_", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Emails", - "formatter": 3, - "formatOptions": { - "palette": "blueDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - Spam Bulk By Level", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "021c022b-aa67-427d-9e1a-688af7aed5d4" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total inbound emails which has any Bulk complaint level. It is summarizing the data by the various Bulk Complaint levels and SenderFromDomain of the email sender. It provides insights how many messages are detected with each Bulk Complaint level for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\" and isnotnull(BulkComplaintLevel)\r\n| summarize count() by BulkComplaintLevel, SenderFromDomain\r\n| top 10 by count_ desc\r\n| project ['Sender Domain'] = SenderFromDomain, ['Bulk Complaint Level'] = BulkComplaintLevel, Emails=count_", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - Spam Bulk By Domain", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "b1835e0f-f9ad-44c3-bba4-cf9a9546d09a" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "4" - }, - "name": "group - 28-Spam-Delivery location-Detection technology-Sender infrastructure insights", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "307d3d03-93ae-4c8f-b68b-f833ee7d38e8" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n\r\n
Spam Detections Top attacked users and top senders\r\n
\r\n\r\nThis section consolidates key visuals that track and explain spam detections in inbound email as identified by Microsoft Defender for Office 365 focusing on top attacked users and top senders.

**Recommended action:** Review the most-affected users and the top spam sender domains as possible block-list candidates." - }, - "name": "text - Spam Section3 Banner", - "id": "4c34ed7b-86da-4ee1-8a69-f96c213a4340" - }, - { - "type": 1, - "content": { - "json": "### Spam Detections top attacked users
\r\n\r\n**Displays the top 10 recipient email addresses that received inbound emails flagged as Spam. These users may be at higher risk and should be prioritised for targeted cybersecurity awareness training. Training should cover the specific threat types and techniques they are exposed to, and reinforce best practices for promptly reporting any suspicious messages that might bypass security controls and reach their inbox.**" - }, - "customWidth": "100", - "name": "text - Spam TopUsers Header", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "be708ad5-51fd-4a54-b1bc-f912e12b4a01" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total inbound emails with Spam detections summarizing the data by the top 15 recipient email address (RecipientEmailAddress).\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where EmailDirection ==\"Inbound\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),SpamEmailCount = countif(ThreatTypes has \"Spam\") by RecipientEmailAddress\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(SpamEmailCount / todouble(TotalEmailCount)* 100, 2))\r\n| where SpamEmailCount !=0\r\n| top 15 by SpamEmailCount\r\n| project ['Recipient'] = RecipientEmailAddress, ['Spam Emails'] = SpamEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Spam Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Total Inbound", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Bad Traffic %", - "formatter": 4, - "formatOptions": { - "customColumnWidthSetting": "40ch", - "palette": "red", - "min": 0, - "max": 20 - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal", - "useGrouping": false - } - } - }, - { - "columnMatch": "Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "50ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "count_", - "formatter": 3, - "formatOptions": { - "palette": "blue" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "sortBy": [], - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - Spam TopRecipients Table", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "6e7b357d-6792-41c5-83fc-efae31afe2ee" - }, - { - "type": 1, - "content": { - "json": "### Top 10 Sender Domains with Spam Detections (Inbound)
\r\n\r\n**Displays the top 10 sender domains sending inbound emails detected as Spam. Helps identify external sources most frequently associated with spam content for prioritised monitoring and mitigation.**" - }, - "customWidth": "100", - "name": "text - Spam TopSenders Header", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "1d1bdb8d-9619-488b-935a-3791ad73f096" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total inbound emails with Spam detections summarizing the data by the top 15 email sender P2 domain (SenderFromDomain). Adding additional insights for total inbound emails and bad traffic percentage for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| where EmailDirection == \"Inbound\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount = count(),\r\n SpamEmailCount = countif(ThreatTypes has \"Spam\") by SenderFromDomain\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(SpamEmailCount / todouble(TotalEmailCount) * 100, 2))\r\n| where SpamEmailCount !=0\r\n| top 15 by SpamEmailCount\r\n| project ['Sender Domain'] = SenderFromDomain, ['Spam Emails'] = SpamEmailCount, ['Total Inbound'] = TotalEmailCount, ['Bad Traffic %'] = Bad_Traffic_Percentage_Inbound", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Spam Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Total Inbound", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Bad Traffic %", - "formatter": 4, - "formatOptions": { - "customColumnWidthSetting": "40ch", - "palette": "red", - "min": 0, - "max": 20 - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "50ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "count_", - "formatter": 3, - "formatOptions": { - "palette": "redDark" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "sortBy": [], - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - Spam TopSenders Table", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "253efada-ca89-49c5-b1e3-e42ac005b938" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "4" - }, - "name": "group - 29-Spam Detections Top attacked users and top senders", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "d4cc057f-c9b7-40b9-85d3-52f90767d1f5" - }, - { - "type": 1, - "content": { - "json": "# Email Impersonation & BEC Insights\r\n\r\n---\r\nThis tab focuses on the highest-value email threat class: **impersonation and Business Email Compromise (BEC)**. It brings together impersonation and spoof detections, sender authentication (DMARC, DKIM, SPF, CompAuth), supply-chain and partner-compromise correlation, and first-contact / new-vendor senders - the signals that precede targeted financial and credential attacks. It is the email-side companion to the impersonation insights on the **Teams & Collaboration** tab." - }, - "name": "text - impersonation bec description", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "15" - }, - "id": "fda8ccd5-fafc-457a-a6a2-05b504be1023" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//KPI summary of inbound email impersonation and spoof (BEC) detections for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet bec = EmailEvents | where EmailDirection == \"Inbound\" | where DetectionMethods has \"Impersonation\" or DetectionMethods has \"Spoof\";\r\nlet inbox = bec | where DeliveryLocation has \"Inbox\";\r\nlet becTrend = toscalar(bec | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet inboxTrend = toscalar(inbox | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(bec | summarize count()), Details = \"Impersonation / Spoof Emails\", Ord = 1, Trend = becTrend),\r\n(print Count = toscalar(bec | summarize dcount(RecipientEmailAddress)), Details = \"Users Targeted\", Ord = 2, Trend = becTrend),\r\n(print Count = toscalar(bec | summarize dcount(SenderFromDomain)), Details = \"Spoofed Sender Domains\", Ord = 3, Trend = becTrend),\r\n(print Count = toscalar(inbox | summarize count()), Details = \"Delivered to Inbox\", Ord = 4, Trend = inboxTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "leftContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 0, - "palette": "blue" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "secondaryContent": { - "columnMatch": "Trend", - "formatter": 21, - "formatOptions": { - "min": 0, - "palette": "blue" - } - }, - "showBorder": true, - "size": "auto" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "15" - }, - "name": "bec kpi strip", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "91fdd28f-31c4-4f94-b60a-12cd97d44ddf" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Phish Detections Business Email Compromise (BEC) detections\r\n
\r\n\r\nThis section consolidates key visuals that track and explain phish detections in inbound email as identified by Microsoft Defender for Office 365 focusing on Business Email Compromise (BEC) detections Impersonation and Spoof.

**Recommended action:** Enable mailbox intelligence and impersonation protection for frequently-impersonated users and domains; consider adding confirmed look-alike domains to the Tenant Block List." - }, - "name": "text - Phish BEC Banner", - "id": "e3b2232c-8056-4913-a652-64f70e228750" - }, - { - "type": 1, - "content": { - "json": "### Phish Detections - Impersonation detections Trend\r\n**Displays counts (per {Granularity}) of inbound emails flagged for Business Email Compromise (BEC) using Impersonation detection methods by Microsoft Defender for Office 365. Helps track impersonation attack patterns over time.**" - }, - "customWidth": "100", - "name": "text - Phish BEC Imp Trend Header", - "id": "e95667df-3bcd-4023-9e8f-99ed05bc4bf0" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Impersonation detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has 'Impersonation'\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ImpersonationDetections = coalesce(Count, 0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "areachart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "ImpersonationDetections", - "color": "blueDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - Phish BEC Imp Trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "61fa166d-f300-42a6-a324-de18b3fdf4c1" - }, - { - "type": 1, - "content": { - "json": "### Phish Detections - Impersonation detections by Detection Technology\r\n**Visualizes counts (per {Granularity}) of Phish detections of inbound emails by various Microsoft Defender for Office 365 detection technologies used for detecting Impersonations.**" - }, - "customWidth": "100", - "name": "text - Phish BEC Imp Tech Header", - "id": "09e1a866-f344-4a92-a3bd-8c3c3c5d598d" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Impersonation detections over time summarizing the data daily by various Impersonation Detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where Details has \"Impersonation\"\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - Phish BEC Imp Tech Trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "6cd5662f-13b4-4a9b-afe7-0a6343e3ab5c" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phish - Business Email Compromise (BEC) - Impersonation detections summarized by individual detection technology/control in Microsoft Defender for Office 365.\r\n//Each technique is counted individually via mv-expand over DetectionMethods.Phish (matching the sibling trend line chart), so a message flagged by multiple techniques counts once per technique.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where Details has \"Impersonation\"\r\n| summarize Count = count() by Details\r\n| sort by Count desc\r\n| project ['Detection Technology'] = Details, ['Detections'] = Count", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "graphSettings": { - "type": 0 - }, - "gridSettings": { - "formatters": [ - { - "columnMatch": "Detections", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - Phish BEC Imp Tech Pie", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "73499618-e842-440e-a555-cd8849093884" - }, - { - "type": 1, - "content": { - "json": "### Phish Detections - Impersonation detections by SenderIPv4 Geo Location\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Phish - Impersonation, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" - }, - "customWidth": "100", - "name": "text - Phish BEC Imp Geo Header", - "id": "189a1ac1-f275-4697-880b-7ffae1e5d263" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Impersonation detections summarizing the data by email sender IP address (SenderIPv4).\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Impersonation\" and isnotempty(SenderIPv4)\r\n//| project Timestamp, EmailDirection, SenderFromAddress, AdditionalFields, SenderIPv4 \r\n| summarize count()by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_ ", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "map", - "mapSettings": { - "locInfo": "LatLong", - "latitude": "Latitude", - "longitude": "Longitude", - "sizeSettings": "count_", - "sizeAggregation": "Sum", - "labelSettings": "SenderIPv4", - "legendMetric": "count_", - "legendAggregation": "Sum", - "itemColorSettings": { - "nodeColorField": "count_", - "colorAggregation": "Sum", - "type": "none" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - Phish BEC Imp Geo Map", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "574b61ad-ec2d-4517-93c5-d0e9bd14f2e9" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phish detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where DetectionMethods has \"Impersonation\" and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Impersonation Emails'] = count_\r\n| sort by ['Impersonation Emails'] desc", - "size": 0, - "showAnalytics": true, - "title": "Impersonation Detections-Sender Heatmap (IPv4)", - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Impersonation Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "50ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ] - }, - "mapSettings": { - "locInfo": "LatLong", - "latitude": "Latitude", - "longitude": "Longitude", - "sizeSettings": "count_", - "sizeAggregation": "Sum", - "labelSettings": "SenderIPv4", - "legendMetric": "count_", - "legendAggregation": "Sum", - "itemColorSettings": { - "nodeColorField": "count_", - "colorAggregation": "Sum", - "type": "heatmap", - "heatmapPalette": "red" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - Phish BEC Imp Country", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "e53b7dbc-4683-4309-b879-c7be68599159" - }, - { - "type": 1, - "content": { - "json": "### Phish Detections - Spoof detections Trend\r\n**Displays counts (per {Granularity}) of inbound emails flagged for Business Email Compromise (BEC) using Spoof detection methods by Microsoft Defender for Office 365. Helps track Spoofing based attack patterns over time.**" - }, - "customWidth": "100", - "name": "text - Phish BEC Spoof Trend Header", - "id": "8db0f1b0-49bf-43a2-9f9f-164eb9530629" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Spoof detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has 'Spoof'\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, SpoofDetections = coalesce(Count, 0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "areachart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "SpoofDetections", - "color": "blueDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - Phish BEC Spoof Trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "9a308cd9-bf05-4287-b0d5-54636d081a82" - }, - { - "type": 1, - "content": { - "json": "### Phish Detections - Spoof detections Trend by Detection Technology\r\n**Visualizes counts (per {Granularity}) of Phish detections of inbound emails by various Microsoft Defender for Office 365 detection technologies used for detecting Spoofing.**" - }, - "customWidth": "100", - "name": "text - Phish BEC Spoof Tech Header", - "id": "28c9c15d-d22f-4412-9efc-868b95082668" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Spoof detections over time summarizing the data daily by various Spoof Detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where Details has \"Spoof\"\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "chartSettings": { - "yAxis": [ - "Count" - ], - "seriesLabelSettings": [ - { - "seriesName": "[\"Spoof external domain\"]", - "color": "redDark" - }, - { - "seriesName": "[\"Spoof intra-org\"]", - "color": "orangeDark" - }, - { - "seriesName": "[\"Spoof DMARC\"]", - "color": "yellowDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - Phish BEC Spoof Tech Trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "1a1328fc-5404-4dff-99ed-3a30082a4cbe" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phish - Business Email Compromise (BEC) - Spoof detections summarized by individual detection technology/control in Microsoft Defender for Office 365.\r\n//Each technique is counted individually via mv-expand over DetectionMethods.Phish (matching the sibling trend line chart), so a message flagged by multiple techniques counts once per technique.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Phish\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where Details has \"Spoof\"\r\n| summarize Count = count() by Details\r\n| sort by Count desc\r\n| project ['Detection Technology'] = Details, ['Detections'] = Count", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Detections", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - Phish BEC Spoof Tech Pie", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "f7df9892-85b4-49c3-8739-873b745183a3" - }, - { - "type": 1, - "content": { - "json": "### Phish Detections - Spoof detections by SenderIPv4 Geo Location\r\n**Visualizes the email sending infrastructure sender IPv4 addresses associated with inbound emails detected as Phish - Spoofing, along with the IPv4 address geographic coordinates (latitude, longitude) and country information. Helps identify high-risk regions and sources for targeted threat mitigation.**" - }, - "customWidth": "100", - "name": "text - Phish BEC Spoof Geo Header", - "id": "3c83e7f0-5391-4b1a-bb5b-de0d17488efd" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phish – Business Email Compromise (BEC) – Spoof detections summarizing the data by email sender IP address (SenderIPv4).\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where DetectionMethods has \"Spoof\" and isnotempty(SenderIPv4)\r\n//| project Timestamp, EmailDirection, SenderFromAddress, AdditionalFields, SenderIPv4 \r\n| summarize count()by SenderIPv4\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Latitude = tostring(GeoInfo.latitude), Longitude = tostring(GeoInfo.longitude)\r\n| project SenderIPv4, Latitude, Longitude, count_ ", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "map", - "mapSettings": { - "locInfo": "LatLong", - "latitude": "Latitude", - "longitude": "Longitude", - "sizeSettings": "count_", - "sizeAggregation": "Sum", - "labelSettings": "SenderIPv4", - "legendMetric": "count_", - "legendAggregation": "Sum", - "itemColorSettings": { - "nodeColorField": "count_", - "colorAggregation": "Sum", - "type": "none" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - Phish BEC Spoof Geo Map", - "styleSettings": { - "margin": "15px", - "padding": "15px" - }, - "id": "122d860c-ab0d-475e-b29e-2955020680c7" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phish detections summarizing the data by email sender IP address and IP address country information (SenderIPv4).\r\nEmailEvents \r\n| where DetectionMethods has \"Spoof\" and isnotempty(SenderIPv4)\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend GeoInfo = geo_info_from_ip_address(SenderIPv4)\r\n| extend Country = tostring(GeoInfo.country)\r\n| summarize count() by Country\r\n| project Country, ['Spoof Emails'] = count_\r\n| sort by ['Spoof Emails'] desc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Spoof Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ] - }, - "mapSettings": { - "locInfo": "LatLong", - "latitude": "Latitude", - "longitude": "Longitude", - "sizeSettings": "count_", - "sizeAggregation": "Sum", - "labelSettings": "SenderIPv4", - "legendMetric": "count_", - "legendAggregation": "Sum", - "itemColorSettings": { - "nodeColorField": "count_", - "colorAggregation": "Sum", - "type": "heatmap", - "heatmapPalette": "red" - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - Phish BEC Spoof Country", - "styleSettings": { - "margin": "15px", - "padding": "15px" - }, - "id": "9d0111bc-8d01-4a99-9009-645dc02c3bed" - }, - { - "type": 1, - "content": { - "json": "### Supply-Chain & Partner Risk (Possible Partner Compromise)\r\n**Correlates the external domains your organization emails most with inbound emails from those same domains that carried threats. A trusted partner or supplier domain suddenly sending threats is a strong signal that the partner may be compromised - a common supply-chain and business email compromise (BEC) vector.**

**Recommended action:** Verify any flagged partner through a trusted channel before acting on their recent messages, alert them to a possible compromise, and consider tightening inbound policy for that domain until confirmed clean." - }, - "customWidth": "100", - "name": "text - Phish Partner Compromise Header", - "id": "2c62c576-3b05-4663-ae2e-4f961d7409c6" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises top outbound recipient domains by outbound email volume and shows total number of inbound emails with Threats from the same domains (as inbound senders) \r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Outbound\"\r\n| project RecipientDomain = tostring(split(RecipientEmailAddress, \"@\")[1])\r\n| summarize count() by RecipientDomain\r\n| project OutboundCount=count_, RecipientDomain, SenderFromDomain=RecipientDomain\r\n| join (EmailEvents | where EmailDirection == \"Inbound\" and isempty(ThreatTypes)==false) on SenderFromDomain\r\n| summarize max(OutboundCount),count() by SenderFromDomain\r\n| project SenderFromDomain, OutboundEmails=max_OutboundCount, IncomingEmailsWithThreats=count_\r\n| extend Bad_Traffic_Percentage = todouble(round(IncomingEmailsWithThreats / todouble(OutboundEmails) * 100, 2))\r\n| top 15 by OutboundEmails\r\n| project ['Sender Domain'] = SenderFromDomain, ['Outbound Emails'] = OutboundEmails, ['Inbound w/ Threats'] = IncomingEmailsWithThreats, ['Bad Traffic %'] = Bad_Traffic_Percentage", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Outbound Emails", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Inbound w/ Threats", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "60ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Bad Traffic %", - "formatter": 4, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - }, - "formatOptions": { - "palette": "red", - "min": 0, - "max": 20 - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - Phish Partner Compromise", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "1aaa047c-1108-4288-833e-61ca35b5495a" - }, - { - "type": 1, - "content": { - "json": "### Top Recipients Targeted by Impersonation / BEC\r\n**Lists the recipients most frequently targeted by impersonation and Business Email Compromise (BEC) attempts, showing the number of impersonation emails, how many distinct senders were involved, the top spoofed sender domains, and how many of those messages were delivered to the inbox. Helps identify high-risk users (often executives or finance staff) who may need extra protection or awareness.**" - }, - "customWidth": "100", - "name": "text - impersonation targets", - "id": "b1e7c2a4-9f3d-4a6b-8c12-7d5e9f0a1b23" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Top recipients targeted by impersonation / BEC, with distinct senders, spoofed domains and how many landed in the inbox.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| where OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")\r\n| where DetectionMethods has \"Impersonation\"\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize ImpersonationEmails = count(),\r\n DistinctSenders = dcount(SenderFromAddress),\r\n TopSpoofedDomains = make_set(SenderFromDomain, 5),\r\n DeliveredToInbox = countif(DeliveryLocation has \"Inbox\")\r\n by RecipientEmailAddress\r\n| top 20 by ImpersonationEmails\r\n| project ['Recipient'] = RecipientEmailAddress, ['Impersonation Emails'] = ImpersonationEmails, ['Distinct Senders'] = DistinctSenders, ['Top Spoofed Domains'] = strcat_array(TopSpoofedDomains, \", \"), ['Delivered to Inbox'] = DeliveredToInbox", - "size": 0, - "title": "Top Recipients Targeted by Impersonation / BEC", - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "showAnalytics": true, - "gridSettings": { - "formatters": [ - { - "columnMatch": "Impersonation Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "15" - }, - "name": "newviz - impersonation targets", - "id": "afe28369-af82-47ae-846d-179bd86b660e" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "15" - }, - "name": "group - 7 - Phish-BEC-Insights", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "b7971cd9-d086-47c7-8f66-50956b9c56c3" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Phish Detections Sender Authentication details (DMARC, DKIM, SPF, CompAuth)\r\n
\r\n\r\nThis section consolidates key visuals that track and explain Sender Authentication checks details in inbound email by Microsoft Defender for Office 365 focusing on the various Sender Authentication standards: DMARC, DKIM, SPF, CompAuth.

**Recommended action:** For domains failing DMARC/DKIM/SPF, verify your own outbound authentication is published and enforced (p=reject), and treat persistent external spoofers as possible block candidates." - }, - "name": "text - Phish Section5 Banner", - "id": "90d7a338-d943-4398-b788-bfd4f93007d4" - }, - { - "type": 1, - "content": { - "json": "### Phish Detections Sender Authentication Trend (DMARC, DKIM, SPF, CompAuth)\r\n**Shows counts (per {Granularity}) of sender authentication check outcomes (DMARC, DKIM, SPF, CompAuth) performed by Microsoft Defender for Office 365 on inbound emails. Useful for monitoring authentication success and failure patterns over time to identify anomalies or potential phishing risks.**" - }, - "customWidth": "100", - "name": "text - Phish SenderAuth Trend Header", - "id": "4a0ab90e-55dd-4fa6-82c3-0edc57ce0966" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Spoof- DMARC fails summarizing the data daily.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend DMARCFail = (tostring(parse_json(AuthenticationDetails).DMARC) == \"fail\") \r\n| summarize DMARCFail = sum(DMARCFail) by bin (Timestamp,{Granularity})", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "DMARCFail", - "color": "orangeDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - Phish Auth DMARC Trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "79920d30-01d4-4412-b994-853e50c9d7d8" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Spoof- DKIM fails summarizing the data daily.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend DKIMFail = (tostring(parse_json(AuthenticationDetails).DKIM) == \"fail\") \r\n| summarize DKIMFail = sum(DKIMFail) by bin (Timestamp,{Granularity})", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "DKIMFail", - "color": "yellowDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - Phish Auth DKIM Trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "bf09ffd4-eee0-42f7-a507-1cf54d9c365a" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Spoof- SPF fails summarizing the data daily.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend SPFFail = (tostring(parse_json(AuthenticationDetails).SPF) == \"fail\") \r\n| summarize SPFFail = sum(SPFFail) by bin (Timestamp,{Granularity})", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "SPFFail", - "color": "purpleDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - Phish Auth SPF Trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "4d66fe13-9904-45cf-8783-f3ee984f3a66" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Spoof- Composite Authentication fails summarizing the data daily.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend CompAuthFail = (tostring(parse_json(AuthenticationDetails).CompAuth) == \"fail\") \r\n| summarize CompAuthFail = sum(CompAuthFail) by bin (Timestamp,{Granularity})", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "CompAuthFail", - "color": "blueDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - Phish Auth CompAuth Trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "0968b828-23fe-4fa2-a5ea-8ab39362457f" - }, - { - "type": 1, - "content": { - "json": "### Phish Detections Top Sender Domains with DMARC Failures (Inbound)\r\n**Displays the top 10 sender domains (P1 and P2) for inbound emails where Spoof-DMARC detection triggered. Includes total inbound email volume and calculates DMARC fail traffic percentage per domain to highlight high-risk sources.**" - }, - "customWidth": "100", - "name": "text - Phish Auth DMARC Domains Header", - "id": "24d4689a-eb6d-49f5-85a8-fcadca409f7a" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Spoof-DMARC fails detections summarizing the data by the top 10 email sender P2 domain (SenderFromDomain) and sender P1 domain (SenderMailFromDomain). Adding additional insights for total inbound emails and DMARC fail traffic percentage for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalEmailCount = count(),\r\n DMARCFailCount = countif(set_has_element(parse_json(DetectionMethods).Phish, \"Spoof DMARC\")) by P1Sender=SenderMailFromDomain, P2Sender=SenderFromDomain\r\n| extend DMARCFail_Traffic_Percentage = todouble(round(DMARCFailCount / todouble(TotalEmailCount) * 100, 2))\r\n| where DMARCFailCount !=0\r\n| top 10 by DMARCFailCount\r\n| project ['P1 Sender'] = P1Sender, ['P2 Sender'] = P2Sender, ['DMARC Failures'] = DMARCFailCount, ['Total Inbound'] = TotalEmailCount, ['DMARC Fail %'] = DMARCFail_Traffic_Percentage", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "DMARCFail", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Total Inbound", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "DMARC Fail %", - "formatter": 4, - "formatOptions": { - "customColumnWidthSetting": "40ch", - "palette": "red", - "min": 0, - "max": 20 - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - Phish Auth DMARC Domains", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "642814ad-9d24-4be9-ae10-3578e89da05b" - }, - { - "type": 1, - "content": { - "json": "### Phish Detections Top Sender Domains with Spoof External Domain Detections (Inbound)\r\n**Displays the top 10 sender domains (P1 and P2) for inbound emails flagged for Spoof External Domain detection. Includes total inbound email volume and calculates spoof traffic percentage per domain to highlight high-risk sources.**" - }, - "customWidth": "100", - "name": "text - Phish Auth SpoofExt Domains Header", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "993fdc34-354b-412e-be39-facbde4f4f0e" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phish-Spoof-external domain detections summarizing the data by the top 10 email sender P2 domain (SenderFromDomain) and sender P1 domain (SenderMailFromDomain). Adding additional insights for total inbound emails and Spoof external domain detection traffic percentage for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalEmailCount = count(),\r\n SpoofExternalCount = countif(set_has_element(parse_json(DetectionMethods).Phish, \"Spoof external domain\")) by P1Sender=SenderMailFromDomain, P2Sender=SenderFromDomain\r\n| extend SpoofExternal_Traffic_Percentage = todouble(round(SpoofExternalCount / todouble(TotalEmailCount) * 100, 2))\r\n| where SpoofExternalCount !=0\r\n| top 10 by SpoofExternalCount\r\n| project ['P1 Sender'] = P1Sender, ['P2 Sender'] = P2Sender, ['Spoof External'] = SpoofExternalCount, ['Total Inbound'] = TotalEmailCount, ['Spoof External %'] = SpoofExternal_Traffic_Percentage", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Spoof External", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Total Inbound", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Spoof External %", - "formatter": 4, - "formatOptions": { - "customColumnWidthSetting": "40ch", - "palette": "red", - "min": 0, - "max": 20 - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "SpoofExternalFail", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true, - "sortBy": [ - { - "itemKey": "Spoof External %", - "sortOrder": 2 - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - Phish Auth SpoofExt Domains", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "69ca3799-d2d5-4896-b3a5-1eeba46f0b46" - }, - { - "type": 1, - "content": { - "json": "### Phish Detections Top Sender Domains with Spoof Internal Domain Detections (Inbound)\r\n**Displays the top 10 sender domains (P1 and P2) for inbound emails flagged for Spoof Internal Domain detection. Includes total inbound email volume and calculates spoof traffic percentage per domain to highlight high-risk sources.**" - }, - "customWidth": "100", - "name": "text - Phish Auth SpoofInt Domains Header", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "3fa33c5d-0eba-471f-b47f-0c12c1f770d6" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phish-Spoof-internal domain detections summarizing the data by the top 10 email sender P2 domain (SenderFromDomain) and sender P1 domain (SenderMailFromDomain). Adding additional insights for total inbound emails and Spoof internal domain detection traffic percentage for each sender domain.\r\nEmailEvents\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalEmailCount = count(),\r\n SpoofInternalCount = countif(set_has_element(parse_json(DetectionMethods).Phish, \"Spoof intra-org\")) by P1Sender=SenderMailFromDomain, P2Sender=SenderFromDomain\r\n| extend SpoofInternal_Traffic_Percentage = todouble(round(SpoofInternalCount / todouble(TotalEmailCount) * 100, 2))\r\n| where SpoofInternalCount !=0\r\n| top 10 by SpoofInternalCount\r\n| project ['P1 Sender'] = P1Sender, ['P2 Sender'] = P2Sender, ['Spoof Internal'] = SpoofInternalCount, ['Total Inbound'] = TotalEmailCount, ['Spoof Internal %'] = SpoofInternal_Traffic_Percentage", - "size": 3, - "showAnalytics": true, - "title": "Top 10 Spoof intra-org detections by Sender domain (P1/P2)", - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Spoof Internal", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Total Inbound", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Spoof Internal %", - "formatter": 4, - "formatOptions": { - "customColumnWidthSetting": "40ch", - "palette": "red", - "min": 0, - "max": 20 - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "SpoofIntraorgFail", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - Phish Auth SpoofInt Domains", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "ae0c65c7-68ea-4d50-b177-1effeaf1c045" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "15" - }, - "name": "group - 8-Phish-SenderAuth", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "8077779a-4da8-46be-8032-626bd8c36dbd" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
First-Contact & New-Vendor Senders\r\n
\r\n\r\nExternal email senders and domains seen for the first time in the selected period. New/first-contact relationships - especially ones already carrying threats - are a common precursor to phishing, business email compromise (BEC), and supply-chain attacks.

**Recommended action:** Treat brand-new domains sending threats as high-priority review; verify any that claim to be a known brand or partner before trusting their messages." - }, - "name": "phish fc banner", - "id": "05b83435-c7ed-48a3-919e-388b2e599726" - }, - { - "type": 1, - "content": { - "json": "### First-contact external senders
\r\n\r\n**External email senders ordered by when they were first seen in the period (most recent first). In tenants with longer history this highlights genuinely new senders.**" - }, - "customWidth": "100", - "name": "phish fc senders header", - "styleSettings": { - "margin": "10px", - "padding": "0px" - }, - "id": "c57dffb4-dfdb-4a1e-93be-16fa9e856a0d" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query lists external email senders seen for the first time in the selected period (most recent first), surfacing new/first-contact senders. In tenants with longer history this highlights genuinely new relationships - a common precursor to BEC and supply-chain attacks.\r\n// TIP: to hide your own accepted domains, uncomment the ExcludeDomains line and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"fabrikam.com\"]);\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| extend SenderDomain = tostring(split(SenderFromAddress, \"@\")[1])\r\n| where isnotempty(SenderFromAddress)\r\n//| where SenderDomain !in~ (ExcludeDomains)\r\n| summarize FirstSeen=min(Timestamp), Messages=count(), ThreatMessages=countif(isnotempty(ThreatTypes)) by SenderFromAddress, SenderDomain\r\n| top 20 by FirstSeen desc\r\n| project ['Sender']=SenderFromAddress, ['Sender Domain']=SenderDomain, ['First Seen']=FirstSeen, Messages, ['Threat Messages']=ThreatMessages", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true, - "formatters": [ - { - "columnMatch": "Messages", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Threat Messages", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "phish fc senders table", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "d1ceb0ac-2dad-49af-b416-a3376a7b8513" - }, - { - "type": 1, - "content": { - "json": "### New sender domains carrying threats
\r\n\r\n**External sender domains seen for the first time in the period that already carried threats, most-recent first. A brand-new domain sending threats to your users is a strong early-warning signal.**" - }, - "customWidth": "100", - "name": "phish fc domains header", - "styleSettings": { - "margin": "10px", - "padding": "0px" - }, - "id": "bd29bbe4-cde2-499c-a1d0-e2cc51f7733d" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query lists external sender domains seen for the first time in the selected period that already carried threats, ranked by most-recently first seen. A brand-new domain sending threats to your users is a strong early-warning signal for phishing and BEC.\r\n// TIP: to hide your own accepted domains, uncomment the ExcludeDomains line and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"fabrikam.com\"]);\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| extend SenderDomain = tostring(split(SenderFromAddress, \"@\")[1])\r\n| where isnotempty(SenderDomain)\r\n//| where SenderDomain !in~ (ExcludeDomains)\r\n| summarize FirstSeen=min(Timestamp), LastSeen=max(Timestamp), Messages=count(), Senders=dcount(SenderFromAddress), Recipients=dcount(RecipientEmailAddress), ThreatMessages=countif(isnotempty(ThreatTypes)) by SenderDomain\r\n| where ThreatMessages > 0\r\n| top 20 by FirstSeen desc\r\n| project ['Sender Domain']=SenderDomain, ['First Seen']=FirstSeen, Messages, Senders, Recipients, ['Threat Messages']=ThreatMessages, ['Last Seen']=LastSeen", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true, - "formatters": [ - { - "columnMatch": "Messages", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Senders", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Recipients", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Threat Messages", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "phish fc domains table", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "7da952d5-5ae2-4b2e-a5cf-c78b11bda4f8" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "15" - }, - "customWidth": "100", - "name": "group - Phish First Contact", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "90e5248a-2c35-48f3-869c-c45c631c6fbf" - }, - { - "type": 1, - "content": { - "json": "# URL Detections and URL Click Insights\r\n\r\n---\r\nThis tab provides insights into **URL-based detections** in email messages and details about URL clicks performed by end users on URLs identified as **malicious**." - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "5" - }, - "name": "text - 24 - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "2156430d-fec6-48bb-a9a8-3166182f6993" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//KPI summary of URL threat protection (Safe Links clicks and URLs seen in email) for the selected period, with a per-period Trend series feeding each tile sparkline.\r\nlet gran = {Granularity};\r\nlet clicks = UrlClickEvents;\r\nlet blocked = clicks | where ActionType in (\"ClickBlocked\",\"ClickBlockedByTenantPolicy\");\r\nlet allowed = clicks | where ActionType == \"ClickAllowed\";\r\nlet blockedTrend = toscalar(blocked | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet allowedTrend = toscalar(allowed | make-series Trend = count() default = 0 on Timestamp step gran | project Trend);\r\nlet usersTrend = toscalar(clicks | make-series Trend = dcount(AccountUpn) default = 0 on Timestamp step gran | project Trend);\r\nlet urlsTrend = toscalar(EmailUrlInfo | make-series Trend = dcount(Url) default = 0 on Timestamp step gran | project Trend);\r\nunion\r\n(print Count = toscalar(blocked | summarize count()), Details = \"Malicious Clicks Blocked\", Ord = 1, Trend = blockedTrend),\r\n(print Count = toscalar(allowed | summarize count()), Details = \"Clicks Allowed Through\", Ord = 2, Trend = allowedTrend),\r\n(print Count = toscalar(clicks | summarize dcount(AccountUpn)), Details = \"Users Clicking Links\", Ord = 3, Trend = usersTrend),\r\n(print Count = toscalar(EmailUrlInfo | summarize dcount(Url)), Details = \"Distinct URLs in Email\", Ord = 4, Trend = urlsTrend)\r\n| sort by Ord asc\r\n| project Count, Details, Trend", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "leftContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 0, - "palette": "blue" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "secondaryContent": { - "columnMatch": "Trend", - "formatter": 21, - "formatOptions": { - "min": 0, - "palette": "blue" - } - }, - "showBorder": true, - "size": "auto" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "5" - }, - "name": "url kpi strip", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "d5e2326a-a5dd-4217-bb75-0e337d75d306" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Insights on URL-Based Threat Detections\r\n
\r\n\r\nThis section consolidates key visuals that track and explain URL based threat detections in inbound email as identified by Microsoft Defender for Office 365 focusing on per-{Granularity} trends of URL-based threat detections, QR code detections, and URL scans activity by locations.

**Recommended action:** Confirm Safe Links is enabled for email and Teams; investigate QR-code and URL detection spikes for emerging campaigns." - }, - "name": "text - 13 - Copy", - "id": "ed3468e7-1936-45fd-9168-93010a662302" - }, - { - "type": 1, - "content": { - "json": "### Trend of URL-Based Malware Threat Detections
\r\n\r\n**This visual displays a per-{Granularity} trend of emails with URL based Malware threat detections identified by Microsoft Defender for Office 365. The line chart summarises the number of messages flagged for malware threats.**" - }, - "name": "text - 13 - Copy - Copy", - "id": "77e7bbac-d752-478b-bce9-06bb1bd12bfe" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Malware detections over time summarizing the data daily by various Malware URL threat based detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Malware'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand MalwareMethod = ParsedMethods.Malware\r\n| where MalwareMethod contains \"URL\"\r\n| summarize Count = count() by MalwareMethod = tostring(MalwareMethod), Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct MalwareMethod | extend d = 1) on d | project Timestamp, MalwareMethod\r\n| join kind=leftouter (agg) on Timestamp, MalwareMethod\r\n| project Timestamp, MalwareMethod, Count = coalesce(Count, 0)\r\n| sort by MalwareMethod asc, Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - 8 - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "79ef5e7b-57a6-4519-9899-18fd8cae5e68" - }, - { - "type": 1, - "content": { - "json": "### Trend of URL-Based Phish Threat Detections
\r\n\r\n**This visual displays a per-{Granularity} trend of emails with URL based Phish threat detections identified by Microsoft Defender for Office 365. The line chart summarises the number of messages flagged for Phish threats.**" - }, - "name": "text - 13 - Copy - Copy - Copy", - "id": "48923812-5440-4f47-8881-273f14cbfb8e" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total emails with Phishing detections over time summarizing the data daily by various Phishing URL threat based detection technologies/controls in Microsoft Defender for Office 365.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has 'Phish'\r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ParsedMethods = parse_json(DetectionMethods)\r\n| mv-expand PhishMethod = ParsedMethods.Phish\r\n| where PhishMethod contains \"URL\"\r\n| summarize Count = count() by PhishMethod = tostring(PhishMethod), Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct PhishMethod | extend d = 1) on d | project Timestamp, PhishMethod\r\n| join kind=leftouter (agg) on Timestamp, PhishMethod\r\n| project Timestamp, PhishMethod, Count = coalesce(Count, 0)\r\n| sort by PhishMethod asc, Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - 8 - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "b983b361-6c2e-47d5-b2c5-edd9caa6a55d" - }, - { - "type": 1, - "content": { - "json": "### Trend (per {Granularity}) of QR Code-Based Threat Detections
\r\n\r\n**Displays counts (per {Granularity}) of inbound emails containing QR codes flagged for Phish, Malware, or Spam via URL-based detection methods. Helps track QR code abuse patterns over time.**" - }, - "customWidth": "50", - "name": "text - 13 - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "3d8b75e1-6e1d-44eb-b1fc-78d3db7feb71" - }, - { - "type": 1, - "content": { - "json": "### URL Scan activity by Location (per {Granularity})
\r\n\r\n**Displays counts (per {Granularity}) of URLs scanned from various locations within emails (e.g., body, attachments, QR codes). Helps identify where malicious URLs are most commonly embedded.**" - }, - "customWidth": "50", - "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "b275b28c-e441-4c19-9055-256d5d45c69c" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "let gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where EmailDirection == \"Inbound\" \r\n| where DetectionMethods has \"Url\"\r\n| join EmailUrlInfo on NetworkMessageId\r\n| where UrlLocation == \"QRCode\"\r\n| summarize [\"Phish QR Detection\"]=countif(parse_json(DetectionMethods).Phish has \"URL\"), [\"Malware QR Detection\"]=countif(parse_json(DetectionMethods).Malware has \"URL\"), [\"Spam QR Detection\"]=countif(parse_json(DetectionMethods).Spam has \"URL\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, [\"Phish QR Detection\"]=coalesce([\"Phish QR Detection\"],0), [\"Malware QR Detection\"]=coalesce([\"Malware QR Detection\"],0), [\"Spam QR Detection\"]=coalesce([\"Spam QR Detection\"],0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "graphSettings": { - "type": 0 - }, - "chartSettings": { - "xAxis": "Timestamp", - "xSettings": { - "dateFormatSettings": { - "formatName": "shortDatePattern", - "showUtcTime": false - } - } - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 6", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "6c2a7724-d3c2-42b2-b8da-7acbcd0666c6" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises where URL's have been scanned identified from various locations in emails\r\nEmailUrlInfo\r\n| summarize count() by UrlLocation", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 5", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "5640dbd5-4085-4f2a-8fb9-e4112233e99e" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "5" - }, - "name": "group - 9-URL detections", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "b572d79b-17a0-48ac-9a43-4f20324cf998" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Insights on URL Click-Based Threat Detections\r\n
\r\n\r\nThis section consolidates key visuals that track and explain URL click based threat detections in emails as identified by Microsoft Defender for Office 365 focusing on per-{Granularity} trend of blocked URL clicks, time-of-click URL scans by workload, malicious clicks allowed, top clicks on malicious URLs, and more.

**Recommended action:** For blocked-click spikes, verify Safe Links is set to not allow click-through; investigate workloads with high click-through activity." - }, - "name": "text - 13 - Copy - Copy", - "id": "6d37617e-911e-4ce6-a10d-4749486738ea" - }, - { - "type": 1, - "content": { - "json": "### Trend (per {Granularity}) of Blocked URL Click Events
\r\n\r\n**Shows the count (per {Granularity}) of blocked URL click attempts and click attempts on URLs with detections, grouped by threat types (e.g., Phish, Malware, Spam). Helps track user interaction with malicious links over time across various threat types.**" - }, - "name": "text - 13 - Copy - Copy - Copy", - "id": "9e477950-bedc-4cc0-9863-df07d124806c" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "// Generates a time-series analysis for blocked URL click events from the 'UrlClickEvents' table\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(UrlClickEvents\r\n| where isnotempty(ActionType)\r\n| where ActionType has_any(\"ClickBlocked\")\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, BlockedClicks = coalesce(Count, 0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "areachart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "BlockedClicks", - "color": "blueDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "66", - "name": "query - 4", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "366e80d9-f6ed-43af-91e5-3d04cdcf692d" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the total ammount of click attempts on URL's with detections split by the different threat types identified\r\nUrlClickEvents\r\n| where isnotempty(ThreatTypes)\r\n| summarize count() by ThreatTypes", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "33", - "name": "query - 4", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "a356eac3-62c2-4fc9-a4d9-3b05b13848df" - }, - { - "type": 1, - "content": { - "json": "### Trend (per {Granularity}) of URL Click Actions by Type
\r\n\r\n**Displays counts (per {Granularity}) of URL click events categorised by action type: Blocked, Allowed, Pending Verdict, Error Page, and Clicked Through. Helps identify risky user behaviour and policy gaps.**" - }, - "customWidth": "66", - "name": "text - 13 - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "a91fe7a6-f507-48f7-bbcc-61dc4f998ba6" - }, - { - "type": 1, - "content": { - "json": "### URL Clicks by Workload
\r\n\r\n**Displays counts (per {Granularity}) of URL click events grouped by Workload (e.g., Outlook, Teams, Copilot, Office Apps: Word, Excel, PowerPoint) Helps identify which applications are most frequently used for URL interactions and potential risk exposure.**" - }, - "customWidth": "33", - "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "ce05fa08-6e68-4c02-a0bf-2be6cdfae935" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises different URL click event types by action (e.g., blocked, allowed, pending verdict, error pages, and clicked through), summarizing the data daily\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(UrlClickEvents\r\n| where isnotempty(ActionType)\r\n| summarize ClickBlocked=countif(ActionType has_any(\"ClickBlocked\")), ClickAllowed=countif(ActionType has_any(\"ClickAllowed\")), PendingVerdict=countif(ActionType has_any(\"UrlScanInProgress\")), ErrorPage=countif(ActionType has_any(\"UrlErrorPage\")), ClickedThrough=countif(IsClickedThrough == true) by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ClickBlocked=coalesce(ClickBlocked,0), ClickAllowed=coalesce(ClickAllowed,0), PendingVerdict=coalesce(PendingVerdict,0), ErrorPage=coalesce(ErrorPage,0), ClickedThrough=coalesce(ClickedThrough,0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "chartSettings": { - "xAxis": "Timestamp" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "66", - "name": "query - 1", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "a12b4c78-7d18-4adc-86e0-54395d6a996a" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises where URL clicks scanned by the Workload the click happened from\r\nUrlClickEvents\r\n| summarize count() by Workload", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "33", - "name": "query - 5 - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "3237cd55-1d5c-41a9-a8f2-1d46c61a709e" - }, - { - "type": 1, - "content": { - "json": "### Blocked URL Clicks by Workload (per {Granularity})
\r\n\r\n**Displays counts (per {Granularity}) of blocked URL click attempts grouped by Workload (Email, Teams, Office, Microsoft 365 Copilot). Helps identify which platforms are most exposed to malicious link interactions and where user awareness or policy enforcement should be strengthened.**" - }, - "customWidth": "66", - "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "1f209a83-3d50-4bb8-9a79-a365a50a4142" - }, - { - "type": 1, - "content": { - "json": "### Click-Through Activity on Detected URLs by Workload
\r\n\r\n**Displays counts of click‑through actions on URLs already identified with detections, grouped by Workload where the click happened. Helps identify clients/platforms where users are most likely to proceed to risky URLs and prioritise awareness training or policy tuning for those workloads**" - }, - "customWidth": "33", - "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "33592db8-0ff5-4d8e-bd8f-0201b81a4584" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises blocked URL click event types by Workload (e.g., Email, Teams, Office, Microsoft 365 Copilot), summarizing the data daily\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(UrlClickEvents\r\n| where ActionType ==\"ClickBlocked\"\r\n| summarize Teams=countif(Workload==\"Teams\"), Office=countif(Workload==\"Office\"), Email=countif(Workload==\"Email\"), Copilot=countif(Workload==\"Copilot\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, Teams=coalesce(Teams,0), Office=coalesce(Office,0), Email=coalesce(Email,0), Copilot=coalesce(Copilot,0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "66", - "name": "query - 3", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "80241767-0f69-4e2e-9889-3bf1f48e4f02" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the total ammount of click-through activities on URL's with detections split by the source client\r\nUrlClickEvents \r\n| where IsClickedThrough !=\"0\"\r\n| where isnotempty(ThreatTypes) \r\n| summarize count() by Workload", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "33", - "name": "query - 2", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "fde29b46-2896-4bfc-bb61-09436696d738" - }, - { - "type": 1, - "content": { - "json": "### Top clicks on Malicious URLs
\r\n\r\n**Displays the top 20 URLs associated with detections that registered the highest number of clicks. Includes ThreatTypes, ActionType, and Workload to provide context on the nature of the threat and where user interaction occurred.**" - }, - "customWidth": "100", - "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "22bda63a-626c-47de-9a76-ad665ef87862" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query shows the top 20 URL's that have a detection associated with the most ammount of clicks registered \r\nUrlClickEvents\r\n| where ThreatTypes !=\"\"\r\n| summarize count() by Url, ThreatTypes, ActionType, Workload\r\n| top 20 by count_\r\n| project ['URL']=Url, ['Threat Types']=ThreatTypes, ['Action Type']=ActionType, Workload, ['Click Count']=count_", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Click Count", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "50ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - 10 - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "a044fd4e-7be6-4a11-974c-b54e417c2a81" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "5" - }, - "name": "group - 31-URL clicks", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "75e543f6-08c0-42ed-9869-ecd61b721d34" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Top Risky Users Clicking on URLs with Threats\r\n
\r\n\r\nThis section consolidates key visuals that track and identify users who have clicked on malicious URLs detected by Microsoft Defender for Office 365.

**Recommended action:** Enroll these users in security awareness training and verify Safe Links policy coverage for their mailboxes." - }, - "name": "text - 13 - Copy - Copy - Copy", - "id": "19487811-a94b-4537-877e-61ac7e287c21" - }, - { - "type": 1, - "content": { - "json": "### Top 10 Users Clicking on URLs with Malware Threat
\r\n\r\n**Displays the top 10 user accounts with the highest number of click attempts on URLs flagged as Malware. Helps identify individuals at greater risk and prioritise targeted security awareness training.**" - }, - "customWidth": "100", - "name": "text - 13 - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "78e10621-0e98-44c4-8399-810c19f138c2" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the top 10 users with click attempts on URL's with malware detections\r\nUrlClickEvents\r\n| summarize TotalClickCount=count(),MalwareClickCount = countif(ThreatTypes has \"Malware\") by AccountUpn\r\n| extend Bad_Click_Percentage = todouble(round(MalwareClickCount / todouble(TotalClickCount) *100, 2))\r\n| where MalwareClickCount !=0\r\n| sort by MalwareClickCount desc\r\n| top 15 by MalwareClickCount\r\n| project ['User']=AccountUpn, ['Malware Clicks']=MalwareClickCount, ['Total Clicks']=TotalClickCount, ['Bad Click %']=Bad_Click_Percentage", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Malware Clicks", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "25ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Total Clicks", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "20ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Bad Click %", - "formatter": 4, - "formatOptions": { - "customColumnWidthSetting": "25ch", - "palette": "red", - "min": 0, - "max": 20 - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "MalwareEmailCount", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "TotalEmailCount", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Bad_Traffic_Percentage_Inbound", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "50ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "count_", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "50ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "sortBy": [], - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - 18 - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "a7ae8a75-ca7f-49be-8cad-d1451a3bd396" - }, - { - "type": 1, - "content": { - "json": "### Top 10 Users Clicking on URLs with Phish Threat
\r\n\r\n**Displays the top 10 user accounts with the highest number of click attempts on URLs flagged as Phish. Helps identify individuals at greater risk and prioritise targeted security awareness training.**" - }, - "customWidth": "100", - "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "90d9a0c3-970a-4998-be62-3b3b84bb0f37" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the top 10 users with click attempts on URL's with Phish detections\r\nUrlClickEvents\r\n| summarize TotalClickCount=count(),PhishClickCount = countif(ThreatTypes has \"Phish\") by AccountUpn\r\n| extend Bad_Click_Percentage = todouble(round(PhishClickCount / todouble(TotalClickCount) *100, 2))\r\n| where PhishClickCount !=0\r\n| sort by PhishClickCount desc\r\n| top 15 by PhishClickCount\r\n| project ['User']=AccountUpn, ['Phish Clicks']=PhishClickCount, ['Total Clicks']=TotalClickCount, ['Bad Click %']=Bad_Click_Percentage", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Phish Clicks", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "25ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Total Clicks", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "20ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Bad Click %", - "formatter": 4, - "formatOptions": { - "customColumnWidthSetting": "25ch", - "palette": "red", - "min": 0, - "max": 20 - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "MalwareClickCount", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "MalwareEmailCount", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "TotalEmailCount", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Bad_Traffic_Percentage_Inbound", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "50ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "count_", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "50ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "sortBy": [], - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - 18 - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "d46877d9-03af-463a-b406-bb4c601dffeb" - }, - { - "type": 1, - "content": { - "json": "### Top 10 Users Clicking on URLs with Spam Threat
\r\n\r\n**Displays the top 10 user accounts with the highest number of click attempts on URLs flagged as Spam. Helps identify individuals at greater risk and prioritise targeted security awareness training.**" - }, - "customWidth": "100", - "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "dc66e020-0932-4346-8e20-6a2dc78de7a9" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the top 10 users with click attempts on URL's with Spam detections\r\nUrlClickEvents\r\n| summarize TotalClickCount=count(),SpamClickCount = countif(ThreatTypes has \"Spam\") by AccountUpn\r\n| extend Bad_Click_Percentage = todouble(round(SpamClickCount / todouble(TotalClickCount) *100, 2))\r\n| where SpamClickCount !=0\r\n| sort by SpamClickCount desc\r\n| top 15 by SpamClickCount\r\n| project ['User']=AccountUpn, ['Spam Clicks']=SpamClickCount, ['Total Clicks']=TotalClickCount, ['Bad Click %']=Bad_Click_Percentage", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Spam Clicks", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "25ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Total Clicks", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "20ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Bad Click %", - "formatter": 4, - "formatOptions": { - "customColumnWidthSetting": "25ch", - "palette": "red", - "min": 0, - "max": 20 - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "PhishClickCount", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "MalwareClickCount", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "MalwareEmailCount", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "TotalEmailCount", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Bad_Traffic_Percentage_Inbound", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "50ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "count_", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "50ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "sortBy": [], - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - 18 - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "734ee45e-4dff-4ca1-b17d-02389086b17b" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "5" - }, - "name": "group - 32-Top clickers", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "ee6c3413-28be-49a1-a89d-bf5fce7acfa4" - }, - { - "type": 1, - "content": { - "json": "# Microsoft Teams Collaboration Protection\r\n\r\n---\r\nAs email defenses mature, attackers are shifting into **Microsoft Teams**, where messages bypass secure email gateways and carry the implicit trust of a colleague chat. Microsoft Threat Intelligence reports Teams-based phishing and voice phishing (vishing) rising steadily through 2026, most often as **IT help desk or technical-support impersonation** from external or newly-created tenants, used to steer users toward remote-access tools and credential theft.\r\n\r\nThis tab shows **Microsoft Defender for Office 365** protection for Microsoft Teams: threat detections and impersonation, suspicious external senders, malicious URLs and clicks, malicious files, post-delivery ZAP removals, and user and admin submissions across chats and channels.\r\n\r\n**Recommended action:** Treat unsolicited external help desk or IT support contact as suspicious. Restrict inbound chat from unmanaged and consumer tenants, allowlist trusted external domains, remove or restrict remote-support tools such as Quick Assist where they are not required, and enforce phishing-resistant MFA for all users (Conditional Access with authentication strength), prioritizing privileged and administrator accounts first.\r\n\r\n[

Disrupting threats targeting Microsoft Teams

](https://www.microsoft.com/en-us/security/blog/2025/10/07/disrupting-threats-targeting-microsoft-teams/)[

Cross-tenant helpdesk impersonation to data exfiltration: a human-operated intrusion playbook

](https://www.microsoft.com/en-us/security/blog/2026/04/18/crosstenant-helpdesk-impersonation-data-exfiltration-human-operated-intrusion-playbook/)[

Help on the line: how a Microsoft Teams support call led to compromise

](https://www.microsoft.com/en-us/security/blog/2026/03/16/help-on-the-line-how-a-microsoft-teams-support-call-led-to-compromise/)[

Email threat landscape: Q2 2026 trends and insights

](https://www.microsoft.com/en-us/security/blog/2026/07/23/email-threat-landscape-q2-2026-trends-and-insights/)" - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "14" - }, - "name": "text - teams description", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "5c0f0100-0a11-4b22-9c33-000000000100" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Headline Microsoft Teams protection metrics for the selected period, with per-interval sparklines. Messages are de-duplicated to the latest record per Teams message.\r\nlet gran = {Granularity};\r\nlet msgs = materialize(MessageEvents | summarize arg_max(Timestamp, *) by TeamsMessageId);\r\nlet zap = materialize(MessagePostDeliveryEvents);\r\nunion\r\n(msgs | summarize Count = count() | extend Details = \"Teams Messages Scanned\", Ord = 1, Trend = toscalar(msgs | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where isnotempty(ThreatTypes) | summarize Count = count() | extend Details = \"Messages with Threats\", Ord = 2, Trend = toscalar(msgs | where isnotempty(ThreatTypes) | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where ThreatTypes has \"Phish\" | summarize Count = count() | extend Details = \"Phish Detections\", Ord = 3, Trend = toscalar(msgs | where ThreatTypes has \"Phish\" | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where ThreatTypes has \"Malware\" | summarize Count = count() | extend Details = \"Malware Detections\", Ord = 4, Trend = toscalar(msgs | where ThreatTypes has \"Malware\" | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where ThreatTypes has \"Spam\" | summarize Count = count() | extend Details = \"Spam Detections\", Ord = 5, Trend = toscalar(msgs | where ThreatTypes has \"Spam\" | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(msgs | where SafetyTip == \"URLMessageWarning\" | summarize Count = count() | extend Details = \"Messages with URL Warning\", Ord = 6, Trend = toscalar(msgs | where SafetyTip == \"URLMessageWarning\" | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(zap | summarize Count = count() | extend Details = \"Post-Delivery ZAP Actions\", Ord = 7, Trend = toscalar(zap | make-series S = count() default = 0 on Timestamp step gran | project S))\r\n| sort by Ord asc\r\n| project Details, Count, Trend", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "leftContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 0, - "palette": "blue" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "secondaryContent": { - "columnMatch": "Trend", - "formatter": 21 - }, - "showBorder": true, - "size": "auto" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams kpi tiles", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "b2c476ca-4141-43b4-9d4e-98470aa432fc", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "14" - } - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Microsoft Teams - Collaboration Protection Overview\r\n
\r\n\r\nMicrosoft Defender for Office 365 extends its protection to **Microsoft Teams**, detecting malicious messages, URLs, and files shared through chats and channels. This tab summarizes Teams message detections, link-safety warnings, post-delivery ZAP, file scanning, and user/admin submissions.

*Scope note: the Teams message tables surface metadata for external-conversation messages plus internal messages that contain URLs, so counts reflect that scope rather than the full volume of Teams messages.*" - }, - "name": "teams overview banner", - "id": "2f71360f-1673-480f-8361-5afc83aee67d" - }, - { - "type": 1, - "content": { - "json": "### Teams threat detections over time
\r\n\r\n**Volume (per selected interval) of Microsoft Teams messages detected with a threat by Microsoft Defender for Office 365. Spikes may indicate a targeted Teams-based campaign.**" - }, - "customWidth": "100", - "name": "teams trend header", - "styleSettings": { - "margin": "10px", - "padding": "0px" - }, - "id": "0ac71d4e-8ecb-4d17-9fd3-10754007ec07" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the number of Microsoft Teams messages detected with a threat over time, de-duplicated to the latest record per message and summarized per selected interval.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(MessageEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(MessageEvents | summarize max(Timestamp));\r\nlet agg = materialize(MessageEvents | where isnotempty(ThreatTypes) | summarize arg_max(Timestamp, *) by TeamsMessageId | summarize ThreatDetections = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ThreatDetections = coalesce(ThreatDetections, 0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "areachart", - "chartSettings": { - "xAxis": "Timestamp", - "seriesLabelSettings": [ - { - "seriesName": "ThreatDetections", - "color": "blueDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams detection trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "937f3bc6-21f5-4f4c-ab72-78f08f32c5bd" - }, - { - "type": 1, - "content": { - "json": "### Threat type breakdown
\r\n\r\n**Split of Microsoft Teams threat detections across Phish, Malware, and Spam.**" - }, - "customWidth": "50", - "name": "teams threat pie header", - "styleSettings": { - "margin": "10px", - "padding": "0px" - }, - "id": "645a39ae-843a-47db-8016-6082ef37744d" - }, - { - "type": 1, - "content": { - "json": "### Thread exposure
\r\n\r\n**De-duplicated Microsoft Teams messages split by whether the conversation includes external participants.**" - }, - "customWidth": "50", - "name": "teams thread header", - "id": "a1a48f9a-8593-4ab5-8824-5998c643e844" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query breaks down Microsoft Teams threat detections by threat type for the selected period, de-duplicated to the latest record per message. A message flagged for more than one threat type is counted under each, so the split can exceed the distinct message count.\r\nlet msgs = MessageEvents | where isnotempty(ThreatTypes) | summarize arg_max(Timestamp, *) by TeamsMessageId;\r\nunion\r\n(msgs | where ThreatTypes has \"Phish\" | summarize Count = count() | extend ThreatType = \"Phish\"),\r\n(msgs | where ThreatTypes has \"Malware\" | summarize Count = count() | extend ThreatType = \"Malware\"),\r\n(msgs | where ThreatTypes has \"Spam\" | summarize Count = count() | extend ThreatType = \"Spam\")\r\n| project ThreatType, Count", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "teams threat type pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "029b4ecc-cd95-4385-a251-8ab194add8f4" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query shows de-duplicated Microsoft Teams messages split by whether the thread includes external participants.\r\nMessageEvents\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| extend Thread = iif(IsExternalThread == true, \"External Thread\", \"Internal Thread\")\r\n| summarize Count = count() by Thread", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "teams thread pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "1581f447-9b3e-4857-84b8-e78b5df65ac5" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "14" - }, - "name": "group - Teams Overview", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "283f36b2-5c54-4afe-9a87-33d4796bd5b7" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Teams Calls and Vishing (Voice Phishing)\r\n
\r\n\r\n**Voice phishing (vishing) over Microsoft Teams is the fastest-growing collaboration threat of 2026. Attackers impersonate IT help desk or support and call users directly, often after a chat lure, to talk them into granting remote access or entering credentials. Because a target must be online to answer, malicious calls cluster in working hours. This section surfaces Teams call activity, when calls happen, and callers using support or brand-impersonation identities.**

*Interim data source: Teams call activity is currently read from Microsoft Defender for Cloud Apps call telemetry (CloudAppEvents). The existing V4 logic retains this source while the dedicated CallActivityEvents implementation is evaluated separately.*

**Recommended action:** Treat unsolicited help desk or support calls as suspicious. Confirm any request through a known internal channel, and never grant remote access such as Quick Assist on the strength of an inbound Teams call. Restrict inbound calls and chat from unmanaged and consumer tenants." - }, - "customWidth": "100", - "name": "teams calls banner", - "id": "9815bdc9-9e10-4e84-9164-783092b4ccb0" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Teams call and vishing headline metrics for the selected period, with per-interval sparklines. Interim source: Defender for Cloud Apps call telemetry (CloudAppEvents / CallParticipantDetail).\r\nlet gran = {Granularity};\r\nlet calls = materialize(CloudAppEvents | where ActionType == \"CallParticipantDetail\" | extend R = parse_json(RawEventData) | extend CallId = tostring(R.CallId), UId = tolower(tostring(R.UserId)));\r\nlet susp = calls | extend Local = tostring(split(UId, \"@\")[0]), Dom = tostring(split(UId, \"@\")[1]) | where Local matches regex @\"(?i)help ?desk|helpdesk|it ?support|service ?desk|sys ?admin|administrator|security|microsoft|google|apple|amazon|paypal|support|update|verif|account|password|mfa|maintenance\" or Dom endswith \".onmicrosoft.com\";\r\nlet reported = CloudAppEvents | where ActionType == \"CallReported\";\r\nunion\r\n(calls | summarize Count = dcount(CallId) | extend Details = \"Teams Calls\", Ord = 1, Trend = toscalar(calls | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(susp | summarize Count = dcount(UId) | extend Details = \"Impersonation-style Callers\", Ord = 2, Trend = toscalar(susp | make-series S = count() default = 0 on Timestamp step gran | project S)),\r\n(reported | summarize Count = count() | extend Details = \"Reported Suspicious Calls\", Ord = 3, Trend = toscalar(reported | make-series S = count() default = 0 on Timestamp step gran | project S))\r\n| sort by Ord asc\r\n| project Details, Count, Trend", - "size": 3, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "leftContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 0, - "palette": "blue" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "secondaryContent": { - "columnMatch": "Trend", - "formatter": 21 - }, - "showBorder": true, - "size": "auto" - }, - "showAnalytics": true, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams calls kpi", - "id": "be8946d9-1eae-405c-b8df-cee2242cb44d" - }, - { - "type": 1, - "content": { - "json": "### Teams call activity over time
\r\n**Distinct Microsoft Teams calls per selected interval. A sudden rise, or calls outside normal working hours, can indicate a vishing campaign in progress.**" - }, - "customWidth": "100", - "name": "teams calls trend header", - "id": "1b49c98f-e5d9-457c-b058-a195e89eac0e" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Distinct Teams calls per interval (interim source: CloudAppEvents / CallParticipantDetail).\r\nCloudAppEvents\r\n| where ActionType == \"CallParticipantDetail\"\r\n| extend R = parse_json(RawEventData)\r\n| extend CallId = tostring(R.CallId)\r\n| summarize ['Teams Calls'] = dcount(CallId) by Timestamp = bin(Timestamp, {Granularity})\r\n| sort by Timestamp asc", - "size": 0, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "areachart", - "chartSettings": { - "xAxis": "Timestamp", - "seriesLabelSettings": [ - { - "seriesName": "Teams Calls", - "color": "blueDark" - } - ] - }, - "showAnalytics": true, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams calls trend", - "id": "7538b3ca-b96d-421a-9cdc-69b8aef4b185" - }, - { - "type": 1, - "content": { - "json": "### When calls happen (hour of day, UTC)
\r\n**Microsoft Teams calls by the hour of day they started (UTC), listed 00:00 through 23:00. The bar length is the number of calls that started in that hour across the selected period. Vishing calls cluster in working hours because the target must be online to answer, with the heaviest malicious-call activity between 14:00 and 20:00 UTC, Monday to Friday, according to Microsoft Threat Intelligence. Use this to baseline normal call timing and spot unusual off-hours spikes.**" - }, - "customWidth": "100", - "name": "teams calls hour header", - "id": "6bc095e9-fe0d-4f6f-81bd-f3374d758229" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Teams calls by start hour of day (UTC), all 24 hours 00:00..23:00 in order (interim source: CloudAppEvents / CallParticipantDetail).\r\nlet data = CloudAppEvents\r\n| where ActionType == \"CallParticipantDetail\"\r\n| extend R = parse_json(RawEventData)\r\n| extend JoinTime = todatetime(R.JoinTime), CallId = tostring(R.CallId)\r\n| where isnotempty(JoinTime) and isnotempty(CallId)\r\n| summarize CallStart = min(JoinTime) by CallId\r\n| extend HourUTC = hourofday(CallStart)\r\n| summarize Calls = count() by HourUTC;\r\nrange HourUTC from 0 to 23 step 1\r\n| join kind=leftouter (data) on HourUTC\r\n| extend Calls = coalesce(Calls, 0)\r\n| extend HourLabel = strcat(iif(HourUTC < 10, strcat(\"0\", tostring(HourUTC)), tostring(HourUTC)), \":00\")\r\n| order by HourUTC asc\r\n| project ['Hour of Day (UTC)'] = HourLabel, ['Teams Calls'] = Calls", - "size": 0, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true, - "formatters": [ - { - "columnMatch": "Teams Calls", - "formatter": 3, - "formatOptions": { - "palette": "blueDark", - "customColumnWidthSetting": "360px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ] - }, - "showAnalytics": true, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams calls hour", - "id": "c36a9909-5570-4fe7-8efc-1b9b4745713a" - }, - { - "type": 1, - "content": { - "json": "### Suspicious callers (support and helpdesk impersonation)
\r\n**Teams call participants whose display name or address looks like IT support, help desk, or a well-known brand (for example \"Microsoft IT support\", \"Help Desk\", \"Office 365 Support\"), or who dial in from a throwaway `.onmicrosoft.com` tenant. Origin shows whether the caller is external, an external throwaway tenant, or inside your own tenant. External and throwaway-tenant callers are the primary vishing risk; own-tenant matches are frequently a legitimate internal help desk and should be confirmed rather than assumed malicious.**

**Recommended action:** Prioritise External and `.onmicrosoft` callers, confirm none are legitimate, and warn the users they called. Genuine IT support does not cold-call staff over Teams to request remote access." - }, - "customWidth": "100", - "name": "teams calls susp header", - "id": "aa420b5f-efd2-4da5-ab41-192031f62ed1" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Suspicious Teams callers by impersonation-style DISPLAY NAME or address (Attendees[].DisplayName / UPN), with Origin from the org's own accepted (EmailEvents inbound) domains - no tenant-id anchor. Interim source: CloudAppEvents / CallParticipantDetail.\r\nlet suspRegex = @\"(?i)help ?desk|helpdesk|it ?support|service ?desk|sys ?admin|administrator|security|microsoft|google|apple|amazon|paypal|support|update|verif|account|password|mfa|maintenance\";\r\nlet ownDomains = toscalar(EmailEvents | where EmailDirection == \"Inbound\" | extend RD = tolower(tostring(split(RecipientEmailAddress, \"@\")[1])) | where isnotempty(RD) | summarize make_set(RD, 200));\r\nlet calls = CloudAppEvents\r\n| where ActionType == \"CallParticipantDetail\"\r\n| extend R = parse_json(RawEventData)\r\n| extend CallId = tostring(R.CallId), JoinTime = todatetime(R.JoinTime), Attendees = R.Attendees\r\n| where isnotempty(CallId);\r\nlet callAtt = calls | summarize Attendees = take_any(Attendees), JoinTime = min(JoinTime) by CallId;\r\ncallAtt\r\n| mv-expand Att = Attendees\r\n| extend Caller = tolower(tostring(Att.UPN)), CallerName = tostring(Att.DisplayName)\r\n| extend CallerDom = tostring(split(Caller, \"@\")[1])\r\n| where isnotempty(Caller)\r\n| extend SuspName = CallerName matches regex suspRegex or Caller matches regex suspRegex\r\n| where SuspName or CallerDom endswith \".onmicrosoft.com\"\r\n| extend Origin = case(CallerDom endswith \".onmicrosoft.com\", \"External (.onmicrosoft throwaway)\", set_has_element(ownDomains, CallerDom), \"Own tenant\", \"External\")\r\n| summarize CallsPlaced = dcount(CallId), FirstSeen = min(JoinTime), LastSeen = max(JoinTime) by CallerName, Caller, Origin\r\n| extend OriginRank = case(Origin == \"External (.onmicrosoft throwaway)\", 0, Origin == \"External\", 1, 2)\r\n| sort by OriginRank asc, CallsPlaced desc\r\n| take 10\r\n| project ['Caller Display Name'] = CallerName, ['Caller Address'] = Caller, ['Origin'] = Origin, ['Calls Placed'] = CallsPlaced, ['First Seen'] = FirstSeen, ['Last Seen'] = LastSeen", - "size": 0, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true, - "formatters": [ - { - "columnMatch": "Calls Placed", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ] - }, - "showAnalytics": true, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams calls susp table", - "id": "d1c4df7b-db07-4c4c-bc71-dfd8623cd704" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "14" - }, - "name": "group - Teams Calls and Vishing", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "1d133411-9b5c-4ede-8502-68b3b02262e4" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Teams Impersonation & Identity Deception\r\n
\r\n\r\nMicrosoft Defender for Office 365 flags Teams messages where a sender impersonates a brand, a specific person, or a trusted domain. Impersonation is the entry point for most Teams social-engineering: attackers pose as IT, executives, or Microsoft to build trust before delivering a malicious link or request. These visuals expose who is being impersonated, who is being targeted, and the infrastructure (display names, look-alike domains, and URLs) behind the campaigns so you can hunt IOCs and coach at-risk users.

**Recommended action:** Treat the impersonated display names and look-alike domains below as IOCs to hunt, and prioritize the Microsoft Defender alert *Microsoft Teams chat initiated by a suspicious external user*. Teach users that a Teams display name is not proof of identity: verify the real sender domain, and confirm any help desk, executive, or Microsoft support request through a known internal channel before acting." - }, - "name": "teams imp banner", - "id": "7ff04ff3-9f2d-4a49-8383-2b542d78fe9b" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nunion\r\n(imp | summarize Count=count() | extend Details=\"Impersonation Detections\", Ord=1),\r\n(imp | summarize Count=dcount(FakeSenderAddress) | extend Details=\"Distinct Fake Senders\", Ord=2),\r\n(imp | summarize Count=dcount(TargetUser) | extend Details=\"Targeted Users\", Ord=3),\r\n(imp | summarize Count=dcount(ImpersonationType) | extend Details=\"Impersonation Types\", Ord=4)\r\n| sort by Ord asc | project Count, Details", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "secondaryContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 0, - "palette": "blue" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "showBorder": true, - "size": "full" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams imp tiles", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "e37f94d5-9bcc-432e-aa66-25831603c228" - }, - { - "type": 1, - "content": { - "json": "### Impersonation over time, by type
\r\n\r\n**Trend of Brand, User, and Domain impersonation detections. A spike in a single type often marks the start of a targeted campaign.**" - }, - "customWidth": "100", - "name": "teams imp trend header", - "id": "09907f5b-5c20-4a7e-86d3-c89153c4df98" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp | summarize Count=count() by ImpersonationType, Timestamp=bin(Timestamp, {Granularity}) | sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "chartSettings": { - "xAxis": "Timestamp" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams imp trend", - "id": "757204b1-e900-4217-a2ff-2224a033fdcc" - }, - { - "type": 1, - "content": { - "json": "### Suspicious external senders (impersonation and throwaway tenants)
\r\n**External Microsoft Teams senders flagged as likely impersonation: throwaway `.onmicrosoft.com` tenants and/or help desk, IT support, security, admin, or account/update-themed display names. Attackers rotate through many such identities (for example numbered `ithelpdesk@...` addresses) from newly-created or consumer tenants to pose as internal support, frequently before the Defender impersonation detector assigns a verdict. This heuristic complements that detector.**

**Recommended action:** Review high threat-rate senders, block the sending domains, and remind users that genuine IT support does not cold-contact them from an external tenant; verify any such request through a known internal channel." - }, - "customWidth": "100", - "name": "teams susp senders header", - "id": "5df4af86-49e9-4fc7-b6ad-76d3ef3f7da6" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//External Teams senders flagged as likely impersonation: throwaway .onmicrosoft.com tenants and/or help desk / IT / admin / update-themed display names, ranked by messages carrying a threat.\r\nMessageEvents\r\n| where IsExternalThread == true\r\n| extend SenderDomain = tolower(tostring(split(SenderEmailAddress, \"@\")[1]))\r\n| extend IsOnMicrosoft = SenderDomain endswith \".onmicrosoft.com\"\r\n| extend SuspName = SenderDisplayName matches regex @\"(?i)help ?desk|helpdesk|it ?support|service ?desk|it team|administrator|sys ?admin|security|microsoft|maintenance|support|update|verif|account|password|mfa\"\r\n| where IsOnMicrosoft or SuspName\r\n| summarize TeamsMessages = count(), ThreatMessages = countif(isnotempty(ThreatTypes)), FirstSeen = min(Timestamp), LastSeen = max(Timestamp) by SenderDisplayName, SenderEmailAddress, SenderDomain, IsOnMicrosoft, SuspName\r\n| extend WhyFlagged = case(IsOnMicrosoft and SuspName, \"Throwaway .onmicrosoft tenant + helpdesk-style name\", IsOnMicrosoft, \"Throwaway .onmicrosoft tenant\", \"Helpdesk / IT-style display name\")\r\n| extend ThreatPct = round(todouble(ThreatMessages) * 100 / TeamsMessages, 1)\r\n| project ['Sender Display Name']=SenderDisplayName, ['Sender Address']=SenderEmailAddress, ['Why Flagged']=WhyFlagged, ['Teams Messages']=TeamsMessages, ['Threat Messages']=ThreatMessages, ['Threat %']=ThreatPct, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen\r\n| sort by ['Threat Messages'] desc, ['Teams Messages'] desc\r\n| take 10", - "size": 0, - "title": "", - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true, - "formatters": [ - { - "columnMatch": "Teams Messages", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Threat Messages", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Threat %", - "formatter": 4, - "formatOptions": { - "palette": "red", - "min": 0, - "max": 100 - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ] - }, - "showAnalytics": true, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams susp senders table", - "id": "dd1d79d8-f591-4aae-bd44-6ad23a3e0ae4" - }, - { - "type": 1, - "content": { - "json": "### Who is being targeted
\r\n\r\n**Internal users receiving the most impersonation attempts. Concentrated targeting of a few users is a strong signal of a deliberate campaign - prioritize these users for security awareness training.**" - }, - "customWidth": "100", - "name": "teams imp targets header", - "id": "43112ad1-ebc9-42fb-9ebd-0dbaa862ed45" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp | summarize Detections=count(), ['Distinct Fake Senders']=dcount(FakeSenderAddress), Types=make_set(ImpersonationType,3), ['Last Seen']=max(Timestamp) by ['Targeted User']=TargetUser | top 10 by Detections", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams imp targets", - "id": "cc4b3f98-bfcb-4741-9abb-9ff099eb946f" - }, - { - "type": 1, - "content": { - "json": "### Impersonating senders
\r\n\r\n**The identities behind the impersonation, grouped by fake display name, sender domain, and type. Attackers rotate through many sending addresses under a single display name - Distinct Sender Addresses exposes that rotation, and a high count is itself a strong bulk-campaign signal. Use First/Last Seen to scope the campaign window.**" - }, - "customWidth": "100", - "name": "teams imp senders header", - "id": "99859796-7b69-42e7-a27a-541e0ba86cb2" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query lists the identities behind Teams impersonation, grouped by the fake display name, sender domain, and impersonation type. Attackers rotate through many sending addresses under one display name, so Distinct Sender Addresses reveals bulk campaigns that per-address ranking would hide.\r\nlet imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp\r\n| summarize Detections=count(), SenderAddresses=dcount(FakeSenderAddress), Targets=dcount(TargetUser), FirstSeen=min(Timestamp), LastSeen=max(Timestamp) by FakeDisplayName, FakeSenderDomain, ImpersonationType\r\n| top 10 by Detections\r\n| project ['Fake Display Name']=FakeDisplayName, ['Sender Domain']=FakeSenderDomain, ['Impersonation Type']=ImpersonationType, ['Distinct Sender Addresses']=SenderAddresses, Detections, ['Targeted Users']=Targets, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true, - "formatters": [ - { - "columnMatch": "Distinct Sender Addresses", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Detections", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams imp senders", - "id": "209439a0-5be3-4e41-abe9-695552730dc8" - }, - { - "type": 1, - "content": { - "json": "### Display names abused
\r\n\r\n**The identities attackers pretend to be (for example \"IT HelpDesk\", \"Microsoft Support\"). These are the trust anchors of the social-engineering lure.**" - }, - "customWidth": "100", - "name": "teams imp names header", - "id": "e645578b-7a52-4d38-9d83-f5c500bbfe1a" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp | summarize Detections=count(), ['Targeted Users']=dcount(TargetUser), ['Distinct Senders']=dcount(FakeSenderAddress) by ['Fake Display Name']=FakeDisplayName | top 10 by Detections", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true, - "formatters": [ - { - "columnMatch": "Detections", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Distinct Senders", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams imp names", - "id": "d723d72b-4e7c-431b-ae7b-980879c8bd75" - }, - { - "type": 1, - "content": { - "json": "### Look-alike sender domains
\r\n\r\n**Sending domains used for impersonation - watch for typosquats (for example rnicrosoft.com for m→rn). Add confirmed domains to your Tenant Allow/Block List.**" - }, - "customWidth": "100", - "name": "teams imp domains header", - "id": "98040a5a-bbd5-4c95-b976-5630ce48b282" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "let imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ImpersonationType = tostring(RD.ImpersonationType),\r\n FakeDisplayName = tostring(RD.Sender.DisplayName),\r\n FakeSenderAddress = tostring(RD.Sender.UPN),\r\n ChatThreadId = tostring(RD.ChatThreadId),\r\n TargetUser = tostring(RD.UserId)\r\n| extend FakeSenderDomain = tostring(split(FakeSenderAddress, \"@\")[1]);\r\nimp | summarize Detections=count(), ['Targeted Users']=dcount(TargetUser), ['Display Names Used']=dcount(FakeDisplayName) by ['Sender Domain']=FakeSenderDomain | top 10 by Detections", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true, - "formatters": [ - { - "columnMatch": "Detections", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Display Names Used", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams imp domains", - "id": "94b9fa45-c889-46a7-8b80-92e5d280ad3b" - }, - { - "type": 1, - "content": { - "json": "### URL IOCs from impersonation messages
\r\n\r\n**URL domains that appeared in messages sent by impersonating senders. Threat actors deliberately mix legitimate domains (for example microsoft.com or google.com) with their malicious ones to make the lure look trustworthy, so treat this as a review list - not a blocklist. Investigate the unfamiliar or look-alike domains and block only those you confirm malicious; never block a well-known legitimate domain from this list.**" - }, - "customWidth": "100", - "name": "teams imp ioc header", - "id": "d5f4886c-7c7e-4c6f-94ca-569cabda5ede" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query lists URL domains that appeared in messages sent by impersonating senders, with a breakdown of how many carried Malware, Phish, or Spam verdicts. Threat actors mix legitimate and malicious domains in a single lure, so review the unfamiliar or look-alike domains and block only confirmed-malicious ones.\r\nlet imp = CloudAppEvents\r\n| where ActionType == \"TeamsImpersonationDetected\"\r\n| extend RD = parse_json(RawEventData)\r\n| extend ChatThreadId = tostring(RD.ChatThreadId);\r\nlet impThreads = imp | distinct ChatThreadId;\r\nlet impMsgs = MessageEvents\r\n | where ThreadId in (impThreads)\r\n | summarize arg_max(Timestamp, *) by TeamsMessageId\r\n | project TeamsMessageId, ThreatTypes;\r\nMessageUrlInfo\r\n| where isnotempty(UrlDomain)\r\n| join kind=inner (impMsgs) on TeamsMessageId\r\n| summarize ['URL Count']=count(), Messages=dcount(TeamsMessageId), Malware=countif(ThreatTypes has \"Malware\"), Phish=countif(ThreatTypes has \"Phish\"), Spam=countif(ThreatTypes has \"Spam\") by ['URL Domain']=UrlDomain\r\n| top 10 by ['URL Count']", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true, - "formatters": [ - { - "columnMatch": "URL Count", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Messages", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Malware", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Phish", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Spam", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams imp ioc", - "id": "958ac65c-d56d-4a80-ba83-2ab33e8b1e2e" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "14" - }, - "name": "group - Teams Impersonation", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "c49582db-6318-423f-b806-91cbeb625ea2" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Malicious URLs and Link Warnings in Teams\r\n
\r\n\r\nTracks URLs shared through Microsoft Teams, messages that triggered a Microsoft Defender for Office 365 URL safety-tip warning, and the outcome of Teams URL clicks (allowed versus blocked) captured in UrlClickEvents.

**Recommended action:** Enable Safe Links for Microsoft Teams so links are checked at click time, and prioritize *User clicked a malicious link in Teams chat* alerts for investigation. Treat a blocked click as an attempted compromise: check whether the user went on to share credentials or run a file, and reset credentials where warranted." - }, - "name": "teams url banner", - "id": "e3ec4d65-8d1f-4303-bd8f-eb1ae521da41" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query surfaces Microsoft Teams URL-sharing and link-warning metrics for the selected period. URL-warning messages carry the Microsoft Defender for Office 365 URL safety tip.\r\nlet msgs = materialize(MessageEvents | summarize arg_max(Timestamp, *) by TeamsMessageId);\r\nunion\r\n(msgs | where SafetyTip == \"URLMessageWarning\" | summarize Count = count() | extend Details = \"Messages with URL Warning\", Ord = 1),\r\n(MessageUrlInfo | summarize Count = count() | extend Details = \"URLs Shared in Messages\", Ord = 2),\r\n(MessageUrlInfo | summarize Count = dcount(TeamsMessageId) | extend Details = \"Messages Containing URLs\", Ord = 3),\r\n(MessageUrlInfo | summarize Count = dcount(UrlDomain) | extend Details = \"Distinct URL Domains\", Ord = 4)\r\n| sort by Ord asc\r\n| project Count, Details", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "secondaryContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 0, - "palette": "blue" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "showBorder": true, - "size": "full" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams url tiles", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "b71382c7-c0f7-4f9d-9d21-e0a8bf9504ff" - }, - { - "type": 1, - "content": { - "json": "### Teams URL click outcomes over time
\r\n\r\n**Allowed versus blocked Microsoft Teams URL clicks (per selected interval) from UrlClickEvents where the click happened in the Teams workload.**" - }, - "customWidth": "66", - "name": "teams click trend header", - "styleSettings": { - "margin": "10px", - "padding": "0px" - }, - "id": "30818e0d-6c4b-4868-896a-ac48cb3cef86" - }, - { - "type": 1, - "content": { - "json": "### Click outcomes
\r\n\r\n**Distribution of Microsoft Teams URL click actions by type.**" - }, - "customWidth": "33", - "name": "teams click pie header", - "styleSettings": { - "margin": "10px", - "padding": "0px" - }, - "id": "5a882138-2241-4527-80b8-9983c5807050" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises Microsoft Teams URL click outcomes over time (allowed vs blocked) using the UrlClickEvents workload filter, summarizing the data per selected interval.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(UrlClickEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(UrlClickEvents | summarize max(Timestamp));\r\nlet agg = materialize(UrlClickEvents\r\n| where Workload == \"Teams\"\r\n| summarize ClickAllowed = countif(ActionType has \"ClickAllowed\"), ClickBlocked = countif(ActionType has \"ClickBlocked\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ClickAllowed = coalesce(ClickAllowed, 0), ClickBlocked = coalesce(ClickBlocked, 0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "chartSettings": { - "xAxis": "Timestamp" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "66", - "name": "teams click trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "7a2f5559-1e3e-412a-addf-c3bf6be98502" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query shows Microsoft Teams URL click outcomes by action type for the selected period.\r\nUrlClickEvents\r\n| where Workload == \"Teams\"\r\n| where isnotempty(ActionType)\r\n| summarize Count = count() by ActionType", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "33", - "name": "teams click pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "889c6bb3-438b-4575-84f2-084c1b5fd1f4" - }, - { - "type": 1, - "content": { - "json": "### Top domains shared in Teams messages
\r\n\r\n**The 10 most-shared URL domains in Microsoft Teams messages, with the number of messages each appeared in.**" - }, - "customWidth": "100", - "name": "teams top domains header", - "id": "dcb8c87c-087e-4d69-b7b7-0329296293ff" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query lists the top 10 URL domains shared in Microsoft Teams messages by volume for the selected period.\r\nMessageUrlInfo\r\n| where isnotempty(UrlDomain)\r\n| summarize UrlCount = count(), Messages = dcount(TeamsMessageId) by UrlDomain\r\n| top 10 by UrlCount\r\n| project ['URL Domain']=UrlDomain, ['URLs Shared']=UrlCount, ['Messages']=Messages", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "URLs Shared", - "formatter": 3, - "formatOptions": { - "palette": "redDark" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams top domains table", - "id": "7561adb0-1fbe-41ce-a924-a27bcd4c5c12" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "14" - }, - "name": "group - Teams Malicious URLs", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "6d47c309-be9e-4b21-940e-7c7b282e5dc2" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Targeted Users & Risky Senders\r\n
\r\n\r\nIdentifies who is most targeted in Microsoft Teams, and profiles the external senders and domains behind risky messages - URL safety-tip warnings, first-contact senders, threat-carrying domains, and low-reputation link infrastructure - so you can spot anomalous senders before they succeed.

**Recommended action:** Prioritize the most-targeted users for phishing-resistant MFA and awareness coaching, and treat first-contact external senders and low-reputation domains as IOCs. Restrict inbound chat from unmanaged and consumer tenants, and allowlist only trusted external domains so unsolicited outsiders cannot start a conversation." - }, - "name": "teams risky banner", - "id": "0aa13d73-2e13-487c-a7c4-d90464a554d4" - }, - { - "type": 1, - "content": { - "json": "### Top targeted users (messages with threats)
\r\n\r\n**The 10 users receiving the most Microsoft Teams messages that contained a threat, expanded from each message recipient list.**" - }, - "customWidth": "100", - "name": "teams targeted header", - "id": "827dc0f6-2bb2-49b9-acf8-d7b400238594" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query lists the top 10 users receiving Microsoft Teams messages that contained a threat, expanded from the message recipient list, with each user's total Teams messages received and the share that carried a threat. Messages are de-duplicated to the latest record per message.\r\nlet expanded = MessageEvents\r\n | summarize arg_max(Timestamp, *) by TeamsMessageId\r\n | mv-expand rd = parse_json(RecipientDetails)\r\n | extend Recipient = tostring(rd.RecipientSmtpAddress)\r\n | where isnotempty(Recipient);\r\nlet totals = expanded | summarize TotalMessages = count() by Recipient;\r\nexpanded\r\n| where isnotempty(ThreatTypes)\r\n| summarize ThreatMessages = count() by Recipient\r\n| join kind=leftouter (totals) on Recipient\r\n| extend ThreatPct = round(100.0 * ThreatMessages / TotalMessages, 1)\r\n| top 10 by ThreatMessages\r\n| project ['Recipient']=Recipient, ['Threat Messages']=ThreatMessages, ['Total Messages']=TotalMessages, ['Threat %']=ThreatPct", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Threat Messages", - "formatter": 3, - "formatOptions": { - "palette": "redDark" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams targeted users table", - "id": "79481d1b-617e-46df-b555-9f7240932dd0" - }, - { - "type": 1, - "content": { - "json": "### Top senders of URL-warning messages
\r\n\r\n**Senders whose Microsoft Teams messages most often triggered a URL safety-tip warning.**" - }, - "customWidth": "50", - "name": "teams warn senders header", - "styleSettings": { - "margin": "10px", - "padding": "0px" - }, - "id": "ef71d7dd-4442-4992-977d-d550aad4533c" - }, - { - "type": 1, - "content": { - "json": "### Top domains in URL-warning messages
\r\n\r\n**URL domains most frequently present in Microsoft Teams messages that triggered a URL safety-tip warning.**" - }, - "customWidth": "50", - "name": "teams warn domains header", - "styleSettings": { - "margin": "10px", - "padding": "0px" - }, - "id": "6f41a4ba-f832-4947-ad27-cd6b8015bd63" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query lists the top 10 senders whose Microsoft Teams messages triggered a URL safety-tip warning for the selected period, with each sender's total Teams messages and the share that carried a warning. Messages are de-duplicated to the latest record per message.\r\nlet dedup = MessageEvents | summarize arg_max(Timestamp, *) by TeamsMessageId;\r\nlet totals = dedup | summarize TotalMessages = count() by SenderEmailAddress;\r\ndedup\r\n| where SafetyTip == \"URLMessageWarning\"\r\n| summarize WarningMessages = count() by SenderEmailAddress\r\n| join kind=leftouter (totals) on SenderEmailAddress\r\n| extend WarningPct = round(100.0 * WarningMessages / TotalMessages, 1)\r\n| top 10 by WarningMessages\r\n| project ['Sender']=SenderEmailAddress, ['Warning Messages']=WarningMessages, ['Total Messages']=TotalMessages, ['Warning %']=WarningPct", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Warning Messages", - "formatter": 3, - "formatOptions": { - "palette": "redDark" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "teams warn senders table", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "3fa023af-79e3-407f-ac20-b0aa6e3ba511" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query lists the top 10 URL domains appearing in Microsoft Teams messages that triggered a URL safety-tip warning, with the domain's total message appearances and the share that carried a warning.\r\nlet warned = MessageEvents | where SafetyTip == \"URLMessageWarning\" | distinct TeamsMessageId;\r\nlet totals = MessageUrlInfo | where isnotempty(UrlDomain) | summarize TotalMessages = dcount(TeamsMessageId) by UrlDomain;\r\nMessageUrlInfo\r\n| where TeamsMessageId in (warned)\r\n| summarize WarningMessages = dcount(TeamsMessageId) by UrlDomain\r\n| join kind=leftouter (totals) on UrlDomain\r\n| extend WarningPct = round(100.0 * WarningMessages / TotalMessages, 1)\r\n| top 10 by WarningMessages\r\n| project ['URL Domain']=UrlDomain, ['Warning Messages']=WarningMessages, ['Total Messages']=TotalMessages, ['Warning %']=WarningPct", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Warning Messages", - "formatter": 3, - "formatOptions": { - "palette": "redDark" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "teams warn domains table", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "68811015-1383-48ad-86da-4f8f9d39e4c4" - }, - { - "type": 1, - "content": { - "json": "### First-contact external senders
\r\n\r\n**External Microsoft Teams senders ordered by when they were first seen in the period (most recent first). Note: some flows tag internal-domain senders as external - to hide your own tenant domains, edit the query and uncomment the ExcludeDomains filter.**" - }, - "customWidth": "100", - "name": "teams fc senders header", - "id": "0f131ff3-d6b2-4187-b86c-ca3493594b54" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query lists external Microsoft Teams senders by the date they were first seen in the selected period, surfacing recent first-contact senders. Messages are de-duplicated to the latest record per message. In tenants with longer history this highlights genuinely new senders.\r\n// TIP: IsExternalThread may still surface senders from your own accepted domains. To hide them,\r\n// uncomment the ExcludeDomains line below (add your tenant domains) and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"contoso.com\"]);\r\nMessageEvents\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| where IsExternalThread == true\r\n//| where tostring(split(SenderEmailAddress, \"@\")[1]) !in~ (ExcludeDomains)\r\n| summarize FirstSeen = min(Timestamp), Messages = count(), ThreatMessages = countif(isnotempty(ThreatTypes)) by SenderEmailAddress\r\n| top 10 by FirstSeen desc\r\n| project ['Sender']=SenderEmailAddress, ['First Seen']=FirstSeen, ['Messages']=Messages, ['Threat Messages']=ThreatMessages", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Threat Messages", - "formatter": 3, - "formatOptions": { - "palette": "redDark" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true, - "sortBy": [ - { - "itemKey": "Threat Messages", - "sortOrder": 2 - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams fc senders table", - "id": "4e10a78d-8858-4dbb-9db0-e7b7d7e7636c" - }, - { - "type": 1, - "content": { - "json": "### External sender-domain risk
\r\n\r\n**External sending domains ranked by threat volume, with the mix of conversation types (1:1 chat, group chat, channel), threat breakdown, threat rate, count of messages carrying low-reputation URLs (domains on commonly-abused TLDs such as .xyz, .top, .click, .shop, .zip), and first/last-seen. A domain that is new in the period, skews toward 1:1 chats, or shows a high threat rate is anomalous and warrants review. Note: to exclude your own tenant domains, edit the query and uncomment the ExcludeDomains filter.**" - }, - "customWidth": "100", - "name": "teams anomaly header", - "id": "a91295db-8192-4828-93c5-408436e4b0e1" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query ranks external sender domains in Microsoft Teams by threat volume for the selected period, split by conversation type (1:1 chat, group chat, channel), with threat-type breakdown, threat rate, and a count of messages carrying low-reputation URL TLDs. Messages are de-duplicated to the latest record per message. New, 1:1-skewed, or high-threat-rate domains are the anomalies to review.\r\n// TIP: IsExternalThread may still surface your own accepted domains. To hide them, uncomment the\r\n// ExcludeDomains line below (add your tenant domains) and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"contoso.com\"]);\r\nlet suspTlds = dynamic([\"top\",\"xyz\",\"click\",\"link\",\"shop\",\"online\",\"site\",\"live\",\"icu\",\"cyou\",\"sbs\",\"rest\",\"quest\",\"cfd\",\"bond\",\"buzz\",\"fun\",\"space\",\"monster\",\"work\",\"tk\",\"ml\",\"ga\",\"cf\",\"gq\",\"dev\",\"app\",\"zip\",\"mov\",\"info\",\"win\",\"loan\",\"men\",\"stream\",\"country\"]);\r\nlet suspUrlMsgs = MessageUrlInfo\r\n | where isnotempty(UrlDomain)\r\n | extend Tld = tostring(split(UrlDomain, \".\")[-1])\r\n | where Tld in (suspTlds)\r\n | distinct TeamsMessageId;\r\nMessageEvents\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| where IsExternalThread == true\r\n| extend SenderDomain = tostring(split(SenderEmailAddress, \"@\")[1])\r\n| where isnotempty(SenderDomain)\r\n//| where SenderDomain !in~ (ExcludeDomains)\r\n| extend ConvType = case(isnotempty(GroupId), \"Channel\", array_length(todynamic(RecipientDetails)) > 1, \"Group chat\", \"1:1 chat\")\r\n| extend HasSuspUrl = TeamsMessageId in (suspUrlMsgs)\r\n| summarize Messages=count(), Senders=dcount(SenderEmailAddress), OneToOne=countif(ConvType==\"1:1 chat\"), GroupChat=countif(ConvType==\"Group chat\"), ChannelMsgs=countif(ConvType==\"Channel\"), ThreatMessages=countif(isnotempty(ThreatTypes)), Malware=countif(ThreatTypes has \"Malware\"), Phish=countif(ThreatTypes has \"Phish\"), Spam=countif(ThreatTypes has \"Spam\"), SuspUrlMsgs=countif(HasSuspUrl), FirstSeen=min(Timestamp), LastSeen=max(Timestamp) by SenderDomain\r\n| where ThreatMessages > 0\r\n| extend ThreatRatePct = round(100.0 * ThreatMessages / Messages, 1)\r\n| top 10 by ThreatMessages desc\r\n| project ['Sender Domain']=SenderDomain, Messages, Senders, ['1:1']=OneToOne, ['Group']=GroupChat, ['Channel']=ChannelMsgs, ['Threat Msgs']=ThreatMessages, Malware, Phish, Spam, ['Threat Rate %']=ThreatRatePct, ['Low-Rep URL Msgs']=SuspUrlMsgs, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Threat Messages", - "formatter": 3, - "formatOptions": { - "palette": "redDark" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams anomaly table", - "id": "bcd6746d-8298-495d-9d6c-2fadc6cba569" - }, - { - "type": 1, - "content": { - "json": "### Suspicious new senders (no threat verdict yet)
\r\n\r\n**External sending domains with no threat verdict yet, but that are either sending low-reputation-URL messages or showing unusual volume. These slip past threat filters - watch for new domains skewing toward 1:1 chats, an early social-engineering signal. Note: to exclude your own tenant domains, edit the query and uncomment the ExcludeDomains filter.**" - }, - "customWidth": "100", - "name": "teams newdom header", - "id": "9e3844f4-befc-4b76-a8cd-ca53fdf51d41" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query surfaces external sender domains in Microsoft Teams that have NO threat verdict yet but are sending messages with low-reputation URL TLDs or unusual volume, split by conversation type. These are early-warning senders that have not tripped a detection. Messages are de-duplicated to the latest record per message.\r\n// TIP: IsExternalThread may still surface your own accepted domains. To hide them, uncomment the\r\n// ExcludeDomains line below (add your tenant domains) and the matching where-clause.\r\n//let ExcludeDomains = dynamic([\"contoso.com\",\"contoso.com\"]);\r\nlet suspTlds = dynamic([\"top\",\"xyz\",\"click\",\"link\",\"shop\",\"online\",\"site\",\"live\",\"icu\",\"cyou\",\"sbs\",\"rest\",\"quest\",\"cfd\",\"bond\",\"buzz\",\"fun\",\"space\",\"monster\",\"work\",\"tk\",\"ml\",\"ga\",\"cf\",\"gq\",\"dev\",\"app\",\"zip\",\"mov\",\"info\",\"win\",\"loan\",\"men\",\"stream\",\"country\"]);\r\nlet suspUrlMsgs = MessageUrlInfo\r\n | where isnotempty(UrlDomain)\r\n | extend Tld = tostring(split(UrlDomain, \".\")[-1])\r\n | where Tld in (suspTlds)\r\n | distinct TeamsMessageId;\r\nMessageEvents\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| where IsExternalThread == true\r\n| extend SenderDomain = tostring(split(SenderEmailAddress, \"@\")[1])\r\n| where isnotempty(SenderDomain)\r\n//| where SenderDomain !in~ (ExcludeDomains)\r\n| extend ConvType = case(isnotempty(GroupId), \"Channel\", array_length(todynamic(RecipientDetails)) > 1, \"Group chat\", \"1:1 chat\")\r\n| extend HasSuspUrl = TeamsMessageId in (suspUrlMsgs)\r\n| summarize Messages=count(), Senders=dcount(SenderEmailAddress), OneToOne=countif(ConvType==\"1:1 chat\"), GroupChat=countif(ConvType==\"Group chat\"), ChannelMsgs=countif(ConvType==\"Channel\"), ThreatMessages=countif(isnotempty(ThreatTypes)), SuspUrlMsgs=countif(HasSuspUrl), FirstSeen=min(Timestamp), LastSeen=max(Timestamp) by SenderDomain\r\n| where ThreatMessages == 0\r\n| where SuspUrlMsgs > 0 or Messages >= 5\r\n| order by SuspUrlMsgs desc, Messages desc\r\n| take 10\r\n| project ['Sender Domain']=SenderDomain, Messages, Senders, ['1:1']=OneToOne, ['Group']=GroupChat, ['Channel']=ChannelMsgs, ['Low-Rep URL Msgs']=SuspUrlMsgs, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams newdom table", - "id": "8036a5b7-b5b3-4af4-912f-bb092bb01b89" - }, - { - "type": 1, - "content": { - "json": "### Low-reputation link domains in Teams (IOC radar)
\r\n\r\n**URL domains shared in Teams that use TLDs commonly abused for phishing and malware (for example .xyz, .top, .click, .zip, .shop). Ranked by message reach, with first/last-seen. Review these domains as potential indicators - .zip and .mov are especially deceptive because links read like file names.**" - }, - "customWidth": "100", - "name": "teams tld header", - "id": "d48921f4-233c-4e0f-a97b-83e1bcaed399" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query lists URL domains shared in Microsoft Teams that use low-reputation TLDs commonly abused for phishing and malware, ranked by the number of Teams messages they appeared in, with first- and last-seen. Treat high-reach or newly-seen domains as candidate indicators of compromise.\r\nlet suspTlds = dynamic([\"top\",\"xyz\",\"click\",\"link\",\"shop\",\"online\",\"site\",\"live\",\"icu\",\"cyou\",\"sbs\",\"rest\",\"quest\",\"cfd\",\"bond\",\"buzz\",\"fun\",\"space\",\"monster\",\"work\",\"tk\",\"ml\",\"ga\",\"cf\",\"gq\",\"dev\",\"app\",\"zip\",\"mov\",\"info\",\"win\",\"loan\",\"men\",\"stream\",\"country\"]);\r\nMessageUrlInfo\r\n| where isnotempty(UrlDomain)\r\n| extend Tld = tostring(split(UrlDomain, \".\")[-1])\r\n| where Tld in (suspTlds)\r\n| summarize Messages=dcount(TeamsMessageId), FirstSeen=min(Timestamp), LastSeen=max(Timestamp) by ['URL Domain']=UrlDomain, ['TLD']=Tld\r\n| top 10 by Messages desc", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true, - "formatters": [ - { - "columnMatch": "Messages", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams tld table", - "id": "30d5588e-010c-474a-9c53-74b73dcc9676" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "14" - }, - "name": "group - Teams Targeted Users & Risky Senders", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "6fef737b-cb4e-4a51-9ced-bf11754a6b33" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Teams File Protection\r\n
\r\n\r\nMicrosoft Defender for Office 365 scans files shared in Microsoft Teams. These visuals show files scanned versus malware detected, and list the malicious files found.

**Recommended action:** Investigate each malicious file below and confirm it was quarantined and removed from the SharePoint or OneDrive location backing the chat. Enable Safe Attachments for SharePoint, OneDrive, and Microsoft Teams, and use attack surface reduction rules to block executable content delivered through collaboration." - }, - "name": "teams file banner", - "id": "2f01c905-dd65-4a13-9f67-c70402b2c175" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query summarizes Microsoft Teams file protection by Microsoft Defender for Office 365 - files scanned, files with malware detected, and files scanned with no detection - for the selected period.\r\nlet base = FileMaliciousContentInfo | where Workload == \"MicrosoftTeams\";\r\nunion\r\n(base | summarize Count = count() | extend Details = \"Teams Files Scanned\", Ord = 1),\r\n(base | where isnotempty(ThreatTypes) | summarize Count = count() | extend Details = \"Files with Malware Detected\", Ord = 2),\r\n(base | where isempty(ThreatTypes) | summarize Count = count() | extend Details = \"Files Scanned - No Detection\", Ord = 3)\r\n| sort by Ord asc\r\n| project Count, Details", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "secondaryContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 0, - "palette": "blue" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "showBorder": true, - "size": "full" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams file tiles", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "9f555c51-1680-47ef-94d4-b1f8cf9dce3b" - }, - { - "type": 1, - "content": { - "json": "### Malicious files shared in Teams
\r\n\r\n**Files shared in Microsoft Teams that were detected with malware, with owner and file details.**" - }, - "customWidth": "100", - "name": "teams file table header", - "id": "4cd3274e-0c61-4722-83b7-1fccf8a94a57" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query lists Microsoft Teams files detected with malware by Microsoft Defender for Office 365 for the selected period.\r\nFileMaliciousContentInfo\r\n| where Workload == \"MicrosoftTeams\"\r\n| where isnotempty(ThreatTypes)\r\n| top 10 by Timestamp desc\r\n| project ['Time']=Timestamp, ['File Name']=FileName, ['Threat Type']=tostring(ThreatTypes), ['Threat Names']=ThreatNames, ['File Location']=FolderPath, ['File Owner']=FileOwnerUpn, SHA256", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams file table", - "id": "135e0e7d-7110-40ee-a377-1a5992b2ef9d" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "14" - }, - "name": "group - Teams File Protection", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "8ecc1bae-4a06-4b1c-8952-59fb434b7cbc" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Post-Delivery ZAP Insights (Teams)\r\n
\r\n\r\nZero-hour auto purge (ZAP) removes malicious Microsoft Teams messages after delivery. These visuals summarize ZAP volume, type, result, and the senders whose messages were most often removed.

**Recommended action:** Confirm zero-hour auto purge is enabled for Microsoft Teams so newly-weaponized messages are pulled after delivery. Investigate senders with repeated ZAP removals as likely compromised or malicious accounts and block or restrict them. A rising ZAP trend can signal an active campaign that slipped past delivery-time filtering." - }, - "name": "teams zap banner", - "id": "136cfb4e-d2a5-4db0-9771-6b6380011ba0" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query summarizes Microsoft Teams post-delivery ZAP (zero-hour auto purge) activity by Microsoft Defender for Office 365 for the selected period.\r\nlet zap = materialize(MessagePostDeliveryEvents);\r\nunion\r\n(zap | summarize Count = count() | extend Details = \"Total ZAP Actions\", Ord = 1),\r\n(zap | where ActionType == \"Malware ZAP\" | summarize Count = count() | extend Details = \"Malware ZAP\", Ord = 2),\r\n(zap | where ActionType == \"Phish ZAP\" | summarize Count = count() | extend Details = \"Phish ZAP\", Ord = 3),\r\n(zap | where ActionResult == \"Success\" | summarize Count = count() | extend Details = \"Successful Actions\", Ord = 4),\r\n(zap | where ActionResult == \"Failed\" | summarize Count = count() | extend Details = \"Failed Actions\", Ord = 5),\r\n(zap | where Action == \"Moved to quarantine\" | summarize Count = count() | extend Details = \"Moved to Quarantine\", Ord = 6)\r\n| sort by Ord asc\r\n| project Count, Details", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "secondaryContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 0, - "palette": "blue" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "showBorder": true, - "size": "full" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams zap tiles", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "06980411-5e6b-4aa4-a746-351cd2b12dae" - }, - { - "type": 1, - "content": { - "json": "### ZAP actions over time
\r\n\r\n**Microsoft Teams post-delivery ZAP actions (per selected interval) split by Malware ZAP and Phish ZAP.**" - }, - "customWidth": "66", - "name": "teams zap trend header", - "styleSettings": { - "margin": "10px", - "padding": "0px" - }, - "id": "7fc1cfcd-3a9f-45b1-9f39-3820fce23c03" - }, - { - "type": 1, - "content": { - "json": "### ZAP by action type
\r\n\r\n**Distribution of Microsoft Teams post-delivery ZAP actions by type.**" - }, - "customWidth": "33", - "name": "teams zap pie header", - "styleSettings": { - "margin": "10px", - "padding": "0px" - }, - "id": "9bc0d0a3-876a-49d7-9046-31764511ca38" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises Microsoft Teams post-delivery ZAP actions over time by ZAP type, summarizing the data per selected interval.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(MessagePostDeliveryEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(MessagePostDeliveryEvents | summarize max(Timestamp));\r\nlet agg = materialize(MessagePostDeliveryEvents\r\n| summarize MalwareZAP = countif(ActionType == \"Malware ZAP\"), PhishZAP = countif(ActionType == \"Phish ZAP\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, MalwareZAP = coalesce(MalwareZAP, 0), PhishZAP = coalesce(PhishZAP, 0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "chartSettings": { - "xAxis": "Timestamp" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "66", - "name": "teams zap trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "c78a509e-324f-4a8c-b2e7-bce3e0d20667" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query shows Microsoft Teams post-delivery ZAP actions by type for the selected period.\r\nMessagePostDeliveryEvents\r\n| summarize Count = count() by ActionType", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "33", - "name": "teams zap pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "cfc94695-fb02-4b6c-a223-f79f7b947379" - }, - { - "type": 1, - "content": { - "json": "### Top senders whose messages were removed by ZAP
\r\n\r\n**Senders whose Microsoft Teams messages were most often removed by post-delivery ZAP.**" - }, - "customWidth": "100", - "name": "teams zap senders header", - "id": "f8677ffe-007a-41ca-81de-1ae5dd19d06a" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query lists the top 10 senders whose Microsoft Teams messages were removed by post-delivery ZAP for the selected period.\r\nMessagePostDeliveryEvents\r\n| where isnotempty(SenderEmailAddress)\r\n| summarize ZapActions = count(), MalwareZAP = countif(ActionType == \"Malware ZAP\"), PhishZAP = countif(ActionType == \"Phish ZAP\") by SenderEmailAddress\r\n| top 10 by ZapActions\r\n| project ['Sender']=SenderEmailAddress, ['ZAP Actions']=ZapActions, ['Malware ZAP']=MalwareZAP, ['Phish ZAP']=PhishZAP", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "ZAP Actions", - "formatter": 3, - "formatOptions": { - "palette": "redDark" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams zap senders table", - "id": "50c9a883-6442-40dc-b84f-57adfbb46a38" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "14" - }, - "name": "group - Teams ZAP", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "f5cc2425-e5ae-4520-9a97-2e4c2c447dcd" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Teams Message and Call Submissions\r\n
\r\n\r\nMicrosoft Teams messages and calls reported by users, and messages submitted by admins, for review by Microsoft. Sourced from the submission records in CloudAppEvents.

**Recommended action:** Encourage users to report suspicious Teams messages and calls so Microsoft can tune protection, and triage admin submissions promptly. A cluster of reports naming the same sender, display name, or call identity is an early signal of a targeted campaign: pivot those identities into the impersonation and risky-sender views above to scope it." - }, - "name": "teams sub banner", - "id": "54cbfb29-2626-4b65-8cb5-a42ff4b41e63" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query summarizes Microsoft Teams message and call submissions reported to Microsoft for the selected period, split by user and admin reports. Only completed submissions are counted (submission triage/timeout lifecycle records are excluded).\r\nlet sub = materialize(CloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType in (\"ChatMessage\", \"TeamsCall\"));\r\nunion\r\n(sub | where SubmissionContentType == \"ChatMessage\" and ActionType == \"UserSubmission\" | summarize Count = count() | extend Details = \"Messages Reported by Users\", Ord = 1),\r\n(sub | where SubmissionContentType == \"TeamsCall\" and ActionType == \"UserSubmission\" | summarize Count = count() | extend Details = \"Calls Reported by Users\", Ord = 2),\r\n(sub | where SubmissionContentType == \"ChatMessage\" and ActionType == \"AdminSubmission\" | summarize Count = count() | extend Details = \"Messages Submitted by Admins\", Ord = 3)\r\n| sort by Ord asc\r\n| project Count, Details", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "secondaryContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 0, - "palette": "blue" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "showBorder": true, - "size": "full" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams sub tiles", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "419ed645-ebc1-4df1-b9f0-c744403ab494" - }, - { - "type": 1, - "content": { - "json": "### Submissions over time
\r\n\r\n**Microsoft Teams user and admin submissions (per selected interval).**" - }, - "customWidth": "66", - "name": "teams sub trend header", - "styleSettings": { - "margin": "10px", - "padding": "0px" - }, - "id": "6a795b0a-82e2-427a-8ac0-abfb5bb5e447" - }, - { - "type": 1, - "content": { - "json": "### Submission mix
\r\n\r\n**Microsoft Teams submissions split by content type (message or call) and reporter (user or admin).**" - }, - "customWidth": "33", - "name": "teams sub pie header", - "styleSettings": { - "margin": "10px", - "padding": "0px" - }, - "id": "1f4c55f8-7290-4b6f-b02a-e3134568b9ff" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises Microsoft Teams message and call submissions over time, summarizing the data per selected interval. Only completed submissions are counted (submission triage/timeout lifecycle records are excluded).\r\nlet gran = {Granularity};\r\nlet sub = materialize(CloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType in (\"ChatMessage\", \"TeamsCall\"));\r\nlet minTime = toscalar(sub | summarize min(Timestamp));\r\nlet maxTime = toscalar(sub | summarize max(Timestamp));\r\nlet agg = materialize(sub\r\n| summarize UserReports = countif(ActionType == \"UserSubmission\"), AdminReports = countif(ActionType == \"AdminSubmission\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, UserReports = coalesce(UserReports, 0), AdminReports = coalesce(AdminReports, 0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "chartSettings": { - "xAxis": "Timestamp" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "66", - "name": "teams sub trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "7dcb03da-de96-4388-90a4-0a3f3ca98dc6" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query shows the mix of Microsoft Teams submissions by content type and reporter for the selected period. Only completed user submissions (chat and call) and admin submissions (chat) are counted; submission triage/timeout lifecycle records are excluded.\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\"\r\n| where (SubmissionContentType == \"ChatMessage\" and ActionType == \"UserSubmission\")\r\n or (SubmissionContentType == \"TeamsCall\" and ActionType == \"UserSubmission\")\r\n or (SubmissionContentType == \"ChatMessage\" and ActionType == \"AdminSubmission\")\r\n| extend Reporter = iif(ActionType == \"AdminSubmission\", \"Admin\", \"User\")\r\n| summarize Count = count() by SubmissionType = strcat(SubmissionContentType, \" (\", Reporter, \")\")", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "33", - "name": "teams sub pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "84a0141e-51de-4423-acb0-3c4342a49bf2" - }, - { - "type": 1, - "content": { - "json": "### False Negative (FN) User Submissions by submission State
\r\n\r\n**Microsoft Teams messages reported by users as missed detections, broken down by submission state (for example Rescaned, Graded). Tracks the processing status of user reports.**" - }, - "customWidth": "50", - "name": "teams sub state header", - "styleSettings": { - "margin": "10px", - "padding": "0px" - }, - "id": "1b2bdffd-69b0-41b0-bdda-b242b7faaec0" - }, - { - "type": 1, - "content": { - "json": "### False Negative (FN) User Submissions by Triage Verdict
\r\n\r\n**Microsoft Teams user submissions grouped by the verdict assigned during grading (for example Phishing, NotSpam, Spam). Shows how reported messages were graded and highlights detection gaps.**" - }, - "customWidth": "50", - "name": "teams sub verdict header", - "styleSettings": { - "margin": "10px", - "padding": "0px" - }, - "id": "bdb97e09-44d2-41ad-a99f-931e4a8169cc" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query shows Microsoft Teams user (false negative) message submissions by submission state (for example Rescaned, Graded), to track processing status.\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend SubmissionState = tostring(RD.SubmissionState)\r\n| summarize Count = count() by tostring(SubmissionState)", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "teams sub state pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "139ce840-5fc2-44d1-9872-91b37a74f0e7" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query shows Microsoft Teams user (false negative) message submissions by the triage verdict assigned during grading (for example Phishing, NotSpam, Spam).\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend TriageVerdict = tostring(parse_json(tostring(RD.GradingResult)).TriageVerdict)\r\n| where isnotempty(TriageVerdict)\r\n| summarize Count = count() by TriageVerdict", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "teams sub verdict pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "538ce4a3-a1ff-4b8d-a466-2173edbb2cd7" - }, - { - "type": 1, - "content": { - "json": "### Top 10 P2 sender domains in FN User Submissions
\r\n\r\n**The sender domains most often reported by users as missed Microsoft Teams threats. High-volume domains are candidate sources of malicious messaging.**" - }, - "customWidth": "50", - "name": "teams sub domains header", - "styleSettings": { - "margin": "10px", - "padding": "0px" - }, - "id": "9b8db0c7-2bf2-4077-ae20-60146001bf23" - }, - { - "type": 1, - "content": { - "json": "### Top 10 individual P2 senders in FN User Submissions
\r\n\r\n**The individual senders most often reported by users as missed Microsoft Teams threats.**" - }, - "customWidth": "50", - "name": "teams sub senders header", - "styleSettings": { - "margin": "10px", - "padding": "0px" - }, - "id": "ffbe90ab-129c-47fa-9dac-50cab528ad55" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query lists the top 10 P2 (envelope) sender domains of Microsoft Teams messages reported by users as false negatives (missed detections).\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend P2SenderDomain = tostring(RD.P2SenderDomain)\r\n| where isnotempty(P2SenderDomain)\r\n| summarize Submissions = count() by ['P2 Sender Domain']=P2SenderDomain\r\n| top 10 by Submissions", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true, - "formatters": [ - { - "columnMatch": "Submissions", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "teams sub domains table", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "b18192fb-26a8-4bd1-9b07-7aeab496eae3" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query lists the top 10 individual P2 (envelope) senders of Microsoft Teams messages reported by users as false negatives (missed detections).\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend P2Sender = tostring(RD.P2Sender)\r\n| where isnotempty(P2Sender)\r\n| summarize Submissions = count() by ['P2 Sender']=P2Sender\r\n| top 10 by Submissions", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true, - "formatters": [ - { - "columnMatch": "Submissions", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "teams sub senders table", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "7ead0a01-2b56-4225-b625-554b09350013" - }, - { - "type": 1, - "content": { - "json": "### Top 10 users performing the most FN User Submissions
\r\n\r\n**The users who report the most Microsoft Teams messages as missed detections - useful for recognising engaged reporters and spotting over-reporting.**" - }, - "customWidth": "50", - "name": "teams sub topusers header", - "styleSettings": { - "margin": "10px", - "padding": "0px" - }, - "id": "fb893cdd-d6d3-431a-a1d2-87652571a10d" - }, - { - "type": 1, - "content": { - "json": "### Top 10 admins performing the most FN Admin Submissions
\r\n\r\n**The admins who submit the most Microsoft Teams messages as missed detections.**" - }, - "customWidth": "50", - "name": "teams sub topadmins header", - "styleSettings": { - "margin": "10px", - "padding": "0px" - }, - "id": "14fca69b-e152-4a5d-bd2c-020c34c2226a" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query lists the top 10 users who reported the most Microsoft Teams messages as false negatives (missed detections), with each submitter's email (from the submission record) to disambiguate users with similar names.\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"UserSubmission\"\r\n| extend Submitter = tostring(RD.SubmitterDisplayName), SubmitterEmail = tostring(RD.UserId)\r\n| where isnotempty(Submitter) and SubmitterEmail has \"@\"\r\n| summarize Submissions = count() by ['Submitter']=Submitter, ['Email']=SubmitterEmail\r\n| top 10 by Submissions", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "teams sub topusers table", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "a171a35b-35b0-46ce-a916-052a54101126" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query lists the top 10 admins who submitted the most Microsoft Teams messages as false negatives (missed detections). The admin's own email is not present in the submission record (that would require the Identity table), so the Submitter ID (object GUID) is shown to disambiguate admins with similar names.\r\nCloudAppEvents\r\n| extend RD = parse_json(RawEventData)\r\n| extend RecordType = tostring(RD.RecordType), SubmissionContentType = tostring(RD.SubmissionContentType)\r\n| where RecordType == \"29\" and SubmissionContentType == \"ChatMessage\"| where ActionType startswith \"AdminSubmission\"\r\n| extend Submitter = tostring(RD.SubmitterDisplayName), SubmitterId = tostring(RD.SubmitterId)\r\n| where isnotempty(Submitter)\r\n| summarize Submissions = count() by ['Admin']=Submitter, ['Submitter ID']=SubmitterId\r\n| top 10 by Submissions", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "teams sub topadmins table", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "8bf37c2b-067a-4341-a192-2aa45699c3f7" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "14" - }, - "name": "group - Teams Submissions", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "eeea53a4-69d9-426e-bf9f-1789cd73bfed" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Recent Threat Detail\r\n
\r\n\r\nThe most recent Microsoft Teams phishing and malware messages, de-duplicated to the latest record per message, for investigation." - }, - "name": "teams detail banner", - "id": "4bdd917c-721f-450b-b455-45cbd5f59cc5" - }, - { - "type": 1, - "content": { - "json": "### Last 10 Teams phishing messages
\r\n\r\n**Most recent Microsoft Teams messages detected as phishing, with sender, delivery action, safety tip, team/group, and subject. TeamsMessageId is included to pivot to Advanced Hunting.**" - }, - "customWidth": "100", - "name": "teams detail phish header", - "id": "9bcf96c1-a958-4515-b171-10ec2f3ba660" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query lists the 10 most recent Microsoft Teams messages detected as phishing by Microsoft Defender for Office 365, de-duplicated to the latest record per message. TeamsMessageId is included so analysts can pivot to Advanced Hunting.\r\nMessageEvents\r\n| where ThreatTypes has \"Phish\"\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| top 10 by Timestamp desc\r\n| project ['Time']=Timestamp, ['Sender']=SenderEmailAddress, ['Threat Types']=ThreatTypes, ['Delivery Action']=DeliveryAction, ['Safety Tip']=SafetyTip, ['Team / Group']=GroupName, ['External Thread']=IsExternalThread, ['Subject']=MessageSubject, TeamsMessageId", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams detail phish table", - "id": "3675d08f-1165-4f47-a633-e432cf96e3d5" - }, - { - "type": 1, - "content": { - "json": "### Last 10 Teams malware messages
\r\n\r\n**Most recent Microsoft Teams messages detected as malware, with sender, delivery action, safety tip, team/group, and subject. TeamsMessageId is included to pivot to Advanced Hunting.**" - }, - "customWidth": "100", - "name": "teams detail mal header", - "id": "6b9d66d2-8d89-47b0-a72a-5ee8623082dc" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query lists the 10 most recent Microsoft Teams messages detected as malware by Microsoft Defender for Office 365, de-duplicated to the latest record per message. TeamsMessageId is included so analysts can pivot to Advanced Hunting.\r\nMessageEvents\r\n| where ThreatTypes has \"Malware\"\r\n| summarize arg_max(Timestamp, *) by TeamsMessageId\r\n| top 10 by Timestamp desc\r\n| project ['Time']=Timestamp, ['Sender']=SenderEmailAddress, ['Threat Types']=ThreatTypes, ['Delivery Action']=DeliveryAction, ['Safety Tip']=SafetyTip, ['Team / Group']=GroupName, ['External Thread']=IsExternalThread, ['Subject']=MessageSubject, TeamsMessageId", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "teams detail mal table", - "id": "d6e76d0a-7eee-4c05-8e92-10f9622b5ab3" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "14" - }, - "name": "group - Teams Detail", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "1e9c879b-d6be-4d36-9068-b5438abf7dd2" - }, - { - "type": 1, - "content": { - "json": "# Top Attacked Users, Top Senders, and Automatic External Email Forwarding\r\n\r\n---\r\nThis tab provides insights into **Top attacked users, Top Senders** in inbound email messages and details about **automatic external email forwarding**." - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "6" - }, - "name": "text - 24 - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "f1a60054-44b1-432e-be7a-9d7d114ff5c7" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Top Attacked Users and Top Senders Insights\r\n
\r\n\r\nThis section provides key visuals that highlight top attacked users – individuals most frequently targeted by inbound email threats as detected by Microsoft Defender for Office 365. Offers insights into top email senders and sender domains across inbound email traffic, helping identify patterns and potential risk sources.

**Recommended action:** Apply the Strict preset to the most-attacked users and review the top sender domains as possible block-list candidates." - }, - "name": "text - 13 - Copy - Copy", - "id": "ff220902-30b8-4aef-9b79-14c913a1b2d2" - }, - { - "type": 1, - "content": { - "json": "### Top Attacked Users
\r\n\r\n**Displays the top 10 recipient email addresses that received inbound emails flagged as Spam, Phishing, or Malware. Helps identify high-risk users for targeted security awareness and policy enforcement.**" - }, - "name": "text - 13 - Copy - Copy - Copy", - "id": "58f34b9f-824d-4fcf-b2aa-d7d380aa08d5" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "// This query visualises the top 10 users that are receiving Spam, Phishing or Malware emails\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\" and EmailDirection ==\"Inbound\"\r\n| extend MDO_detection = parse_json(DetectionMethods) \r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),MalwareEmailCount = countif(FirstDetection == \"Malware\"),PhishEmailCount = countif(FirstDetection == \"Phish\"),SpamEmailCount = countif(FirstDetection == \"Spam\") by RecipientEmailAddress\r\n| extend ThreatEmailCount=(MalwareEmailCount+PhishEmailCount+SpamEmailCount)\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(ThreatEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| top 15 by ThreatEmailCount\r\n| project ['Recipient']=RecipientEmailAddress, ['Total Emails']=TotalEmailCount, ['Threat Emails']=ThreatEmailCount, ['Malware']=MalwareEmailCount, ['Phish']=PhishEmailCount, ['Spam']=SpamEmailCount, ['Bad Traffic %']=Bad_Traffic_Percentage_Inbound", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Total Emails", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Threat Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Malware", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Phish", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Spam", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Bad Traffic %", - "formatter": 4, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - }, - "formatOptions": { - "palette": "red", - "min": 0, - "max": 20 - } - } - ], - "filter": true, - "sortBy": [ - { - "itemKey": "$gen_bar_Threat Emails_2", - "sortOrder": 2 - } - ] - }, - "sortBy": [ - { - "itemKey": "$gen_bar_Threat Emails_2", - "sortOrder": 2 - } - ], - "chartSettings": { - "createOtherGroup": 10 - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - 28", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "e9459e78-6b43-4ef2-9596-32169d95c610" - }, - { - "type": 1, - "content": { - "json": "### Top 10 Senders of Inbound Emails
\r\n\r\n**Displays the top 10 sender email addresses from external sources delivering inbound emails. Helps identify high-volume external senders for monitoring and policy enforcement.**" - }, - "name": "text - 13 - Copy - Copy - Copy - Copy", - "id": "eb4590a7-57c7-4728-af62-3d798afe6f2d" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "// This query visualises the top 10 senders by inbound email sending volume\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\" and EmailDirection ==\"Inbound\"\r\n| extend MDO_detection = parse_json(DetectionMethods) \r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),MalwareEmailCount = countif(FirstDetection == \"Malware\"),PhishEmailCount = countif(FirstDetection == \"Phish\"),SpamEmailCount = countif(FirstDetection == \"Spam\") by SenderFromAddress\r\n| extend ThreatEmailCount=(MalwareEmailCount+PhishEmailCount+SpamEmailCount)\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(ThreatEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| top 15 by TotalEmailCount\r\n| project ['Sender']=SenderFromAddress, ['Total Emails']=TotalEmailCount, ['Threat Emails']=ThreatEmailCount, ['Malware']=MalwareEmailCount, ['Phish']=PhishEmailCount, ['Spam']=SpamEmailCount, ['Bad Traffic %']=Bad_Traffic_Percentage_Inbound", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Total Emails", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Threat Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Malware", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Phish", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Spam", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Bad Traffic %", - "formatter": 4, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - }, - "formatOptions": { - "palette": "red", - "min": 0, - "max": 20 - } - } - ], - "filter": true - }, - "chartSettings": { - "createOtherGroup": 10 - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - 28 - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "e4272979-1073-4c1e-9b1b-b971bc3efc33" - }, - { - "type": 1, - "content": { - "json": "### Top 10 Sender Domains of Inbound Emails
\r\n\r\n**Displays the top 10 sender domains from external sources delivering inbound emails. Helps identify high-volume external sender domains for monitoring and policy enforcement.**" - }, - "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", - "id": "7ab63415-17ce-47f1-a614-e5e6edbe472e" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "// This query visualises the top 10 senders by inbound email sending volume\r\nEmailEvents \r\n| where OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\" and EmailDirection ==\"Inbound\"\r\n| extend MDO_detection = parse_json(DetectionMethods) \r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalEmailCount=count(),MalwareEmailCount = countif(FirstDetection == \"Malware\"),PhishEmailCount = countif(FirstDetection == \"Phish\"),SpamEmailCount = countif(FirstDetection == \"Spam\") by SenderFromDomain\r\n| extend ThreatEmailCount=(MalwareEmailCount+PhishEmailCount+SpamEmailCount)\r\n| extend Bad_Traffic_Percentage_Inbound = todouble(round(ThreatEmailCount / todouble(TotalEmailCount) *100, 2))\r\n| top 15 by TotalEmailCount\r\n| project ['Sender Domain']=SenderFromDomain, ['Total Emails']=TotalEmailCount, ['Threat Emails']=ThreatEmailCount, ['Malware']=MalwareEmailCount, ['Phish']=PhishEmailCount, ['Spam']=SpamEmailCount, ['Bad Traffic %']=Bad_Traffic_Percentage_Inbound", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Total Emails", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Threat Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Malware", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Phish", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Spam", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Bad Traffic %", - "formatter": 4, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - }, - "formatOptions": { - "palette": "red", - "min": 0, - "max": 20 - } - } - ], - "filter": true - }, - "chartSettings": { - "createOtherGroup": 10 - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - 28 - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "b593da94-b735-4fe3-a82d-18c90156e506" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "6" - }, - "name": "group - 10-Top attacked users and top senders", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "3e41cc1a-166e-4094-bc66-7e26a918b2e9" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Automatic External Email Forwarding Insights\r\n
\r\n\r\n**Email forwarding can be useful, but can also pose a security risk due to the potential disclosure of information.**\r\n
\r\n\r\nUsers can configure [Inbox rules](https://support.microsoft.com/en-US/Outlook/mail/use-rules-to-automatically-forward-messages) in Outlook or set up [SMTP forwarding](https://support.microsoft.com/en-us/office/turn-on-automatic-forwarding-in-outlook-7f2670a1-7fff-4475-8a3c-5822d63b0c8e) to automatically forward messages to external recipients. You can control automatic external email forwarding from cloud mailboxes using [Outbound spam policies](https://learn.microsoft.com/en-us/defender-office-365/outbound-spam-policies-external-email-forwarding) in Microsoft Defender for Office 365. \r\n**Attackers might exploit this capability to compromise your organization or its partners.**

**Recommended action:** Investigate external auto-forwarding - it is a common data-exfiltration path. Consider disabling auto-forwarding via the outbound spam policy unless a business case is documented." - }, - "name": "text - 8", - "id": "b04d1590-98e3-4650-9172-33e75561e1e5" - }, - { - "type": 1, - "content": { - "json": "### Automatic Email Forwarding by Type
\r\n\r\n**Displays counts of outbound emails automatically forwarded to external addresses, grouped by forwarding type (e.g., SMTP forwarding, inbox rules). Helps identify forwarding behaviors that may pose data exfiltration risks.**" - }, - "customWidth": "50", - "name": "text - 13 - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "c7cb7917-eaf4-4a1e-989a-75f4b6182851" - }, - { - "type": 1, - "content": { - "json": "### Top 10 Internal Users Forwarding Emails Externally
\r\n\r\n**Displays the top 10 internal user accounts that have automatically forwarded emails to external addresses (regardless of the forwarding type used). Helps identify potential data exfiltration risks and enforce forwarding policies.**" - }, - "customWidth": "50", - "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "5a5d5a8c-c195-45db-a878-e6ac908cc919" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "// This query visualises automatic email forwarding to external email addresses by forwarding type\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| summarize count() by ForwardingType\r\n| sort by count_ desc \r\n", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "chartSettings": { - "yAxis": [ - "count_" - ], - "createOtherGroup": 10 - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 30 - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "15094d98-add2-4b50-a0df-ee91fd34c6fb" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "// This query visualises the top 10 internal senders who are automatically forwarding emails to external email addresses\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| summarize TotalForwardedMessages = count() by ForwardingUser\r\n| sort by TotalForwardedMessages desc \r\n| top 10 by TotalForwardedMessages\r\n| project ['Forwarding User']=ForwardingUser, ['Forwarded Messages']=TotalForwardedMessages\r\n\r\n", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Forwarded Messages", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "chartSettings": { - "yAxis": [ - "TotalForwardedMessages" - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 30 - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "73d66038-2ea0-449d-9aeb-a1bd4b207d7f" - }, - { - "type": 1, - "content": { - "json": "### Top 10 Internal Users Forwarding Emails Using Mailbox Rules
\r\n\r\n**Displays the top 10 internal user accounts that have automatically forwarded outbound emails to external addresses using Mailbox Rules. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" - }, - "customWidth": "100", - "name": "text - 13 - Copy - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "9a7b5fc3-da23-4e95-87df-542a5e3f6320" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "// This query visualises the top 10 internal senders who are automatically forwarding emails to external email addresses using Mailbox Rules\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| where ForwardingType ==\"MbxRule\"\r\n| summarize TotalForwardedMessages = count() by ForwardingUser\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Forwarding User']=ForwardingUser, ['Forwarded Messages']=TotalForwardedMessages", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Forwarded Messages", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "chartSettings": { - "yAxis": [ - "TotalForwardedMessages" - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - 30 - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "f8d7b85d-944a-493f-a143-7e18277846c9" - }, - { - "type": 1, - "content": { - "json": "### Top 10 External domains Receiving Auto-Forwarded Emails (Mailbox Rules)
\r\n\r\n**Displays the top 10 external recipient email domains that received automatically forwarded emails from internal users via Mailbox Rules. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" - }, - "customWidth": "50", - "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "cda99a50-b7c4-4d95-ac61-7231080a3f5d" - }, - { - "type": 1, - "content": { - "json": "### Top 10 External Recipients Receiving Auto-Forwarded Emails (Mailbox Rules)
\r\n\r\n**Displays the top 10 external recipient email addresses that received automatically forwarded emails from internal users via Mailbox Rules. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" - }, - "customWidth": "50", - "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "72b01575-c33e-457c-98db-ea755c003bf0" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "// This query visualises the top 10 external domains who are recieving automatically forwarded emails using Mailbox Rules\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser),RecipientDomain = tostring(split(RecipientEmailAddress, \"@\")[1])\r\n| where ForwardingType ==\"MbxRule\"\r\n| summarize TotalForwardedMessages = count() by RecipientDomain\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Recipient Domain']=RecipientDomain, ['Forwarded Messages']=TotalForwardedMessages", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Forwarded Messages", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "chartSettings": { - "yAxis": [ - "count_" - ], - "createOtherGroup": 10 - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 30 - Copy - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "823dec28-48b5-4be3-8e68-04301a952a62" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "// This query visualises the top 10 external recipients who are recieving automatically forwarded emails using Mailbox Rules\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| where ForwardingType ==\"MbxRule\"\r\n| summarize TotalForwardedMessages = count() by RecipientEmailAddress\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Recipient']=RecipientEmailAddress, ['Forwarded Messages']=TotalForwardedMessages", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Forwarded Messages", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "chartSettings": { - "yAxis": [ - "count_" - ], - "createOtherGroup": 10 - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 30 - Copy - Copy - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "14804990-bfc9-43b7-8c8d-95c2cf32ee56" - }, - { - "type": 1, - "content": { - "json": "### Top 10 Internal Users Forwarding Emails via SMTP Forwarding
\r\n\r\n**Displays the top 10 internal user accounts that have automatically forwarded outbound emails to external addresses using SMTP Forwarding. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" - }, - "customWidth": "100", - "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "fa04b313-5756-4ff7-9ee8-ec61e6b382cc" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "// This query visualises the top 10 internal senders who are automatically forwarding emails to external email addresses using SmtpForwarding\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| where ForwardingType ==\"SmtpForwarding\"\r\n| summarize count() by ForwardingUser\r\n| top 10 by count_ desc\r\n| project ['Forwarding User']=ForwardingUser, ['Forwarded Messages']=count_", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "chartSettings": { - "yAxis": [ - "count_" - ], - "createOtherGroup": 10 - }, - "gridSettings": { - "formatters": [ - { - "columnMatch": "Forwarded Messages", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - 30 - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "bed8e717-4ea7-4f71-aaa7-b70a31f4dc88" - }, - { - "type": 1, - "content": { - "json": "### Top 10 External domains receiving Auto-Forwarded Emails (SMTP Forwarding)
\r\n\r\n**Displays the top 10 external recipient email domains that received automatically forwarded emails from internal users using SMTP Forwarding. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" - }, - "customWidth": "50", - "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "f76bc717-3cf8-4d8d-92fa-3f2024065f8f" - }, - { - "type": 1, - "content": { - "json": "### Top 10 External Recipients Receiving Auto-Forwarded Emails (SMTP Forwarding)
\r\n\r\n**Displays the top 10 external recipient email addresses that received automatically forwarded emails from internal users using SMTP Forwarding. Helps identify potential data exfiltration risks and enforce forwarding restrictions.**" - }, - "customWidth": "50", - "name": "text - 13 - Copy - Copy - Copy - Copy - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "2190c799-ab4f-4bd8-87e1-f9c5c224cca4" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "// This query visualises the top 10 external recipients who are recieving automatically forwarded emails using SmtpForwarding\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser),RecipientDomain = tostring(split(RecipientEmailAddress, \"@\")[1])\r\n| where ForwardingType ==\"SmtpForwarding\"\r\n| summarize TotalForwardedMessages = count() by RecipientDomain\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Recipient Domain']=RecipientDomain, ['Forwarded Messages']=TotalForwardedMessages", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Forwarded Messages", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "chartSettings": { - "yAxis": [ - "count_" - ], - "createOtherGroup": 10 - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 30 - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "c3be87b3-8ce8-40f2-ad92-0651bed71117" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "// This query visualises the top 10 external recipients who are recieving automatically forwarded emails using SmtpForwarding\r\nEmailEvents \r\n| where EmailDirection == \"Outbound\" and ForwardingInformation !=\"\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ForwardingType = tostring((parse_json(ForwardingInformation)).ForwardingType),ForwardingUser=tostring((parse_json(ForwardingInformation)).ForwardingUser)\r\n| where ForwardingType ==\"SmtpForwarding\"\r\n| summarize TotalForwardedMessages = count() by RecipientEmailAddress\r\n| top 10 by TotalForwardedMessages desc\r\n| project ['Recipient']=RecipientEmailAddress, ['Forwarded Messages']=TotalForwardedMessages", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Forwarded Messages", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "chartSettings": { - "yAxis": [ - "count_" - ], - "createOtherGroup": 10 - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 30 - Copy - Copy - Copy - Copy - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "fb6b0113-f5bb-46a7-994b-92ebc3c7881d" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "6" - }, - "name": "group - 34 - Automatic email forwarding", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "02c91ebb-4f92-4843-a73b-6dea7a6ac2bd" - }, - { - "type": 1, - "content": { - "json": "# Email detection action overrides\r\n\r\n---\r\n\r\nThis tab provides insights into admin or end-user configured **detection overrides** where the message was detected as a threat by Microsoft Defender for Office 365, however an admin-configured policy or end-user setting overrode the detection action.[

Learn more

](https://learn.microsoft.com/en-us/defender-office-365/step-by-step-guides/understand-overrides-in-email-entity) " - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "7" - }, - "name": "text - 13 - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "ae594968-00b9-40b8-b5dd-052a27440afb" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Admin configured Detection Overrides (Allow)\r\n
\r\n\r\nThis section consolidates key visuals that track emails subject to administrator policies (e.g., Transport Rules, Tenant Allow/Block List) with an \"Allow\" action, overriding Microsoft Defender for Office 365 detections (excluding SecOps Mailbox overrides).

**Recommended action:** Review Allow overrides that later carried threats and remove stale or overly broad allow entries - they weaken protection." - }, - "name": "text - AdminOverridesAllowHeader", - "id": "3d70a304-c590-4156-a6d4-da147fe106ab" - }, - { - "type": 1, - "content": { - "json": "### Admin Overrides (Allow) Trend\r\n**Displays the count (per {Granularity}) of emails where an administrator policy with an \"Allow\" action overrode detections (excluding SecOps Mailbox). Helps track the frequency of admin overrides over time.**" - }, - "name": "text - AdminOverridesAllowTrend", - "id": "a4ee104a-a0a1-4725-a60f-deedcc91af70" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the ammount of emails subject to an admin policy with action of allow independent of action taken, summarizing the data daily\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where isnotempty(OrgLevelPolicy) and OrgLevelPolicy!=\"SecOps Mailbox\" and OrgLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalAdminOverrides = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Admin Overrides'] = coalesce(TotalAdminOverrides, 0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "areachart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "Admin Overrides", - "color": "blueDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "name": "query - 3", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "79928e9e-48ed-4d08-8ff7-c21fe027550e" - }, - { - "type": 1, - "content": { - "json": "### Total Emails by Admin Override type (Allow)\r\n**Summarizes the total count of emails subject to administrator policies with an \"Allow\" action, grouped by the type of override. Helps identify which policies are most frequently allowing emails.**" - }, - "customWidth": "50", - "name": "text - AdminOverridesAllowByType", - "id": "855fce09-2000-4d16-8521-8b4eeddfae00" - }, - { - "type": 1, - "content": { - "json": "### Admin Overrides (Allow) by Override Type and Threat Type\r\n**Details the count of emails allowed by administrator policies, categorized by the override type and the detected threat type. Helps assess the risk associated with allowed emails.**" - }, - "customWidth": "50", - "name": "text - AdminOverridesAllowByTypeAndThreat", - "id": "a2613078-b427-4b23-aca0-21989b1944db" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the total ammount of emails subject to an admin policy with action of allow, independent of action taken, summarizing the data by type of override\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelPolicy!=\"SecOps Mailbox\" and OrgLevelAction == \"Allow\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by OrgLevelPolicy", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 16", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "b21a0329-8f52-45c2-81f2-6df65c134673" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the ammount of emails subject to an admin policy with action of allow, independent of action taken, summarizing the data by type of override and threats type found\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelPolicy!=\"SecOps Mailbox\" and OrgLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by OrgLevelAction,OrgLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=OrgLevelAction, ['Override Policy']=OrgLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Total Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 2", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "0bf4cbe6-7c84-49d4-801c-d955762b5699" - }, - { - "type": 1, - "content": { - "json": "### SecOps Mailbox Overrides (Allow)\r\nThis section focuses on emails allowed specifically due to the SecOps Mailbox override policy, typically used for investigation and analysis.[

Learn more

](https://learn.microsoft.com/en-us/defender-office-365/advanced-delivery-policy-configure) " - }, - "name": "text - SecOpsOverridesHeader", - "id": "f582dc86-4c40-4cdd-ba0b-ec6ef8820a27" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the total ammount of emails subject to the \r\nEmailEvents \r\n| where OrgLevelPolicy==\"SecOps Mailbox\" and OrgLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by OrgLevelPolicy", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "stat", - "statSettings": { - "valueAggregation": "None", - "colorSettings": { - "type": "static", - "mode": "background", - "heatmapPalette": "greenRed", - "thresholdsGrid": [] - }, - "iconSettings": { - "thresholdsGrid": [] - }, - "tagText": "", - "valueFontStyle": "auto", - "tagTextPosition": "bottom" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 1", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "8ad2fea4-dcd0-454e-a4d4-b5275c86fd9b" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the ammount of emails delivered to the SecOps Mailbox by threat type\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelPolicy==\"SecOps Mailbox\" and OrgLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by OrgLevelAction,OrgLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=OrgLevelAction, ['Override Policy']=OrgLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", - "size": 1, - "showAnalytics": true, - "title": " ", - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Total Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 4", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "52c04df2-69b5-46e4-a000-7c6d212a132a" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "7" - }, - "name": "group - 15 - Admin Detection Overrides - Allow", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "9b9baf2f-fd5f-41b6-8368-b515f8de4fd4" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Admin configured Detection Overrides (Block)\r\n
\r\n\r\nThis section provides insights into email messages blocked by administrative policies (e.g. Tenant allow/block list, Antimalware policy file type block), overriding detection actions defined by Microsoft Defender for Office 365.

**Recommended action:** Confirm these blocks are still needed and consolidate them into the Tenant Allow/Block List where appropriate." - }, - "name": "text - AdminOverridesBlockHeader", - "id": "6157683b-cce7-4165-886f-0da73e25ce86" - }, - { - "type": 1, - "content": { - "json": "### Admin Overrides (Block) Trend\r\n**Displays the count (per {Granularity}) of emails where an administrator policy with a \"Block\" action overrode detections. Helps track the frequency of admin blocks over time.**" - }, - "name": "text - AdminOverridesBlockTrend", - "id": "699820b4-a984-45cc-ab2f-607c3c8569d4" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the ammount of emails subject to an admin policy with action of block, summarizing the data daily\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where isnotempty(OrgLevelPolicy) and OrgLevelAction == \"Block\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalAdminOverrides = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Admin Overrides'] = coalesce(TotalAdminOverrides, 0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "areachart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "Admin Overrides", - "color": "blueDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - 5", - "styleSettings": { - "margin": "10", - "padding": "10" - }, - "id": "9ef5e7fb-843e-439b-b4f3-9b0bb149e74b" - }, - { - "type": 1, - "content": { - "json": "### Total Emails by Admin Override Type (Block)\r\n**Summarizes the total count of emails subject to administrator policies with a \"Block\" action, grouped by the type of override.**" - }, - "customWidth": "50", - "name": "text - AdminOverridesBlockByType", - "id": "5694a7c0-1ee5-40b4-ae2b-263d189c4b4e" - }, - { - "type": 1, - "content": { - "json": "### Admin Overrides (Block) by Override Type and Threat Type\r\n**Details the count of emails blocked by administrator policies, categorized by the override type and the detected threat type.**" - }, - "customWidth": "50", - "name": "text - AdminOverridesBlockByTypeAndThreat", - "id": "6e309742-37c0-4ad5-9b9a-63643059bfaf" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the total ammount of emails subject to an admin policy with action of block, summarizing the data by type of override\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelAction == \"Block\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by OrgLevelPolicy", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 6", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "eabc80ed-d0e9-43d2-ab13-a5af478f11c8" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the ammount of emails subject to an admin policy with action of block, summarizing the data by type of override and threats type found\r\nEmailEvents \r\n| where isnotempty(OrgLevelPolicy) and OrgLevelAction == \"Block\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by OrgLevelAction,OrgLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=OrgLevelAction, ['Override Policy']=OrgLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Total Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 7", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "1661bfa6-d8fd-4387-a334-1bc027a3f6d1" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "7" - }, - "name": "group - 36-Admin Detection Overrides - Block", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "7d514e9a-f67f-45a6-ba1b-6492348cc18b" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
User configured Detection Overrides (Allow)\r\n
\r\n\r\nThis section consolidates key visuals that track email messages subject to user policies (e.g. [Safe Senders list defined in Outlook](https://learn.microsoft.com/en-us/defender-office-365/create-safe-sender-lists-in-office-365#use-outlook-safe-senders)) with an \"Allow\" action, overriding Microsoft Defender for Office 365 detections.

**Recommended action:** Educate users that safe-sender allows can bypass protection; review high-risk user allow entries." - }, - "name": "text - UserOverridesAllowHeader", - "id": "4d41c560-0e73-40c5-b610-33e9500e88c4" - }, - { - "type": 1, - "content": { - "json": "### User Overrides (Allow) Trend\r\n**Displays the count (per {Granularity}) of emails where a user policy with an \"Allow\" action overrode detections. Helps track the frequency of user overrides over time.**" - }, - "name": "text - UserOverridesAllowTrend", - "id": "9432efff-9f03-4d74-8781-02be8b2d07fa" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the ammount of emails subject to a user type policy with action of allow, summarizing the data daily\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Allow\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalUserOverrides = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['User Overrides'] = coalesce(TotalUserOverrides, 0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "areachart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "User Overrides", - "color": "blueDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "name": "query - 3", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "02da1d33-e477-479d-bdd3-95ab1ad7c75c" - }, - { - "type": 1, - "content": { - "json": "### Total Emails by User Override Type (Allow)\r\n**Summarizes the total count of emails subject to user policies with an \"Allow\" action, grouped by the type of override.**" - }, - "customWidth": "50", - "name": "text - UserOverridesAllowByType", - "id": "006a2e87-b1b6-4cc3-a763-ceebaa86b340" - }, - { - "type": 1, - "content": { - "json": "### User Overrides (Allow) by Override Type and Threat Type\r\n**Details the count of emails allowed by user policies, categorized by the override type and the detected threat type. Helps assess the risk associated with user-allowed emails.**" - }, - "customWidth": "50", - "name": "text - UserOverridesAllowByTypeAndThreat", - "id": "7c34bb4b-46c0-4054-9596-3dfd010bb036" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the total ammount of emails subject to a user type policy with action of allow, summarizing the data by type of override\r\nEmailEvents \r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Allow\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by UserLevelPolicy", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 16", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "d1d9021d-e6bf-47b1-bdd2-438a212d2767" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the ammount of emails subject to a user type policy with action of allow, summarizing the data by type of override and threats type found\r\nEmailEvents \r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Allow\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by UserLevelAction,UserLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=UserLevelAction, ['Override Policy']=UserLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Total Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ] - }, - "sortBy": [], - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 2", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "1acd913c-c945-4a58-b04e-d008ca53ffe3" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "7" - }, - "name": "group - 15 - User Detection Overrides - Allow", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "c939060e-6a8b-49ff-951b-a3abddbd9fb4" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
User configured Detection Overrides (Block)\r\n
\r\n\r\nThis section provides insights into emails blocked by user-configured policies (e.g., [Blocked Senders list in Outlook](https://support.microsoft.com/en-us/office/block-or-unblock-senders-in-outlook-9bf812d4-6995-4d19-901a-76d6e26939b0)).

**Recommended action:** Use user block trends to identify unwanted senders that may warrant tenant-wide blocking." - }, - "name": "text - UserOverridesBlockHeader", - "id": "be6c6a3e-08ee-47c5-b8e7-6a1078dd17d1" - }, - { - "type": 1, - "content": { - "json": "### User Overrides (Block) Trend\r\n**Displays the count (per {Granularity}) of emails where a user policy with a \"Block\" action overrode detections. Helps track the frequency of user blocks over time.**" - }, - "name": "text - UserOverridesBlockTrend", - "id": "7cd77d54-2e2b-4d23-a6a9-4bd6bca2642a" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the ammount of emails subject to a user type policy with action of block, summarizing the data daily\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailEvents\r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Block\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize TotalUserOverrides = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['User Overrides'] = coalesce(TotalUserOverrides, 0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "areachart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "User Overrides", - "color": "blueDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "query - 5", - "styleSettings": { - "margin": "10", - "padding": "10" - }, - "id": "0b21b66c-001d-4b3d-b47f-f3a420ccaaf8" - }, - { - "type": 1, - "content": { - "json": "### Total Emails by User Override Type (Block)\r\n**Summarizes the total count of emails subject to user policies with a \"Block\" action, grouped by the type of override.**" - }, - "customWidth": "50", - "name": "text - UserOverridesBlockByType", - "id": "fd513501-5e9d-45d9-9d0d-cd546002b8cf" - }, - { - "type": 1, - "content": { - "json": "### User Overrides (Block) by Override Type and Threat Type\r\n**Details the count of emails blocked by user policies, categorized by the override type and the detected threat type.**" - }, - "customWidth": "50", - "name": "text - UserOverridesBlockByTypeAndThreat", - "id": "4fbfa876-47ed-4c3b-81ee-1c40b982cecd" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the total ammount of emails subject to a user type policy with action of block, summarizing the data by type of override\r\nEmailEvents \r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Block\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize count() by UserLevelPolicy", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 6", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "d3fccaa6-80fd-419d-bb37-aedf67263419" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the ammount of emails subject to a user type policy with action of block, summarizing the data by type of override and threats type found\r\nEmailEvents \r\n| where isnotempty(UserLevelPolicy) and UserLevelAction == \"Block\" \r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend ThreatTypes = case(ThreatTypes has \"Malware\", \"Malware\", ThreatTypes has \"Phish\", \"Phish\", ThreatTypes has \"Spam\", \"Spam\", ThreatTypes)\r\n| summarize TotalEmails=count() by UserLevelAction,UserLevelPolicy,ThreatTypes\r\n| sort by TotalEmails\r\n| project ['Override Action']=UserLevelAction, ['Override Policy']=UserLevelPolicy, ['Threat Type']=ThreatTypes, ['Total Emails']=TotalEmails", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Total Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "query - 7", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "e5e74ce1-fa67-45ea-bc80-97237342e370" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "7" - }, - "name": "group - 37-User Detection Overrides - Block", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "0c1d327a-c2f1-4b9b-b210-53c808b53b48" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
User & Sender Override Detail (Allow)\r\n
\r\n\r\nInbound messages that Microsoft Defender for Office 365 **detected as threats but delivered anyway** because of an admin- or user-configured **Allow** override (phishing-simulation and SecOps Mailbox traffic excluded). **Total Threats** is all detected threats to that recipient / sender domain in the selected range; **Overridden Threats** and **Override %** are the portion delivered due to an Allow override, and **Override Types** names the specific overrides responsible. **User-configured** overrides come from the recipient's own mailbox junk-email settings in Outlook / Outlook on the web (the mailbox \"safelist collection\") — the **Safe Senders** and **Safe Recipients** lists and **trusted contacts** (\"Also trust email from my Contacts\"). **Admin-configured** overrides come from the **Tenant Allow/Block List, Exchange mail flow (transport) rules, the IP Allow List, or allowed sender/domain lists in anti-spam policies**. Use this to spot users or domains where overrides are letting threats through — candidates for policy review or a Tenant Allow/Block List (TABL) block.

**Recommended action:** Focus on the users and sender domains with the most allow overrides - these are the biggest protection gaps." - }, - "name": "Overrides - User Detail Header", - "id": "3b0e83f3-f340-4b95-85c5-831783e8abc2" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Top recipients receiving threats that were delivered due to an admin or user override, with the share of their threats that were overridden and a breakdown of which override types caused them.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend OverrideType = case(\r\n OrgLevelAction == \"Allow\" and OrgLevelPolicy != \"\" and OrgLevelPolicy != \"SecOps Mailbox\", OrgLevelPolicy,\r\n UserLevelAction == \"Allow\", strcat(\"User: \", UserLevelPolicy),\r\n \"(none)\")\r\n| summarize PerType = count() by RecipientEmailAddress, OverrideType\r\n| summarize TotalThreats = sum(PerType),\r\n OverriddenThreats = sumif(PerType, OverrideType != \"(none)\"),\r\n OverrideTypes = strcat_array(make_set_if(strcat(OverrideType, \" (\", PerType, \")\"), OverrideType != \"(none)\"), \"; \")\r\n by RecipientEmailAddress\r\n| where OverriddenThreats > 0\r\n| extend OverridePercent = round(OverriddenThreats * 100.0 / TotalThreats, 1)\r\n| top 15 by OverriddenThreats\r\n| project ['Recipient']=RecipientEmailAddress, ['Total Threats']=TotalThreats, ['Overridden Threats']=OverriddenThreats, ['Override %']=OverridePercent, ['Override Types']=OverrideTypes", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Overridden Threats", - "formatter": 3, - "formatOptions": { - "palette": "redDark" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Override %", - "formatter": 4, - "formatOptions": { - "palette": "red", - "min": 0, - "max": 20 - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - } - ] - }, - "graphSettings": { - "type": 2, - "topContent": { - "columnMatch": "StatisticName", - "formatter": 1 - }, - "centerContent": { - "columnMatch": "Value", - "formatter": 1, - "numberFormat": { - "unit": 17, - "options": { - "maximumSignificantDigits": 3, - "maximumFractionDigits": 2 - } - } - }, - "nodeIdField": "StatisticName", - "sourceIdField": "Value", - "targetIdField": "Value", - "graphOrientation": 3, - "showOrientationToggles": false, - "nodeSize": null, - "staticNodeSize": 100, - "colorSettings": null, - "hivesMargin": 5, - "edgeColorSettings": null - }, - "timeContext": { - "durationMs": 0 - } - }, - "name": "Overrides - Top Users", - "id": "d7e169a2-808a-4bbf-86ee-5be561c690f7" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Top sender domains sending threats to users, with the share of those threats that were delivered because of an admin or user override and a breakdown of which override types caused them. High override rates are strong candidates for policy review or a Tenant Allow/Block List (TABL) block.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and OrgLevelPolicy != \"Phishing simulation\" and OrgLevelPolicy != \"SecOps Mailbox\"\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| extend OverrideType = case(\r\n OrgLevelAction == \"Allow\" and OrgLevelPolicy != \"\" and OrgLevelPolicy != \"SecOps Mailbox\", OrgLevelPolicy,\r\n UserLevelAction == \"Allow\", strcat(\"User: \", UserLevelPolicy),\r\n \"(none)\")\r\n| summarize PerType = count() by SenderFromDomain, OverrideType\r\n| summarize TotalThreats = sum(PerType),\r\n OverriddenThreats = sumif(PerType, OverrideType != \"(none)\"),\r\n OverrideTypes = strcat_array(make_set_if(strcat(OverrideType, \" (\", PerType, \")\"), OverrideType != \"(none)\"), \"; \")\r\n by SenderFromDomain\r\n| where OverriddenThreats > 0\r\n| extend OverridePercent = round(OverriddenThreats * 100.0 / TotalThreats, 1)\r\n| top 10 by OverriddenThreats\r\n| project ['Sender Domain']=SenderFromDomain, ['Total Threats']=TotalThreats, ['Overridden Threats']=OverriddenThreats, ['Override %']=OverridePercent, ['Override Types']=OverrideTypes", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Overridden Threats", - "formatter": 3, - "formatOptions": { - "palette": "redDark" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Override %", - "formatter": 4, - "formatOptions": { - "palette": "red", - "min": 0, - "max": 20 - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - } - ] - }, - "graphSettings": { - "type": 2, - "topContent": { - "columnMatch": "StatisticName", - "formatter": 1 - }, - "centerContent": { - "columnMatch": "Value", - "formatter": 1, - "numberFormat": { - "unit": 17, - "options": { - "maximumSignificantDigits": 3, - "maximumFractionDigits": 2 - } - } - }, - "nodeIdField": "StatisticName", - "sourceIdField": "Value", - "targetIdField": "Value", - "graphOrientation": 3, - "showOrientationToggles": false, - "nodeSize": null, - "staticNodeSize": 100, - "colorSettings": null, - "hivesMargin": 5, - "edgeColorSettings": null - }, - "timeContext": { - "durationMs": 0 - } - }, - "name": "Overrides - Top Sender Domains", - "id": "0eda3153-10ea-4d4e-80ca-7e5ad99e9883" - } - ] - }, - "customWidth": "100", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "7" - }, - "name": "Overrides - User & Sender Detail", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "d5f38e54-a3c7-4df6-b569-bbabe85e1a36" - }, - { - "type": 1, - "content": { - "json": "# False Negative(FN) Submissions insights\r\n\r\n---\r\n\r\nThis tab provides insights into email message **False Negative(FN) Submissions** performed by users or administrators in Microsoft Defender for Office 365 where the message reported to have **Malware, Phish or Spam threat** within its **content, URLs or attachments**." - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "8" - }, - "name": "text - 13 - Copy", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "3b243dca-89ce-41e6-bccb-9ceb0953aa2e" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
False Negative(FN) Admin submissions\r\n
\r\n\r\nThis section provides insights into email message **False Negative(FN) Submissions performed by administrators** in Microsoft Defender for Office 365 where the message reported to have Malware, Phish or Spam threat within its content, URLs or attachments.

**Recommended action:** Prioritise admin-submitted misses for policy tuning; recurring sender domains may be block-list candidates." - }, - "name": "fn admin - section header", - "id": "64420254-0dae-4495-bd55-fc49e5bc1ed0" - }, - { - "type": 1, - "content": { - "json": "### False Negative(FN) Admin Submissions per-{Granularity} trend by submission types \r\n**Displays counts (per {Granularity}) of False Negative(FN) Admin Submissions grouped by submission type (Spam, Phish, Malware) and content type (Mail, URL, Attachment). Helps to monitor where detections were missed and later submitted by admins as false negatives to Microsoft.**" - }, - "name": "fn admin - trend heading", - "id": "5f2de929-6f32-4079-a031-cbf689c15b29" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the daily ammount of admin false negative submission by submission type.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(CloudAppEvents\r\n| where ActionType contains \"Submission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| summarize Admin_Malware_FN=countif(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"), Admin_Phish_FN=countif(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"), Admin_Spam_FN=countif(SubmissionType == \"0\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"), Admin_Malware_URL_FN=countif(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\"), Admin_Malware_Attach_FN=countif(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\"), Admin_Phish_URL_FN=countif(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\"), Admin_Phish_Attach_FN=countif(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Malware (Mail)']=coalesce(Admin_Malware_FN,0), ['Phish (Mail)']=coalesce(Admin_Phish_FN,0), ['Spam (Mail)']=coalesce(Admin_Spam_FN,0), ['Malware (URL)']=coalesce(Admin_Malware_URL_FN,0), ['Malware (Attachment)']=coalesce(Admin_Malware_Attach_FN,0), ['Phish (URL)']=coalesce(Admin_Phish_URL_FN,0), ['Phish (Attachment)']=coalesce(Admin_Phish_Attach_FN,0) | sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "TotalAdminSubmissions", - "color": "redDark" - }, - { - "seriesName": "Phish (Mail)", - "color": "redBright" - }, - { - "seriesName": "Spam (Mail)", - "color": "orange" - }, - { - "seriesName": "Malware (Mail)", - "color": "redDark" - }, - { - "seriesName": "Phish (URL)", - "color": "purple" - }, - { - "seriesName": "Malware (Attachment)", - "color": "yellowDark" - }, - { - "seriesName": "Phish (Attachment)", - "color": "purpleDark" - }, - { - "seriesName": "Malware (URL)", - "color": "yellow" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "name": "fn admin - submissions trend", - "id": "1b61155b-92a1-4533-9561-2e85e9a4dbf8" - }, - { - "type": 1, - "content": { - "json": "### False Negative(FN) Admin Submissions by submission types \r\n**Displays counts (per {Granularity}) of False Negative(FN) Admin Submissions grouped by submission type (Spam, Phish, Malware) and content type (Mail, URL, Attachment).**" - }, - "customWidth": "50", - "name": "fn admin - by-type heading", - "id": "bbaa9ff9-a95d-495a-a44c-6b4cae888a24" - }, - { - "type": 1, - "content": { - "json": "### False Negative(FN) Admin Submissions by submission State\r\n**Displays the total count of False Negative(FN) Admin Submissions by submission State (e.g., Pending, Completed, Failed). Helps track the processing status of admin submissions and identify bottlenecks or errors.**" - }, - "customWidth": "50", - "name": "fn admin - by-state heading", - "id": "b060c706-342a-4b2e-b81a-920bf4d8c5d9" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the total ammount of admin false negative submission by submission type.\r\nCloudAppEvents \r\n| where ActionType contains \"Submission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| extend Admin_SubmissionType=\r\niff(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Malware (Mail)\",\r\niff(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\r\niff(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\",\"Malware (URL)\",\r\niff(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\",\"Malware (Attachment)\",\r\niff(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\",\"Phish (URL)\",\r\niff(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\",\"Phish (Attachment)\",\r\n\"Other\")))))))\r\n| where Admin_SubmissionType!=\"Other\"\r\n| summarize count() by Admin_SubmissionType", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "chartSettings": { - "createOtherGroup": 10 - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "fn admin - by-type pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "9d9d714a-357b-4ac3-bcb7-33601d3c3108" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the total ammount of admin false negative submissions by the state of the submission.\r\nCloudAppEvents \r\n| where ActionType contains \"AdminSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType in (\"0\",\"1\",\"2\")\r\n| summarize count() by tostring(SubmissionState)", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "fn admin - by-state pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "169f0f1c-1f1e-44fb-965e-850733f01879" - }, - { - "type": 1, - "content": { - "json": "### False Negative(FN)/False Positive(FP) Admin Submissions by Triage Verdict\r\n**Displays the total count of False Negative(FN)/False Positive(FP) Admin Submissions grouped by TriageVerdict (e.g., Malware, Spam, Phish, Clean). Helps assess how submissions were graded during triage and identify detection gaps.**" - }, - "customWidth": "50", - "name": "fn admin - triage-verdict heading", - "id": "3df841be-c1b0-4d61-8e38-316a34a48bd1" - }, - { - "type": 1, - "content": { - "json": "### Top Admins Submitting False Negatives \r\n**Displays the top 15 admin accounts that submitted the highest number of false negative messages (missed detections) via AdminSubmission. Helps identify key contributors to threat remediation and potential patterns in detection gaps.**" - }, - "customWidth": "50", - "name": "fn admin - top-admins heading", - "id": "e1e966f4-1f4d-4377-97c6-e2077fc0b8fa" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the total ammount of admin false negative or false positive submissions by the verdict of the submission grading.\r\nCloudAppEvents \r\n| where ActionType contains \"AdminSubmissionTriage\" \r\n| extend UserKey = (parse_json(RawEventData)).UserKey, SubmissionState = (parse_json(RawEventData)).SubmissionState, SubmissionId=(parse_json(RawEventData)).SubmissionId, TriageVerdict=(parse_json(RawEventData)).GradingResult.TriageVerdict \r\n| summarize count() by tostring(TriageVerdict)", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "fn admin - triage-verdict pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "6df0db72-f9db-444e-856a-4369921d199b" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the top admins performing false negative submissions\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend Record= (parse_json(RawEventData)).RecordType,SubmissionState = (parse_json(RawEventData)).SubmissionState, UserId = (parse_json(RawEventData)).UserId,SubmissionType = parse_json(RawEventData).SubmissionType \r\n| where Record == 29 and SubmissionType in (\"0\",\"1\",\"2\")\r\n| summarize ['Submissions']=count() by ['Admin']=tostring(UserId)\r\n| top 15 by ['Submissions'] desc", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "16ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "fn admin - top-admins pie", - "id": "b5ccb4a1-9783-47cf-bf21-ded924f1a200" - }, - { - "type": 1, - "content": { - "json": "### False Negative(FN) Admin Submissions by Top Sender Domains\r\n**For each top sender domain that admins reported missed threats for, shows the domain's MDO-detected threat profile (emails with threats and the Malware/Phish/Spam breakdown), the count of admin FN submissions, and the submission rate (Admin Submission % = admin submissions / total inbound from the domain). A high rate can flag a domain whose mail is frequently reported as missed.**" - }, - "customWidth": "100", - "name": "fn admin - top-sender-domains heading", - "id": "1a481c97-ac85-4b62-a86d-51b33b5a8e68" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Top 10 sender domains that admins reported false negatives (missed threats) for, with each domain's MDO-detected threat profile for context.\r\nlet subs = CloudAppEvents\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType), SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), P2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"2\",\"1\",\"0\")\r\n| summarize AdminSubmissions=count() by P2SenderDomain;\r\nlet domainProfile = EmailEvents\r\n| where EmailDirection == \"Inbound\"\r\n| summarize TotalInbound=count(), EmailsWithThreats=countif(isnotempty(ThreatTypes)), Malware=countif(ThreatTypes has \"Malware\"), Phish=countif(ThreatTypes has \"Phish\"), Spam=countif(ThreatTypes has \"Spam\") by SenderFromDomain;\r\nsubs\r\n| join kind=leftouter (domainProfile) on $left.P2SenderDomain == $right.SenderFromDomain\r\n| extend AdminSubmissionPct = round(AdminSubmissions * 100.0 / todouble(coalesce(TotalInbound, AdminSubmissions)), 2)\r\n| top 10 by AdminSubmissions desc\r\n| project ['Sender Domain']=P2SenderDomain, ['Emails With Threats']=coalesce(EmailsWithThreats,0), ['Malware']=coalesce(Malware,0), ['Phish']=coalesce(Phish,0), ['Spam']=coalesce(Spam,0), ['Admin Submissions']=AdminSubmissions, ['Admin Submission %']=AdminSubmissionPct", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Emails With Threats", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Malware", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "90px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Phish", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "90px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Spam", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "90px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Admin Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "120px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Admin Submission %", - "formatter": 4, - "formatOptions": { - "palette": "red", - "min": 0, - "max": 20, - "customColumnWidthSetting": "110px" - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "fn admin - top-sender-domains table", - "id": "e56bed92-b0fb-4b76-90f3-169f4206418b" - }, - { - "type": 1, - "content": { - "json": "### False Negative(FN) Admin Submissions by admin Detection override types\r\n**Displays the top 10 cases where emails were submitted as false negatives by admins, even though they were initially detected by Microsoft Defender for Office 365 but delivered due to an admin policy override. Includes details on PolicyOverride, PolicySource, and DetectionVerdict for deeper insight into override behaviour.**" - }, - "customWidth": "100", - "name": "fn admin - override-types heading", - "id": "293c174c-0197-4cf8-bbce-36fe42e5cf1b" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises emails submitted as false negatives by admins where emails where already detected by MDO but there was a admin policy override\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| extend Admin_SubmissionType=\r\niff(SubmissionType == \"2\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Malware (Mail)\",\r\niff(SubmissionType == \"1\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\"))),\r\nP2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain),NetworkMessageId=tostring((parse_json(RawEventData).ObjectId)),DetectionVerdict=tostring((parse_json(RawEventData)).DeliveryMessageInfo.FinalFilterVerdict),PolicyOverride=tostring((parse_json(RawEventData)).DeliveryMessageInfo.PolicyOverride),PolicyPolicyOverrideType=tostring((parse_json(RawEventData)).DeliveryMessageInfo.PolicySource)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"2\",\"1\",\"0\") and PolicyOverride !=\"NoOverride\"\r\n| summarize count() by PolicyOverride, PolicyPolicyOverrideType,DetectionVerdict,Admin_SubmissionType\r\n| top 10 by count_ desc\r\n| project ['Policy Override']=PolicyOverride, ['Override Source']=PolicyPolicyOverrideType, ['Detection Verdict']=DetectionVerdict, ['Submission Type']=Admin_SubmissionType, ['Emails']=count_", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "fn admin - override-types table", - "id": "97799422-53e0-4e3b-8103-297fd1c744eb" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "8" - }, - "name": "group - 11-Fn Admin Submissions", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "45a1c185-4fbf-4e83-832e-1f20af427796" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
False Negative(FN) User submissions\r\n
\r\n\r\nThis section provides insights into email message **False Negative(FN) Submissions performed by end users** in Microsoft Defender for Office 365 where the message reported as having Phish, Spam threat within its content, URLs or attachments.

**Recommended action:** Recognise engaged reporters, coach over-reporters, and use graded phishing verdicts to tune anti-phishing policy." - }, - "name": "fn user - section header", - "id": "ca0b48e6-8bd8-4f99-956a-f9c72cc870db" - }, - { - "type": 1, - "content": { - "json": "### False Negative(FN) User Submissions per-{Granularity} trend by submission types \r\n**Displays counts (per {Granularity}) of False Negative(FN) User Submissions grouped by submission type (Spam, Phish and Attack simulations) . Helps to monitor where detections were missed and later submitted by users as false negatives.**" - }, - "name": "fn user - trend heading", - "id": "60ac8608-7875-45e6-8c83-e6bd0c34af8b" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the daily ammount of users false negative submission by submission type, including phish simulations reported by users.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(CloudAppEvents\r\n| where ActionType contains \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| summarize User_Phish_FN=countif(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\"), User_Spam_FN=countif(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\"), User_AttackSim_Submission=countif(ActionType == \"AttackSimUserSubmission\" and SubmissionContentType==\"Mail\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Phish (Mail)']=coalesce(User_Phish_FN,0), ['Spam (Mail)']=coalesce(User_Spam_FN,0), ['Attack simulation reported']=coalesce(User_AttackSim_Submission,0) | sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "TotalAdminSubmissions", - "color": "redDark" - }, - { - "seriesName": "Phish (Mail)", - "color": "redDark" - }, - { - "seriesName": "Attack simulation reported", - "color": "green" - }, - { - "seriesName": "Spam (Mail)", - "color": "orangeDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "name": "fn user - submissions trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "29355816-6cba-4264-938e-b0b27afdcb12" - }, - { - "type": 1, - "content": { - "json": "### False Negative(FN) User Submissions by submission State\r\n**Displays the total count of False Negative(FN) User Submissions by submission State (e.g., Pending, Completed, Failed). Helps track the processing status of user submissions and identify bottlenecks or errors.**" - }, - "customWidth": "50", - "name": "fn user - by-state heading", - "id": "6a4b32cc-b7e4-47bb-b1b9-f415df7e629c" - }, - { - "type": 1, - "content": { - "json": "### False Negative(FN) User Submissions by Triage Verdict\r\n**Displays the total count of False Negative(FN)/False Positive(FP) User Submissions grouped by TriageVerdict (e.g., Malware, Spam, Phish, Clean). Helps assess how submissions were graded during triage and identify detection gaps.**" - }, - "customWidth": "50", - "name": "fn user - triage-verdict heading", - "id": "1427e34f-be44-4517-ae73-cc4776a49fe7" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the total ammount of user false negative submissions by the state of the submission.\r\nCloudAppEvents \r\n| where ActionType contains \"UserSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType in (\"0\",\"1\")\r\n| summarize count() by tostring(SubmissionState)", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "fn user - by-state pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "a6151271-e925-4804-a3c1-06afee27c026" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the total ammount of user false negative or false positive submissions by the verdict of the submission grading.\r\nCloudAppEvents \r\n| where ActionType contains \"UserSubmissionTriage\" \r\n| extend UserKey = (parse_json(RawEventData)).UserKey, SubmissionState = (parse_json(RawEventData)).SubmissionState, SubmissionId=(parse_json(RawEventData)).SubmissionId, TriageVerdict=(parse_json(RawEventData)).GradingResult.TriageVerdict \r\n| summarize count() by tostring(TriageVerdict)", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "fn user - triage-verdict pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "6ff319ea-b5c5-4e33-9e5c-065aadbf465d" - }, - { - "type": 1, - "content": { - "json": "### False Negative(FN) User Submissions of already detected Emails (from Junk folder)\r\n**Displays the total count of False Negative(FN) User Submissions where the email message was already detected by Microsoft Defender for Office 365 and the detection action was configured to deliver the message into the Junk folder of the user mailbox. It breaks down the result based on the original detection verdict determined by Microsoft Defender for Office 365. Helps track the user submissions of messages that already had a detection. Consider changing the detection action to Quarantine to avoid these submissions.**" - }, - "name": "fn user - junk-folder heading", - "id": "d6338907-489d-4c88-b82f-260fc0f9d302" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the total ammount of user false negative submissions that are already detected by MDO and already delivered in the junk folder\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where DeliveryLocation == \"Junk folder\"\r\n| summarize count() by ThreatTypes,User_SubmissionType\r\n| project ThreatTypes,User_SubmissionType, Emails = count_", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "fn user - junk-folder pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "c13452cb-e864-4f01-8623-51f3ea13bbbc" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the total ammount of user false negative submissions that are already detected by MDO and already delivered in the junk folder\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId,UserId = (parse_json(RawEventData)).UserId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where DeliveryLocation == \"Junk folder\"\r\n| extend MDO_detection = parse_json(DetectionMethods) \r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0])) \r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\") \r\n| summarize TotalJunkSubmittedEmailCount=count(),PhishEmailCount = countif(FirstDetection == \"Phish\"),SpamEmailCount = countif(FirstDetection == \"Spam\") by tostring(UserId)\r\n| top 15 by TotalJunkSubmittedEmailCount desc\r\n| project ['User']=UserId, ['Junk Submissions']=TotalJunkSubmittedEmailCount, ['Phish']=PhishEmailCount, ['Spam']=SpamEmailCount", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Junk Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Phish", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Spam", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "fn user - junk-folder table", - "id": "b242f301-c9f7-41f9-aa73-03848bd58eae" - }, - { - "type": 1, - "content": { - "json": "### False Negative(FN) User Submissions - Admin review status (Mark and Notify)\r\n**Displays counts of False Negative(FN) User Submissions that were reviewed by admins and marked with a notify action. The Mark and Notify action also can be taken automatically with Automated investigation and response (AIR). Helps track cases where admins confirmed user reports and communicated the outcome, supporting transparency and user trust.**" - }, - "customWidth": "50", - "name": "fn user - mark-notify heading", - "id": "784bf171-53ae-4907-b2b0-7fc5039df231" - }, - { - "type": 1, - "content": { - "json": "### False Negative(FN) User Submissions accuracy vs Admin review verdict\r\n**Displays counts of False Negative(FN) User Submissions (Phish, Junk, NotJunk) compared to admin review results. Highlights whether submissions were Correct, Not Correct, or misclassified comparing user submission type with the Admin decision using Mark and Notify action in Microsoft Defender for Office 365 (e.g., “Phish reported as Junk”, “Reported but not malicious”).**" - }, - "customWidth": "50", - "name": "fn user - accuracy heading", - "id": "3d137383-6436-4213-9824-72f424b67290" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises user submissions where admin also performed 'mark and notify' action on the submission\r\nlet ReviewResults = CloudAppEvents | where ActionType == \"SubmissionNotification\" \r\n| extend SubmissionId = tostring(parse_json(RawEventData).SubmissionId)\r\n| extend Properties = parse_json(RawEventData.ExtendedProperties)\r\n| mv-expand element = Properties\r\n| where element.Name == \"AdminReviewResult\"\r\n| project SubmissionId, AdminReviewResult = element.Value;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionId = tostring(parse_json(RawEventData).SubmissionId), SubmissionType = parse_json(RawEventData).SubmissionType\r\n| join kind=leftouter ReviewResults on SubmissionId\r\n| extend UserReportedAs=iif(SubmissionType == 1, \"Phish\",iif(SubmissionType == 2, \"Junk\",iif(SubmissionType == 3, \"NotJunk\",\"\")))\r\n| extend ReviewedAccuracy=iif(UserReportedAs==AdminReviewResult, 1,0)\r\n| extend Reviewed=iif(isempty(AdminReviewResult),\"Not Reviewed\",\"Reviewed\")\r\n| project SubmissionId,UserReportedAs,Reviewed,AdminReviewResult, ReviewedAccuracy\r\n| summarize count() by Reviewed", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "fn user - mark-notify pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "7bb7d116-bd61-4e46-81dd-d634a31e7369" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises user submissions type compared to admin review verdict. \r\n//Eg. User reporting a phish but admin review is 'not threat found'\r\nlet ReviewResults = CloudAppEvents | where ActionType == \"SubmissionNotification\" \r\n| extend SubmissionId = tostring(parse_json(RawEventData).SubmissionId)\r\n| extend Properties = parse_json(RawEventData.ExtendedProperties)\r\n| mv-expand element = Properties\r\n| where element.Name == \"AdminReviewResult\"\r\n| project SubmissionId, AdminReviewResult = element.Value;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionId = tostring(parse_json(RawEventData).SubmissionId), SubmissionType = parse_json(RawEventData).SubmissionType\r\n| join kind=leftouter ReviewResults on SubmissionId\r\n| extend UserReportedAs=iif(SubmissionType == 1, \"Phish\",iif(SubmissionType == 2, \"Junk\",iif(SubmissionType == 3, \"NotJunk\",\"\")))\r\n| extend ReviewedAccuracy=iif(AdminReviewResult==UserReportedAs, \"Correct\", iif(AdminReviewResult==\"Phish\" and UserReportedAs == \"Junk\", \"Phish reported as junk\",iif(AdminReviewResult==\"Junk\" and UserReportedAs == \"Phish\",\"Junk reported as Phish\",iif(AdminReviewResult==\"NotJunk\",\"Reported but not malicious or spam\",iif(isempty(AdminReviewResult),\"Not Reviewed\",\"Not correct\")))))\r\n| extend Reviewed=iif(isempty(AdminReviewResult),\"Not Reviewed\",\"Reviewed\")\r\n| project SubmissionId,UserReportedAs,Reviewed,AdminReviewResult, ReviewedAccuracy\r\n| where Reviewed==\"Reviewed\"\r\n| summarize count() by ReviewedAccuracy", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "fn user - accuracy pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "8af1b9f0-995c-4c58-9960-8e69c6960987" - }, - { - "type": 1, - "content": { - "json": "### Top 10 P2 Email Senders domains in False Negative(FN) User Submissions \r\n**Displays the top 10 P2 email sender domains of inbound emails reported by users as false negatives (missed detections). Includes total inbound email volume and calculates the percentage of user submissions per domain to highlight high-risk sources.**" - }, - "customWidth": "100", - "name": "fn user - top-p2-domains heading", - "id": "78dab1f9-09ec-46e2-aee4-f256e368cdd5" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises top 10 sender domains of inbound emails submitted as false negatives by users.\r\nlet TotalInboundbySender=\r\nEmailEvents\r\n| where EmailDirection ==\"Inbound\"\r\n| summarize count() by SenderFromDomain;\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType),RecipientObjectId=AccountObjectId,NetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\"\r\n| summarize UserSubmissions=count() by SenderFromDomain\r\n| join TotalInboundbySender on SenderFromDomain\r\n| extend UserSubmissions_Percentage = todouble(round(UserSubmissions / todouble(count_) * 100, 2))\r\n| top 10 by UserSubmissions desc\r\n| project ['Sender Domain']=SenderFromDomain, ['User Submissions']=UserSubmissions, ['Total Inbound']=count_, ['User Submission %']=UserSubmissions_Percentage", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "User Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "14ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Total Inbound", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "User Submission %", - "formatter": 4, - "formatOptions": { - "customColumnWidthSetting": "12ch", - "palette": "red", - "min": 0, - "max": 20 - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "fn user - top-p2-domains table", - "id": "6e6a59d4-70e1-4d85-bebb-6bb23d25d2d9" - }, - { - "type": 1, - "content": { - "json": "### Top 10 P2 Individual Email Senders in False Negative(FN) User Submissions \r\n**Displays the top 10 P2 individual email sender addresses of inbound emails reported by users as false negatives (missed detections). Includes total inbound email volume and calculates the percentage of user submissions per sender to highlight high-risk sources.**" - }, - "customWidth": "100", - "name": "fn user - top-p2-senders heading", - "id": "a6e8fda5-dd05-49ed-87e2-16443495396e" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises top 10 sender email addresses of inbound emails submitted as false negatives by users.\r\nlet TotalInboundbySender=\r\nEmailEvents\r\n| where EmailDirection ==\"Inbound\"\r\n| summarize count() by SenderFromAddress;\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType),P2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain),RecipientObjectId=AccountObjectId,NetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\"\r\n| summarize UserSubmissions=count() by SenderFromAddress\r\n| join TotalInboundbySender on SenderFromAddress\r\n| extend UserSubmissions_Percentage = todouble(round(UserSubmissions / todouble(count_) * 100, 2))\r\n| top 10 by UserSubmissions desc\r\n| project ['Sender Address']=SenderFromAddress, ['User Submissions']=UserSubmissions, ['Total Inbound']=count_, ['User Submission %']=UserSubmissions_Percentage", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "User Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "14ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Total Inbound", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "User Submission %", - "formatter": 4, - "formatOptions": { - "customColumnWidthSetting": "12ch", - "palette": "red", - "min": 0, - "max": 20 - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "fn user - top-p2-senders table", - "id": "878fd15f-2607-4d6d-b919-0b4bea6a1850" - }, - { - "type": 1, - "content": { - "json": "### Top 10 Intra-org Email Senders in False Negative(FN) User Submissions \r\n**Displays the top 10 email senders of intra-org emails reported by users as false negatives (missed detections). Includes total intra-org email volume and calculates the percentage of user submissions per sender to highlight high-risk sources.**" - }, - "customWidth": "100", - "name": "fn user - intraorg-senders heading", - "id": "87a51814-7f01-42e3-aea2-4136c869d39d" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises top 10 sender email address of intra-org emails submitted as false negatives by users.\r\nlet TotalInboundbySender=\r\nEmailEvents\r\n| where EmailDirection ==\"Intra-org\"\r\n| summarize count() by SenderFromAddress;\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType),P2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain),RecipientObjectId=AccountObjectId,NetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Intra-org\"\r\n| summarize UserSubmissions=count() by SenderFromAddress\r\n| join TotalInboundbySender on SenderFromAddress\r\n| extend UserSubmissions_Percentage = todouble(round(UserSubmissions / todouble(count_) * 100, 2))\r\n| top 10 by UserSubmissions desc\r\n| project ['Sender Address']=SenderFromAddress, ['User Submissions']=UserSubmissions, ['Total Intra-org']=count_, ['User Submission %']=UserSubmissions_Percentage", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "User Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "14ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Total Intra-org", - "formatter": 0, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "User Submission %", - "formatter": 4, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - }, - "formatOptions": { - "palette": "red", - "min": 0, - "max": 20, - "customColumnWidthSetting": "12ch" - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "fn user - intraorg-senders table", - "id": "38edca4b-a403-41e8-8c2b-7c0595e93b7a" - }, - { - "type": 1, - "content": { - "json": "### Top 10 Intra-org Email Subjects in False Negative(FN) User Submissions \r\n**Displays the top 10 Email Subjects of intra-org emails reported by users as false negatives (missed detections). Helps to highlight high-risk intra-org email sources.**" - }, - "customWidth": "100", - "name": "fn user - intraorg-subjects heading", - "id": "52b0bc5b-7e54-4a5b-a487-8a736a8c2397" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises top 10 subjects of intra-org emails submitted as false negatives by users.\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Intra-org\"\r\n| summarize count() by Subject\r\n| top 10 by count_ desc\r\n| project ['Subject']=Subject, ['User Submissions']=count_", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Subject", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "70ch" - } - }, - { - "columnMatch": "User Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "fn user - intraorg-subjects table", - "id": "ee2c1d2e-3d4e-4024-8422-985b22cb7475" - }, - { - "type": 1, - "content": { - "json": "### Top 10 Detection Overrides defined by Admins in False Negative(FN) User Submissions \r\n**Displays the top 10 use cases where users submitted emails as false negatives (Spam or Phish) that were already detected by Microsoft Defender for Office 365 but delivered due to an admin-defined policy override. Includes details on OrgLevelAction, OrgLevelPolicy, and ThreatTypes for deeper insight into override behaviour.**" - }, - "customWidth": "100", - "name": "fn user - admin-override heading", - "id": "0dd9b3ce-9716-42bb-93de-495f0af2d075" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises emails submitted as false negatives by users where emails where already detected by MDO but there was an admin definded policy override.\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where ThreatTypes !=\"\"and OrgLevelAction!=\"\"\r\n| summarize count() by OrgLevelAction, OrgLevelPolicy,ThreatTypes,User_SubmissionType\r\n| top 10 by count_ desc\r\n| project ['Override Action']=OrgLevelAction, ['Override Policy']=OrgLevelPolicy, ['Threat Type']=ThreatTypes, ['Submission Type']=User_SubmissionType, ['User Submissions']=count_", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Override Policy", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "48ch" - } - }, - { - "columnMatch": "User Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "fn user - admin-override table", - "id": "100de6ca-beb0-44d7-a715-449a389e9e8a" - }, - { - "type": 1, - "content": { - "json": "### Top 10 Detection Overrides defined by Users in False Negative(FN) User Submissions \r\n**Displays the top 10 use cases where users submitted emails as false negatives (Spam or Phish) that were already detected by Microsoft Defender for Office 365 but delivered due to a user-defined override. Includes details on UserLevelAction, UserLevelPolicy, and ThreatTypes for deeper insight into override behaviour.**" - }, - "customWidth": "100", - "name": "fn user - user-override heading", - "id": "67057c7d-c0af-4373-b23a-4001fbced888" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises emails submitted as false negatives by users where emails where already detected by MDO but there was an policy override.\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType), RecipientObjectId=AccountObjectId\r\n| extend User_SubmissionType=\r\niff(SubmissionType == \"1\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Phish (Mail)\",\r\niff(SubmissionType == \"0\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\",\"Spam (Mail)\",\"Other\")),\r\nNetworkMessageId=tostring((parse_json(RawEventData).ObjectId))\r\n| where SubmissionContentType == \"Mail\" and SubmissionType in (\"1\",\"0\")\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where ThreatTypes !=\"\"and UserLevelAction!=\"\"\r\n| summarize count() by UserLevelAction, UserLevelPolicy,ThreatTypes,User_SubmissionType\r\n| top 10 by count_ desc\r\n| project ['Override Action']=UserLevelAction, ['Override Policy']=UserLevelPolicy, ['Threat Type']=ThreatTypes, ['Submission Type']=User_SubmissionType, ['User Submissions']=count_", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Override Policy", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "48ch" - } - }, - { - "columnMatch": "User Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "fn user - user-override table", - "id": "1b97f7d2-152d-4eb0-bfac-e161fbfa4046" - }, - { - "type": 1, - "content": { - "json": "### Top 10 users performing the most False Negative(FN) User Submissions\r\n**Displays the Top 10 user accounts that performed the highest number of False Negative(FN) User Submissions (missed detections). Helps identify individuals most engaged in reporting suspicious, malicious messages and potential patterns in detection gaps.**" - }, - "customWidth": "100", - "name": "fn user - top-users heading", - "id": "7799a0a0-a835-4080-b59a-736b08ad809e" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the top 10 users performing false negative submissions\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType in (\"0\",\"1\")\r\n| extend UserId = (parse_json(RawEventData)).UserId\r\n| summarize ['Submissions']=count() by ['User']=tostring(UserId)\r\n| top 10 by ['Submissions'] desc", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "16ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "fn user - top-users pie", - "id": "44838734-43a0-4301-9ddb-a644c7ec509a" - }, - { - "type": 1, - "content": { - "json": "### Top 10 users performing the most User Submissions of Attack simulation messages\r\n**Displays the top 10 user accounts that reported phishing simulation emails during cyber security awareness campaigns. Supports evaluation of cyber security awareness programme effectiveness and identifies highly engaged users.**" - }, - "customWidth": "100", - "name": "fn user - attacksim-users heading", - "id": "8a96e90f-765f-40c0-8476-30c97d43c328" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the top users reporting the phishing simulation emails.\r\nCloudAppEvents \r\n| extend Record= (parse_json(RawEventData)).RecordType \r\n| extend SubmissionState = (parse_json(RawEventData)).SubmissionState \r\n| extend UserId = (parse_json(RawEventData)).UserId\r\n| where Record == 29\r\n| where ActionType == \"AttackSimUserSubmission\" \r\n| summarize ['Submissions']=count() by ['User']=tostring(UserId)\r\n| top 10 by ['Submissions'] desc", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "16ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "fn user - attacksim-users pie", - "id": "ab648c4a-4c46-4c73-96f0-784c9bcef961" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "8" - }, - "name": "group - 11 - FN User submissions", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "348ce24a-7cbc-4b66-a471-dfe3827bed2d" - }, - { - "type": 1, - "content": { - "json": "# False Positive(FP) Submissions insights\r\n\r\n---\r\n\r\nThis tab provides insights into email message **False Positive(FP) Submissions** performed by users or administrators in Microsoft Defender for Office 365 where the message was flagged as a threat by Microsoft Defender for Office 365 but was later reported as No Threat by administrators or users." - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "10" - }, - "name": "fp - tab description", - "id": "78e2df52-a0d2-499a-95fe-708f67db5ad6" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
False Positive(FP) Admin Submissions\r\n
\r\n\r\nAdministrator submissions represent escalated false positive reports submitted by security team members rather than end users. These typically involve more complex cases requiring expert review, such as recurring issues affecting multiple users, business-critical communications being blocked, or suspected policy misconfigurations. Admin submissions carry higher priority and can result in actions as allow-list additions or global policy changes to prevent widespread user impact.

**Recommended action:** Review recurring false-positive sender domains and consider allow entries or policy tuning to reduce business disruption." - }, - "name": "fp admin - section header", - "id": "02d54e9c-e989-4cde-a128-68a6381ed9d7" - }, - { - "type": 1, - "content": { - "json": "### Admin Submission Volume and Type Breakdown\r\n\r\n**These charts track the volume and composition of administrator-initiated false positive submissions. The trend chart shows submission patterns (per {Granularity}) across Email, URL, and Attachment types, while the pie chart reveals the distribution among these categories. Spikes in admin submissions often signal systemic issues requiring immediate policy review, as admins typically escalate only the most impactful or recurring problems.**" - }, - "name": "fp admin - volume/type heading", - "id": "103b8362-a10f-4b46-a757-8290c4269a5c" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the daily ammount of admin false positive submission by submission type.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(CloudAppEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(CloudAppEvents | summarize max(Timestamp));\r\nlet agg = materialize(CloudAppEvents\r\n| where ActionType contains \"Submission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| summarize Admin_Email_FP=countif(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\"), Admin_URL_FP=countif(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\"), Admin_Attach_FP=countif(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\") by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Email']=coalesce(Admin_Email_FP,0), ['URL']=coalesce(Admin_URL_FP,0), ['Attachment']=coalesce(Admin_Attach_FP,0) | sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "TotalAdminSubmissions", - "color": "redDark" - }, - { - "seriesName": "Admin_Phish_FN", - "color": "redBright" - }, - { - "seriesName": "Admin_Spam_FN", - "color": "orange" - }, - { - "seriesName": "Admin_Malware_FN", - "color": "redDark" - }, - { - "seriesName": "Admin_Phish_URL_FN", - "color": "purple" - }, - { - "seriesName": "Admin_Malware_Attach_FN", - "color": "yellowDark" - }, - { - "seriesName": "Admin_Phish_Attach_FN", - "color": "purpleDark" - }, - { - "seriesName": "Admin_Malware_URL_FN", - "color": "yellow" - }, - { - "seriesName": "Admin_Email_FP", - "color": "redDark" - }, - { - "seriesName": "Admin_URL_FP", - "color": "orangeDark" - }, - { - "seriesName": "Admin_Attach_FP", - "color": "yellow" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "66", - "name": "fp admin - submissions trend", - "id": "326762ca-1f2b-48e9-90d6-ff2aa6a75e95" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the total ammount of admin false positive submission by submission type.\r\nCloudAppEvents \r\n| where ActionType contains \"Submission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| extend Admin_SubmissionType=\r\niff(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\",\"Email\",\r\niff(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"URL\",\"URL\",\r\niff(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Attachment\",\"Attachment\",\r\n\"Other\")))\r\n| where Admin_SubmissionType!=\"Other\"\r\n| summarize count() by Admin_SubmissionType", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "chartSettings": { - "createOtherGroup": 10 - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "33", - "name": "fp admin - by-type pie", - "id": "be925c4c-5718-4385-8e82-59c57b975ac5" - }, - { - "type": 1, - "content": { - "json": "### False Positive(FP) Admin Submissions by submission state
\r\n\r\n**Displays the total count of False Positive(FP) Admin Submissions by submission State (e.g., Pending, Completed, Failed). Helps track the processing status of admin submissions and identify bottlenecks or errors.**" - }, - "customWidth": "50", - "name": "fp admin - by-state heading", - "id": "2b2acb67-c070-48bd-acf1-025c05aae8b5" - }, - { - "type": 1, - "content": { - "json": "### Top Admins Submitting False Positives
\r\n\r\n**Displays the top 15 admin accounts that submitted the highest number of false positive messages via AdminSubmission.**" - }, - "customWidth": "50", - "name": "fp admin - top-admins heading", - "id": "52206f40-fae9-460f-97b8-2cf9b633098f" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the total ammount of admin false positive submissions by the state of the submission.\r\nCloudAppEvents \r\n| where ActionType contains \"AdminSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType == \"3\"\r\n| summarize count() by tostring(SubmissionState)", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "fp admin - by-state pie", - "id": "96133d9e-24fb-417e-a3cd-df98dda4c60a" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the top admins performing false positive submissions.\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend Record= (parse_json(RawEventData)).RecordType,SubmissionState = (parse_json(RawEventData)).SubmissionState, UserId = (parse_json(RawEventData)).UserId,SubmissionType = parse_json(RawEventData).SubmissionType \r\n| where Record == 29 and SubmissionType ==\"3\"\r\n| summarize ['Submissions']=count() by ['Admin']=tostring(UserId)\r\n| top 15 by ['Submissions'] desc", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "16ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "fp admin - top-admins pie", - "id": "da7b4c89-904d-4917-b6cd-04b32e02d4a1" - }, - { - "type": 1, - "content": { - "json": "### Admin Submission False Positive Malware Detection Breakdown\r\n**Shows the count of administrator-submitted false positive reports (legitimate emails flagged as malware) grouped by the detection method that flagged them. Helps identify which filtering technologies most often misclassify valid messages as malware.**" - }, - "customWidth": "100", - "name": "fp admin - malware-detection heading", - "id": "69d649e0-86fd-4c08-afd4-e6c200b11c86" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Admin false positive submissions whose original verdict was Malware, grouped by the detection method that flagged them. A high count means that method most often misclassifies legitimate mail as Malware.\r\nlet total = toscalar(CloudAppEvents\r\n | where ActionType == \"AdminSubmissionSubmitted\"\r\n | extend R = parse_json(RawEventData)\r\n | where tostring(R.SubmissionContentType) == \"Mail\" and tostring(R.SubmissionType) == \"3\" and tostring(R.DeliveryMessageInfo.FinalFilterVerdict) == \"Malware\"\r\n | count);\r\nCloudAppEvents\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), DetectionMethod = tostring(R.DeliveryMessageInfo.FinalFilterVerdictControlSource), DetectionVerdict = tostring(R.DeliveryMessageInfo.FinalFilterVerdict), P2SenderDomain = tostring(R.P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\" and DetectionVerdict == \"Malware\"\r\n| extend DetectionMethod = iif(isempty(DetectionMethod), \"Not specified\", DetectionMethod)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(P2SenderDomain) by DetectionMethod\r\n| extend Pct = iif(total == 0, 0.0, round(FPSubmissions * 100.0 / total, 1))\r\n| sort by FPSubmissions desc\r\n| project ['Detection Method'] = DetectionMethod, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains, ['% of Malware FPs'] = Pct", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "FP Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Distinct Sender Domains", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "20ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "% of", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "14ch" - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "fp admin - malware-detection table", - "id": "607eb19b-1ded-488d-98db-8b23f9e90967" - }, - { - "type": 1, - "content": { - "json": "### Admin Submission False Positive Phish Detection Breakdown\r\n**Shows the count of administrator-submitted false positive reports (legitimate emails flagged as phishing) grouped by the detection method that flagged them. Helps identify which filtering technologies most often misclassify valid messages as phishing.**" - }, - "customWidth": "100", - "name": "fp admin - phish-detection heading", - "id": "c1f1e12f-d0aa-4023-9172-8182772b3331" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Admin false positive submissions whose original verdict was Phish, grouped by the detection method that flagged them. A high count means that method most often misclassifies legitimate mail as Phish.\r\nlet total = toscalar(CloudAppEvents\r\n | where ActionType == \"AdminSubmissionSubmitted\"\r\n | extend R = parse_json(RawEventData)\r\n | where tostring(R.SubmissionContentType) == \"Mail\" and tostring(R.SubmissionType) == \"3\" and tostring(R.DeliveryMessageInfo.FinalFilterVerdict) == \"Phish\"\r\n | count);\r\nCloudAppEvents\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), DetectionMethod = tostring(R.DeliveryMessageInfo.FinalFilterVerdictControlSource), DetectionVerdict = tostring(R.DeliveryMessageInfo.FinalFilterVerdict), P2SenderDomain = tostring(R.P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\" and DetectionVerdict == \"Phish\"\r\n| extend DetectionMethod = iif(isempty(DetectionMethod), \"Not specified\", DetectionMethod)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(P2SenderDomain) by DetectionMethod\r\n| extend Pct = iif(total == 0, 0.0, round(FPSubmissions * 100.0 / total, 1))\r\n| sort by FPSubmissions desc\r\n| project ['Detection Method'] = DetectionMethod, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains, ['% of Phish FPs'] = Pct", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "FP Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Distinct Sender Domains", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "20ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "% of", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "14ch" - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "fp admin - phish-detection pie", - "id": "b6c074f9-affa-41a3-802a-53541394ae73" - }, - { - "type": 1, - "content": { - "json": "### Admin Submission False Positive Spam Detection Breakdown\r\n**Shows the count of administrator-submitted false positive reports (legitimate emails flagged as spam) grouped by the detection method that flagged them. Helps identify which filtering technologies most often misclassify valid messages as spam.**" - }, - "customWidth": "100", - "name": "fp admin - spam-detection heading", - "id": "f0f2adb9-34af-4df0-90e6-087a265bedf6" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Admin false positive submissions whose original verdict was Spam, grouped by the detection method that flagged them. A high count means that method most often misclassifies legitimate mail as Spam.\r\nlet total = toscalar(CloudAppEvents\r\n | where ActionType == \"AdminSubmissionSubmitted\"\r\n | extend R = parse_json(RawEventData)\r\n | where tostring(R.SubmissionContentType) == \"Mail\" and tostring(R.SubmissionType) == \"3\" and tostring(R.DeliveryMessageInfo.FinalFilterVerdict) == \"Spam\"\r\n | count);\r\nCloudAppEvents\r\n| where ActionType == \"AdminSubmissionSubmitted\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), DetectionMethod = tostring(R.DeliveryMessageInfo.FinalFilterVerdictControlSource), DetectionVerdict = tostring(R.DeliveryMessageInfo.FinalFilterVerdict), P2SenderDomain = tostring(R.P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\" and DetectionVerdict == \"Spam\"\r\n| extend DetectionMethod = iif(isempty(DetectionMethod), \"Not specified\", DetectionMethod)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(P2SenderDomain) by DetectionMethod\r\n| extend Pct = iif(total == 0, 0.0, round(FPSubmissions * 100.0 / total, 1))\r\n| sort by FPSubmissions desc\r\n| project ['Detection Method'] = DetectionMethod, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains, ['% of Spam FPs'] = Pct", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "FP Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Distinct Sender Domains", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "20ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "% of", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "14ch" - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "fp admin - spam-detection pie", - "id": "e877d9c9-3bd3-4368-997e-945f18ffcf5f" - }, - { - "type": 1, - "content": { - "json": "### Top 10 Sender Domains for Admin False Positive Submissions
\r\n\r\n**Lists the top 10 sender domains of emails reported as false positives by administrators (legitimate messages incorrectly flagged as spam or phishing). Helps identify domains frequently misclassified.**" - }, - "customWidth": "50", - "name": "fp admin - top-sender-domains heading", - "id": "37680101-7e4b-4bcc-9e7e-0ccd2d914881" - }, - { - "type": 1, - "content": { - "json": "### Admin False Positive Submissions by Original Threat Verdict
\r\n\r\n**Displays all administrator-submitted false positive emails by their original filter verdict (e.g., spam, phishing) and policy override details. Helps identify which threat categories are most often misclassified.**" - }, - "customWidth": "50", - "name": "fp admin - by-verdict heading", - "id": "879e81ad-00a6-4a10-bcb6-56879133bb9f" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the top 10 sender domains of emails which are submitted as false positive by admins\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType),P2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType ==\"3\"\r\n| summarize count() by P2SenderDomain\r\n| top 10 by count_ desc\r\n| project ['Sender Domain']=P2SenderDomain, ['Emails']=count_", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "fp admin - top-sender-domains table", - "id": "42844dc9-4418-487b-a5ad-31e1f6b4b487" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises all emails submitted as false positive by admins summarizing by the original filter verdict threat type\r\nCloudAppEvents \r\n| where ActionType == \"AdminSubmissionSubmitted\" \r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| extend Admin_SubmissionType=\r\niff(SubmissionType == \"3\" and ActionType == \"AdminSubmissionSubmitted\" and SubmissionContentType==\"Mail\" ,\"Email\",\r\n\"Other\"),\r\nP2SenderDomain=tostring((parse_json(RawEventData)).P2SenderDomain),NetworkMessageId=tostring((parse_json(RawEventData).ObjectId)),DetectionVerdict=tostring((parse_json(RawEventData)).DeliveryMessageInfo.FinalFilterVerdict),PolicyOverride=tostring((parse_json(RawEventData)).DeliveryMessageInfo.PolicyOverride),PolicyPolicyOverrideType=tostring((parse_json(RawEventData)).DeliveryMessageInfo.PolicySource)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| summarize count() by PolicyOverride,DetectionVerdict,Admin_SubmissionType\r\n| top 10 by count_ desc\r\n| project ['Policy Override']=PolicyOverride, ['Detection Verdict']=DetectionVerdict, ['Submission Type']=Admin_SubmissionType, ['Emails']=count_", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Emails", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "40ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "fp admin - by-verdict table", - "id": "3ebbd402-06ef-45a7-b4ee-c5938b98b540" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "10" - }, - "name": "fp admin - group", - "styleSettings": { - "showBorder": true - }, - "id": "b6215b53-c181-4693-a14f-441809f65f38" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
False Positive (FP) User Submissions\r\n
\r\n\r\nThis section provides insights into email message False Postive(FP) Submissions performed by end users in Microsoft Defender for Office 365 where the message was flagged as a threat by Microsoft Defender for Office 365 but was later reported as No Threat by users. User submissions are critical feedback mechanisms that help security teams identify overly aggressive detection rules, refine security policies, and reduce user friction. High false positive rates can erode user trust and lead to security fatigue, so monitoring these metrics helps balance protection with productivity.

**Recommended action:** High user false-positive volume suggests over-aggressive filtering - review the affected senders and adjust policy." - }, - "name": "fp user - section header", - "id": "0d93d7ee-a61e-43b7-bdcd-172bd79ad050" - }, - { - "type": 1, - "content": { - "json": "### User Submission Trend\r\n\r\n**Displays the volume (per {Granularity}) of false positive submissions from end users. A sudden spike may indicate a new detection rule causing widespread misclassification, while a declining trend suggests improving detection accuracy. Monitoring this trend helps security teams respond quickly to detection issues before they impact user productivity.**" - }, - "name": "fp user - trend heading", - "id": "c3f8ae45-0498-4fa8-b9d1-35e926932639" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the daily ammount of user false positive submission by submission type.\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(CloudAppEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(CloudAppEvents | summarize max(Timestamp));\r\nlet agg = materialize(CloudAppEvents\r\n| where ActionType contains \"UserSubmission\"\r\n| extend SubmissionType = tostring((parse_json(RawEventData)).SubmissionType),SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where SubmissionType == \"3\" and ActionType == \"UserSubmission\" and SubmissionContentType==\"Mail\"\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['User FP Submissions'] = coalesce(Count, 0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "areachart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "User FP Submissions", - "color": "blueDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "fp user - submissions trend", - "id": "847032f5-56a8-4681-9665-9e917c7c9355" - }, - { - "type": 1, - "content": { - "json": "### User False Positive Submissions by State
\r\n\r\n**Displays the total number of user-reported false positive email submissions grouped by their processing state (e.g., pending, completed). Helps track submission workflow and resolution progress.**" - }, - "customWidth": "50", - "name": "fp user - by-state heading", - "id": "7bd03278-7734-4fbf-a502-95b42e90160e" - }, - { - "type": 1, - "content": { - "json": "### Top Users Performing False Positive Submissions
\r\n\r\n**Lists the top 15 users who reported emails as false positives (legitimate messages incorrectly flagged as threats). Helps identify frequent reporters and potential training or policy adjustment needs.**" - }, - "customWidth": "50", - "name": "fp user - top-users heading", - "id": "7e2b987b-325d-4f69-8d6b-fafd6676a03a" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the total ammount of user false positive submission by submission state.\r\nCloudAppEvents \r\n| where ActionType contains \"UserSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType == \"3\"\r\n| summarize count() by tostring(SubmissionState)", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "fp user - by-state pie", - "id": "df79d08b-3eac-4101-a3f2-3a4a3bf450ce" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the top users performing false positive submissions.\r\nCloudAppEvents \r\n| where ActionType == \"UserSubmission\" \r\n| extend Record = (parse_json(RawEventData)).RecordType,SubmissionState = parse_json(RawEventData).SubmissionState,SubmissionId=parse_json(RawEventData).SubmissionId,SubmissionType = parse_json(RawEventData).SubmissionType,SubmissionContentType=tostring((parse_json(RawEventData)).SubmissionContentType)\r\n| where Record == 29 and SubmissionType == \"3\"\r\n| extend UserId = (parse_json(RawEventData)).UserId\r\n| summarize ['Submissions']=count() by ['User']=tostring(UserId)\r\n| top 15 by ['Submissions'] desc", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "16ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "fp user - top-users pie", - "id": "ec7505d8-3a70-4bde-a985-baf5a0c4ec34" - }, - { - "type": 1, - "content": { - "json": "### User Submission False Positive Malware Detection Breakdown\r\n**Shows the count of user-submitted false positive reports (legitimate emails flagged as malware) grouped by the detection technique that flagged them. Malware quarantine is admin-only by default, so this table only populates when a custom quarantine policy lets users view and report their own malware detections - it is usually empty.**" - }, - "customWidth": "100", - "name": "fp user - malware-verdict heading", - "id": "693b1072-5ddd-49d0-a0f5-2bba4c287edf" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//User false positive submissions whose email was originally flagged as Malware, by the detection technique that flagged it. A high count means that technique most often misclassifies legitimate mail as Malware.\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has \"Malware\"\r\n| mv-expand Technique = parse_json(DetectionMethods).Malware to typeof(string)\r\n| where isnotempty(Technique)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(SenderFromDomain) by Technique\r\n| sort by FPSubmissions desc\r\n| project ['Detection Technique'] = Technique, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "FP Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Distinct Sender Domains", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "22ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "fp user - malware-verdict table", - "id": "10ea55bd-937e-454d-b6cc-a9dccfdf3417" - }, - { - "type": 1, - "content": { - "json": "### User Submission False Positive Phish Detection Breakdown\r\n**Shows the count of user-submitted false positive reports (legitimate emails flagged as phishing) grouped by the detection technique that flagged them. Helps identify which filtering technologies most often misclassify valid messages as phishing.**" - }, - "customWidth": "100", - "name": "fp user - phish-verdict heading", - "id": "6dd14abb-2772-4271-89d8-8c0dcdbfd9e5" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//User false positive submissions whose email was originally flagged as Phish, by the detection technique that flagged it. A high count means that technique most often misclassifies legitimate mail as Phish.\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has \"Phish\"\r\n| mv-expand Technique = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Technique)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(SenderFromDomain) by Technique\r\n| sort by FPSubmissions desc\r\n| project ['Detection Technique'] = Technique, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "FP Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Distinct Sender Domains", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "22ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "fp user - phish-verdict pie", - "id": "57049aad-eb17-4e65-a8a4-b5d05b0501cd" - }, - { - "type": 1, - "content": { - "json": "### User Submission False Positive Spam Detection Breakdown\r\n**Shows the count of user-submitted false positive reports (legitimate emails flagged as spam) grouped by the detection technique that flagged them. Helps identify which filtering technologies most often misclassify valid messages as spam.**" - }, - "customWidth": "100", - "name": "fp user - spam-verdict heading", - "id": "5479b2ed-b629-41e7-9857-c91191b09c8f" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//User false positive submissions whose email was originally flagged as Spam, by the detection technique that flagged it. A high count means that technique most often misclassifies legitimate mail as Spam.\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has \"Spam\"\r\n| mv-expand Technique = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Technique)\r\n| summarize FPSubmissions = count(), DistinctDomains = dcount(SenderFromDomain) by Technique\r\n| sort by FPSubmissions desc\r\n| project ['Detection Technique'] = Technique, ['FP Submissions'] = FPSubmissions, ['Distinct Sender Domains'] = DistinctDomains", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "FP Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Distinct Sender Domains", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "22ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "fp user - spam-verdict pie", - "id": "45a2122e-0281-4602-906d-a0406ed20d54" - }, - { - "type": 1, - "content": { - "json": "### Top 10 Sender Domains for User False Positive Submissions
\r\n\r\n**Lists the top 10 sender domains of emails reported as false positives by users (legitimate messages incorrectly flagged as threats). Helps identify domains frequently misclassified.**" - }, - "customWidth": "100", - "name": "fp user - top-sender-domains heading", - "id": "2751fca4-3ac5-45fe-a965-8c811018926a" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Top 10 sender domains reported as false positives by users, with each domain's total inbound volume and the share of it reported as FP (a high rate flags a domain whose legitimate mail is most often misclassified).\r\nlet totalByDomain = EmailEvents | where EmailDirection == \"Inbound\" | summarize TotalInbound = count() by SenderFromDomain;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), P2SenderDomain = tostring(R.P2SenderDomain)\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| summarize FPSubmissions = count() by P2SenderDomain\r\n| join kind=leftouter (totalByDomain) on $left.P2SenderDomain == $right.SenderFromDomain\r\n| extend FPPct = iif(isnull(TotalInbound) or TotalInbound == 0, 0.0, round(FPSubmissions * 100.0 / TotalInbound, 2))\r\n| top 10 by FPSubmissions desc\r\n| project ['Sender Domain'] = P2SenderDomain, ['FP Submissions'] = FPSubmissions, ['Total Inbound'] = coalesce(TotalInbound, 0), ['FP Submission %'] = FPPct", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "FP Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Total Inbound", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "18ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "FP Submission %", - "formatter": 4, - "formatOptions": { - "palette": "red", - "min": 0, - "max": 20, - "customColumnWidthSetting": "16ch" - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "fp user - top-sender-domains table", - "id": "c69b126d-9f25-44a0-b96d-601d89a563f1" - }, - { - "type": 1, - "content": { - "json": "### Top 10 Senders in User False Positive Submissions
\r\n\r\n**Displays the top 10 email senders whose messages were reported as false positives by users (legitimate emails incorrectly flagged as threats). Helps identify senders frequently misclassified.**" - }, - "customWidth": "100", - "name": "fp user - top-senders heading", - "id": "b39966ad-2b40-4144-ae3f-c7ac6b9fb97c" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Top 10 email senders reported as false positives by users, with each sender's total inbound volume and the share reported as FP.\r\nlet totalBySender = EmailEvents | where EmailDirection == \"Inbound\" | summarize TotalInbound = count() by SenderMailFromAddress;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\"\r\n| summarize FPSubmissions = count() by SenderMailFromAddress\r\n| join kind=leftouter (totalBySender) on SenderMailFromAddress\r\n| extend FPPct = iif(isnull(TotalInbound) or TotalInbound == 0, 0.0, round(FPSubmissions * 100.0 / TotalInbound, 2))\r\n| top 10 by FPSubmissions desc\r\n| project ['Sender Address'] = SenderMailFromAddress, ['FP Submissions'] = FPSubmissions, ['Total Inbound'] = coalesce(TotalInbound, 0), ['FP Submission %'] = FPPct", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "FP Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Total Inbound", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "18ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "FP Submission %", - "formatter": 4, - "formatOptions": { - "palette": "red", - "min": 0, - "max": 20, - "customColumnWidthSetting": "16ch" - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "fp user - top-senders table", - "id": "077ab610-58ed-4d23-886c-dbf912cef2d7" - }, - { - "type": 1, - "content": { - "json": "### Top 10 Subjects in User False Positive Submissions
\r\n\r\n**Displays the top 10 email subjects reported as false positives by users (legitimate messages incorrectly flagged as threats). Helps identify common patterns in misclassified emails.**" - }, - "customWidth": "100", - "name": "fp user - top-subjects heading", - "id": "a5b939e1-0fbf-4ee1-a6a3-01fa7639af3a" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Top 10 email subjects reported as false positives by users, with how many distinct recipients reported each (a subject reported by many users is a broad misclassification pattern).\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Inbound\"\r\n| summarize FPSubmissions = count(), DistinctRecipients = dcount(RecipientObjectId) by Subject\r\n| top 10 by FPSubmissions desc\r\n| project ['Subject'] = Subject, ['FP Submissions'] = FPSubmissions, ['Distinct Recipients'] = DistinctRecipients", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Subject", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "70ch" - } - }, - { - "columnMatch": "FP Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Distinct Recipients", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "18ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "fp user - top-subjects table", - "id": "71d5c290-f5d0-493c-b821-b5345dbe7312" - }, - { - "type": 1, - "content": { - "json": "### Top 10 Intra-Org Senders in User False Positive Submissions
\r\n\r\n**Displays the top 10 internal senders whose emails were reported as false positives by users (legitimate intra-org messages incorrectly flagged as threats). Helps identify internal communication patterns causing misclassification.**" - }, - "customWidth": "100", - "name": "fp user - intraorg-senders heading", - "id": "1d38f458-dfde-4608-ad7d-ee8628e85ee7" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Top 10 internal senders whose emails were reported as false positives by users, with total intra-org volume and the share reported as FP.\r\nlet totalBySender = EmailEvents | where EmailDirection == \"Intra-org\" | summarize TotalIntraOrg = count() by SenderMailFromAddress;\r\nCloudAppEvents\r\n| where ActionType == \"UserSubmission\"\r\n| extend R = parse_json(RawEventData)\r\n| extend SubmissionType = tostring(R.SubmissionType), SubmissionContentType = tostring(R.SubmissionContentType), NetworkMessageId = tostring(R.ObjectId), RecipientObjectId = AccountObjectId\r\n| where SubmissionContentType == \"Mail\" and SubmissionType == \"3\"\r\n| join EmailEvents on NetworkMessageId, RecipientObjectId\r\n| where EmailDirection == \"Intra-org\"\r\n| summarize FPSubmissions = count() by SenderMailFromAddress\r\n| join kind=leftouter (totalBySender) on SenderMailFromAddress\r\n| extend FPPct = iif(isnull(TotalIntraOrg) or TotalIntraOrg == 0, 0.0, round(FPSubmissions * 100.0 / TotalIntraOrg, 2))\r\n| top 10 by FPSubmissions desc\r\n| project ['Sender Address'] = SenderMailFromAddress, ['FP Submissions'] = FPSubmissions, ['Total Intra-org'] = coalesce(TotalIntraOrg, 0), ['FP Submission %'] = FPPct", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "FP Submissions", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - }, - { - "columnMatch": "Total Intra-org", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "18ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "FP Submission %", - "formatter": 4, - "formatOptions": { - "palette": "red", - "min": 0, - "max": 20, - "customColumnWidthSetting": "16ch" - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "fp user - intraorg-senders table", - "id": "b6699a7f-897a-4016-ae2c-d816f3a9492b" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "10" - }, - "name": "fp user - group", - "styleSettings": { - "showBorder": true - }, - "id": "2ad3311e-e92b-4a49-bdd0-775f085c4587" - }, - { - "type": 1, - "content": { - "json": "# File Malware Detections (SharePoint, Teams and OneDrive)\r\n\r\n---\r\n\r\nThis tab provides insights into malicious file detections across Microsoft collaboration platforms such as SharePoint, OneDrive, and Teams.\r\n\r\n[

Safe Attachments for SharePoint, OneDrive, and Microsoft Teams

](https://learn.microsoft.com/en-us/defender-office-365/safe-attachments-for-spo-odfb-teams-about)\r\n[

Built-in virus protection in SharePoint, SharePoint Embedded, OneDrive, and Microsoft Teams

](https://learn.microsoft.com/en-us/defender-office-365/anti-malware-protection-for-spo-odfb-teams-about) " - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "9" - }, - "name": "filemal - tab description", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "cefcac88-f373-4748-b0ea-e7600f63edd7" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Microsoft Defender for Office 365 value for files in SharePoint / OneDrive / Teams: total files processed, how many had a malware detection, and how many were scanned with no detection. A per-period Trend series feeds the tile sparkline.\r\nlet gran = {Granularity};\r\nlet base = FileMaliciousContentInfo;\r\nlet counts = union\r\n(base | summarize Count = count() | extend Cat = \"Total Files Processed (SPO/ODB/Teams)\", Ord = 1),\r\n(base | where isnotempty(ThreatTypes) | summarize Count = count() | extend Cat = \"Files with Malware Detected\", Ord = 2),\r\n(base | where isempty(ThreatTypes) | summarize Count = count() | extend Cat = \"Files Scanned - No Detection\", Ord = 3);\r\nlet tagged = union\r\n(base | extend Cat = \"Total Files Processed (SPO/ODB/Teams)\"),\r\n(base | where isnotempty(ThreatTypes) | extend Cat = \"Files with Malware Detected\"),\r\n(base | where isempty(ThreatTypes) | extend Cat = \"Files Scanned - No Detection\");\r\nlet trends = tagged | make-series Trend = count() default = 0 on Timestamp step gran by Cat;\r\ncounts\r\n| join kind=leftouter (trends) on Cat\r\n| sort by Ord asc\r\n| project Count, Details = Cat, Trend", - "size": 3, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "tiles", - "tileSettings": { - "titleContent": { - "columnMatch": "Details", - "formatter": 1 - }, - "leftContent": { - "columnMatch": "Count", - "formatter": 12, - "formatOptions": { - "min": 0, - "palette": "blue" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - "secondaryContent": { - "columnMatch": "Trend", - "formatter": 21, - "formatOptions": { - "min": 0, - "palette": "blue" - } - }, - "showBorder": true, - "size": "auto" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "filemal - MDO value tiles", - "id": "843e58a9-6324-4a90-a652-bfb0549e79dc", - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "9" - } - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
File Malware Detection (SharePoint, OneDrive, and Teams)\r\n
\r\n\r\nThis section monitors malware detections in files stored across Microsoft 365 collaboration platforms. Microsoft Defender for Office 365 and built-in SharePoint Online antivirus work together to scan files uploaded to SharePoint, OneDrive, and Teams. Understanding file-based malware patterns helps protect collaborative workspaces and identify potential security risks in shared content.

**Recommended action:** For repeat file owners or sites, investigate possible compromise and confirm Safe Attachments for SharePoint, OneDrive and Teams is enabled." - }, - "name": "filemal - section header", - "id": "373fe4e5-fc90-49cf-93ba-c8b100efce57" - }, - { - "type": 1, - "content": { - "json": "### File Malware Detection Trend
\r\n\r\n**This visual tracks the volume (per {Granularity}) of malware detections in files across all Microsoft 365 workloads. Spikes in detection activity may indicate targeted attacks or emerging malware campaigns affecting collaborative platforms. Regular monitoring helps identify unusual patterns that require investigation.**" - }, - "name": "filemal - trend heading", - "id": "30145585-8998-443a-b6ec-062d136c621f" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total files located on SharePoint, OneDrive and Teams with Malware detections over time summarizing the data daily.\r\nlet gran = {Granularity};\r\nlet agg = materialize(FileMaliciousContentInfo\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Files']=coalesce(Count, 0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "areachart", - "tileSettings": { - "showBorder": false - }, - "graphSettings": { - "type": 0 - }, - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "Files", - "color": "blueDark" - } - ], - "showDataPoints": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "filemal - detection trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "d39cea9b-75a8-4c29-bfdb-2e0db855e98a" - }, - { - "type": 1, - "content": { - "json": "### Malware Family Analysis - Defender for Office 365\r\n**Provides a breakdown of malware detections in files scanned by Microsoft Defender for Office 365 (Safe Attachments detonation) across SharePoint, OneDrive, and Teams. The table lists each malware family with total detections, distinct files, affected locations and when it was last seen, helping identify dominant threats and their spread across collaboration platforms.**" - }, - "customWidth": "100", - "name": "filemal - family MDO heading", - "id": "4e330873-f732-4d37-a7b0-dced08b019b0" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query summarizes File malware detections by Microsoft Defender for Office 365 (Safe Attachments detonation) into a per-family table: total detections, distinct files, affected locations (file owner or site) and when the family was last seen.\r\nFileMaliciousContentInfo\r\n| where tostring(DetectionMethods) contains \"detonation\"\r\n| extend Owner = iff(isnotempty(FileOwnerUpn), FileOwnerUpn, strcat(\"Site: \", tostring(split(FolderPath, \"/\")[4])))\r\n| summarize ['Files']=count(), ['Distinct Files']=dcount(SHA256), ['Affected Locations']=dcount(Owner), ['Last Seen']=max(Timestamp) by ThreatNames\r\n| sort by ['Files'] desc\r\n| project ['Threat Name']=ThreatNames, ['Files'], ['Distinct Files'], ['Affected Locations'], ['Last Seen']", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "tileSettings": { - "showBorder": false, - "titleContent": { - "columnMatch": "RawinfoVirusInfo", - "formatter": 1 - }, - "leftContent": { - "columnMatch": "count_", - "formatter": 12, - "formatOptions": { - "palette": "auto" - }, - "numberFormat": { - "unit": 17, - "options": { - "maximumSignificantDigits": 3, - "maximumFractionDigits": 2 - } - } - } - }, - "graphSettings": { - "type": 0, - "topContent": { - "columnMatch": "RawinfoVirusInfo", - "formatter": 1 - }, - "centerContent": { - "columnMatch": "count_", - "formatter": 1, - "numberFormat": { - "unit": 17, - "options": { - "maximumSignificantDigits": 3, - "maximumFractionDigits": 2 - } - } - } - }, - "chartSettings": { - "xAxis": "RawinfoVirusInfo", - "createOtherGroup": 15 - }, - "gridSettings": { - "formatters": [ - { - "columnMatch": "Files", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "filemal - family MDO table", - "id": "c3fbb1c9-be67-43b9-9a32-7fb265a84ffc" - }, - { - "type": 1, - "content": { - "json": "### Malware Family Analysis - SharePoint AV\r\n**Provides a breakdown of malware detections in files across SharePoint, OneDrive, and Teams caught by the built-in SharePoint antivirus (Antimalware engine). The table lists each malware family with total detections, distinct files, affected locations and when it was last seen, helping identify prevalent threats and their spread across collaboration environments.**" - }, - "customWidth": "100", - "name": "filemal - family SPO-AV heading", - "id": "331a8361-6e81-4615-b33a-97ebb3e31529" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query summarizes File malware detections by the built-in SharePoint antivirus (Antimalware engine) into a per-family table: total detections, distinct files, affected locations (file owner or site) and when the family was last seen.\r\nFileMaliciousContentInfo\r\n| where tostring(DetectionMethods) contains \"Antimalware engine\"\r\n| extend Owner = iff(isnotempty(FileOwnerUpn), FileOwnerUpn, strcat(\"Site: \", tostring(split(FolderPath, \"/\")[4])))\r\n| summarize ['Files']=count(), ['Distinct Files']=dcount(SHA256), ['Affected Locations']=dcount(Owner), ['Last Seen']=max(Timestamp) by ThreatNames\r\n| sort by ['Files'] desc\r\n| project ['Threat Name']=ThreatNames, ['Files'], ['Distinct Files'], ['Affected Locations'], ['Last Seen']", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "chartSettings": { - "xAxis": "RawinfoVirusInfo", - "createOtherGroup": 10 - }, - "gridSettings": { - "formatters": [ - { - "columnMatch": "Files", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "filemal - family SPO-AV table", - "id": "bbcdccd9-eedb-476a-a0e7-8504f8770229" - }, - { - "type": 1, - "content": { - "json": "### Malware Detections by Location
\r\n\r\n**Displays the number of malware detections grouped by specific SharePoint sites or OneDrive locations. Helps identify which sites have the highest volume of detected threats for targeted remediation and security hardening.**" - }, - "customWidth": "50", - "name": "filemal - by-location heading", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "c5668d6e-7c0e-4ce3-9509-ca93dda3efad" - }, - { - "type": 1, - "content": { - "json": "### Malware Detections by Application
\r\n\r\n**Summarizes malware detections across Microsoft collaboration apps, including SharePoint, OneDrive, and Teams. Helps identify which applications experience the highest volume of detected threats for targeted security measures.**" - }, - "customWidth": "50", - "name": "filemal - by-application heading", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "07e64ca9-04a2-44b2-a044-e927bc73ef1b" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query lists total Malware detections of files on SharePoint, OneDrive and Teams by the location (site or personal path) where the file resides.\r\nFileMaliciousContentInfo\r\n| extend ['Site / Location'] = tostring(split(FolderPath, '/')[4])\r\n| summarize ['Detections'] = count() by ['Site / Location']\r\n| sort by ['Detections'] desc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Detections", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "filemal - by-location table", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "3ce3ea65-a4df-450f-871c-8956d59818a9" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises total Malware detections of files located on SharePoint, OneDrive and Teams summarizing the data by the Microsoft collaboration application (workload).\r\nFileMaliciousContentInfo\r\n| summarize count() by Workload\r\n| sort by count_ desc", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "filemal - by-application pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "003afc8e-0403-4aa9-9084-a3c2e435216a" - }, - { - "type": 1, - "content": { - "json": "### Top File Owners Holding Malware\r\n**Lists the users (or the SharePoint/Teams site, when a file has no individual owner) whose files in SharePoint, OneDrive or Teams were flagged as malware, with the count of malicious files, distinct files, affected workloads and sample threat names. Helps pinpoint the accounts and collaboration locations most affected by malicious content for targeted remediation.**" - }, - "customWidth": "100", - "name": "filemal - top-owners heading", - "id": "c2f8d3b5-0a4e-4b7c-9d23-8e6f0a1b2c34" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Top file owners (or the SharePoint/Teams site, when a file has no user owner) whose SharePoint/OneDrive/Teams files were flagged as malware, with distinct files, workloads and sample threat names.\r\nFileMaliciousContentInfo\r\n| extend Owner = iff(isnotempty(FileOwnerUpn), FileOwnerUpn, strcat(\"Site: \", tostring(split(FolderPath, \"/\")[4])))\r\n| summarize ['Malicious Files'] = count(),\n ['Distinct Files'] = dcount(SHA256),\n ['Workloads'] = make_set(Workload, 3),\n ['Sample Threats'] = make_set_if(ThreatNames, isnotempty(ThreatNames), 5),\n ['Last Seen'] = max(Timestamp)\n by ['Owner']=Owner\n| top 20 by ['Malicious Files']", - "size": 0, - "title": "Top File Owners Holding Malware", - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true, - "formatters": [ - { - "columnMatch": "Malicious Files", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Distinct Files", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "name": "filemal - top-owners table", - "id": "36d9a683-9f9d-4a70-84d9-ec351542f827" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "9" - }, - "name": "filemal - group", - "styleSettings": { - "showBorder": true - }, - "id": "50886cd9-87bf-4a84-bd80-d7f44441b3f7" - }, - { - "type": 1, - "content": { - "json": "# Post-Delivery & Quarantine Insights\r\n\r\n---\r\nThis tab covers what happens to threats **after delivery**: Zero-hour Auto Purge (ZAP) remediation of malicious messages already in mailboxes, and quarantine management - what is held, released, and by whom. Together they show how effectively post-delivery response contains threats that reached the inbox." - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "11" - }, - "name": "postdelivery - tab description", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "93371620-d968-4987-bddd-6c9b9e5a0344" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Post Delivery Protection offered by ZAP\r\n
\r\n\r\nThis section provides insights into Microsoft Defender for Office 365's post-delivery protection capabilities through Zero-Hour Auto Purge (ZAP). ZAP is a critical security feature that continuously monitors delivered emails and automatically removes messages that are later identified as malicious. These visuals help track ZAP effectiveness, response times, and remediation patterns.

**Recommended action:** High post-delivery ZAP volume means threats are reaching inboxes before being caught - review pre-delivery filtering and detection latency." - }, - "name": "postdelivery - section header", - "id": "b22ee5f1-a2dc-4509-92a3-1dbcad3a6ee7" - }, - { - "type": 1, - "content": { - "json": "### ZAP Post-Delivery Actions (per {Granularity})
\r\n\r\n**Shows the count (per {Granularity}) of emails that were remediated post-delivery by Zero-Hour Auto Purge (ZAP). Helps track how often threats are detected and removed after reaching user mailboxes.**" - }, - "customWidth": "50", - "name": "postdelivery - zap-actions heading", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "af1aa73f-d952-4827-bcc9-b97a19016829" - }, - { - "type": 1, - "content": { - "json": "### ZAP Actions by Detection Type (per {Granularity})
\r\n\r\n**Visualizes the count (per {Granularity}) of post-delivery remediation actions performed by Zero-Hour Auto Purge (ZAP), broken down by detection type (Spam ZAP, Phish ZAP, Malware ZAP). Helps track which threat categories are most frequently remediated after delivery.**" - }, - "customWidth": "50", - "name": "postdelivery - by-detection-type heading", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "8eb38cb1-4e2d-435a-81be-e661c9b89ff4" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the daily ammount of emails that had a post delivery action from zero-hour auto purge.\r\nlet gran = {Granularity};\r\nlet agg = materialize(EmailPostDeliveryEvents \r\n| where ActionType has \"ZAP\"\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Zapped Emails'] = coalesce(Count, 0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "areachart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "Zapped Emails", - "color": "blueDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "postdelivery - zap-actions trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "dd60fd71-4e14-4b38-ad22-39f1e3e3f55a" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the daily ammount of emails that had a post delivery action from zero-hour auto purge, summarizing by phish,spam or malware detection action\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailPostDeliveryEvents\r\n| where ActionType has \"ZAP\"\r\n| summarize [\"Spam ZAP\"]=countif(ActionType has 'Spam ZAP'), [\"Phish ZAP\"]=countif(ActionType has 'Phish ZAP'), [\"Malware ZAP\"]=countif(ActionType has 'Malware ZAP') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, [\"Spam ZAP\"]=coalesce([\"Spam ZAP\"],0), [\"Phish ZAP\"]=coalesce([\"Phish ZAP\"],0), [\"Malware ZAP\"]=coalesce([\"Malware ZAP\"],0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "50", - "name": "postdelivery - by-detection-type trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "511f4a43-9f56-48ad-a644-b72722af82d7" - }, - { - "type": 1, - "content": { - "json": "### ZAP Remediation by Destination
\r\n\r\n**This visual shows where ZAP moves malicious emails during remediation. Post-delivery actions can send emails to different locations: Quarantine (isolated for admin review), Deleted Items (soft delete), Junk Email folder, or back to Inbox (for false positive corrections). Understanding these patterns helps evaluate ZAP policy configurations and ensures malicious content is properly isolated from users.**" - }, - "name": "postdelivery - by-destination heading", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "dc7b9b6c-36fb-4ae4-a3e8-ff11da681c97" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the ammount of emails that had a post delivery action, summarizing the data daily by the final location as a result of the action\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailPostDeliveryEvents\r\n| where ActionType contains \"ZAP\"\r\n| summarize Quarantine=countif(DeliveryLocation has 'Quarantine'), ['Deleted Items']=countif(DeliveryLocation has 'Delete'), Junk=countif(DeliveryLocation has 'Junk'), Inbox=countif(DeliveryLocation has 'Inbox') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, Quarantine=coalesce(Quarantine,0), ['Deleted Items']=coalesce(['Deleted Items'],0), Junk=coalesce(Junk,0), Inbox=coalesce(Inbox,0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "timeContext": { - "durationMs": 0 - } - }, - "name": "postdelivery - by-destination trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "cbb737ef-1c7e-4b3e-af26-a553fe6147c9" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "11" - }, - "name": "postdelivery - group", - "styleSettings": { - "showBorder": true - }, - "id": "e436ecee-8886-4179-a578-9e4a42e75b9e" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Quarantine Management and Insights\r\n
\r\n\r\nThis section provides comprehensive insights into quarantine operations, including release patterns, detection methods, and threat categorization. It helps security teams understand what types of threats are being quarantined and monitor quarantine release activity to identify potential false positives or security policy effectiveness.

**Recommended action:** Investigate high release rates - they indicate false positives or risky user releases; review quarantine policies and release permissions." - }, - "name": "quarantine - section header", - "id": "c4862977-6670-4716-8109-252a361d7478" - }, - { - "type": 1, - "content": { - "json": "### Quarantine Release Trend
\r\n\r\n**This visual displays the per-{Granularity} trend of emails released from quarantine by administrators. Monitoring this metric helps identify patterns in quarantine management and potential areas where policy adjustments may be needed to reduce unnecessary quarantines.**" - }, - "name": "quarantine - release-trend heading", - "id": "8526a5e0-c6a4-44e3-b00a-5e135374f58e" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the daily ammount of emails released from quarantine\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailPostDeliveryEvents\r\n| where ActionTrigger has \"AdminAction\" and Action has 'Quarantine release'\r\n| summarize Count = count() by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, ['Quarantine Releases'] = coalesce(Count, 0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "areachart", - "chartSettings": { - "seriesLabelSettings": [ - { - "seriesName": "Quarantine Releases", - "color": "blueDark" - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "quarantine - release trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "3625d1f1-f34a-4cbf-a78f-eb2e5506bad4" - }, - { - "type": 1, - "content": { - "json": "### Quarantine Release Percentage
\r\n\r\n**Calculates the percentage of quarantined emails that were successfully released compared to the total quarantined messages. This metric helps measure engagement with quarantine and assess the effectiveness of quarantine policies.**" - }, - "customWidth": "40", - "name": "quarantine - release-pct heading", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "e3a9502c-9030-4621-b248-55cdf69f81ae" - }, - { - "type": 1, - "content": { - "json": "### Quarantine Release Analysis by Detection Type
\r\n\r\n**For each detection technology, this shows the share of its quarantined emails that were later released from quarantine (Release % = released / quarantined). A high release rate flags a detector that may be over-flagging legitimate mail - a strong candidate for policy or rule tuning. The Released count shows the volume behind each rate.**" - }, - "customWidth": "60", - "name": "quarantine - release-by-detection heading", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "976fc90f-bf46-4315-b05e-4e501b37b869" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the percentage of emails released from quarantine out of the total ammount of quarantined emails\r\nlet Quarantine_Releases = toscalar(EmailPostDeliveryEvents\r\n| where Action == \"Quarantine release\"\r\n| join kind=leftouter (EmailEvents | where DeliveryLocation == \"Quarantine\") on NetworkMessageId\r\n| summarize count());\r\nlet Quarantined_Mailflow = toscalar(EmailEvents | where DeliveryLocation == \"Quarantine\"\r\n| summarize count());\r\nprint\r\nQuarantine_Releases = toreal(Quarantine_Releases),\r\nQuarantined_Mailflow = toreal(Quarantined_Mailflow),\r\nRelease_Percentage = abs(round(((toreal(Quarantine_Releases)/toreal(Quarantined_Mailflow))*100),2))", - "size": 0, - "showAnalytics": true, - "title": " ", - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "stat", - "tileSettings": { - "titleContent": { - "columnMatch": "Release_Percentage", - "formatter": 12, - "formatOptions": { - "palette": "none" - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - }, - "showBorder": true, - "sortCriteriaField": "Release_Percentage", - "size": "auto" - }, - "statSettings": { - "valueField": "Release_Percentage", - "valueAggregation": "None", - "colorSettings": { - "type": "thresholds", - "mode": "foreground", - "heatmapPalette": "greenRed", - "thresholdsGrid": [ - { - "operator": "<", - "thresholdValue": "5", - "representation": "green" - }, - { - "operator": ">", - "thresholdValue": "5", - "representation": "redDark" - } - ] - }, - "iconSettings": { - "thresholdsGrid": [] - }, - "numberFormatSettings": { - "unit": 1, - "options": { - "style": "decimal" - } - }, - "tagText": "Quarantine Release Percentage", - "valueFontStyle": "mega", - "tagTextPosition": "bottom" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "40", - "name": "quarantine - release-pct stat", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "64e157ce-2f6a-423f-9ce5-eade8b6f41d5" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Per detection technology: the share of its quarantined emails that were later released from quarantine.\r\n//Release % = released / quarantined for that detection technology - a high rate flags a detector that may be over-flagging legitimate mail (potential false positives). Detectors with fewer than 10 quarantined emails are excluded so the rate is statistically meaningful.\r\nEmailEvents\r\n| where DeliveryLocation == \"Quarantine\"\r\n| extend MDO_detection = parse_json(DetectionMethods)\r\n| extend FirstDetection = iif(isempty(MDO_detection), \"Clean\", tostring(bag_keys(MDO_detection)[0]))\r\n| extend FirstSubcategory = iif(FirstDetection != \"Clean\" and array_length(MDO_detection[FirstDetection]) > 0, strcat(FirstDetection, \": \", tostring(MDO_detection[FirstDetection][0])), \"No Detection (clean)\")\r\n| where FirstSubcategory contains \"Malware\" or FirstSubcategory contains \"Phish\" or FirstSubcategory contains \"Spam\"\r\n| join kind=leftouter (\r\n EmailPostDeliveryEvents\r\n | where Action == \"Quarantine release\"\r\n | distinct NetworkMessageId\r\n | extend ReleasedFlag = \"yes\"\r\n ) on NetworkMessageId\r\n| summarize Quarantined = dcount(NetworkMessageId), Released = dcountif(NetworkMessageId, ReleasedFlag == \"yes\") by FirstSubcategory\r\n| where Quarantined >= 10 and Released > 0\r\n| extend ReleaseRate = round(Released * 100.0 / Quarantined, 2)\r\n| project ['Detection Type']=FirstSubcategory, ['Quarantined Emails']=Quarantined, ['Released']=Released, ['Release %']=ReleaseRate\r\n| order by ['Release %'] desc", - "size": 3, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Quarantined Emails", - "formatter": 0, - "formatOptions": { - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Released", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "90px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Release %", - "formatter": 4, - "formatOptions": { - "palette": "red", - "min": 0, - "max": 20, - "customColumnWidthSetting": "90px" - }, - "numberFormat": { - "unit": 1, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "60", - "name": "quarantine - release-by-detection pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "9a6d21b7-7542-4ae5-8f3f-b18474b52a20" - }, - { - "type": 1, - "content": { - "json": "### Malware Email Quarantine Analysis
\r\n\r\n**These visuals break down quarantined malware emails by their specific detection methods. Microsoft Defender for Office 365 employs multiple malware detection techniques including file detonation, file reputation analysis, and advanced filters. Understanding which detection methods are most frequently triggered helps optimize anti-malware policies and identify emerging malware tactics.
The line chart shows per-{Granularity} trends across all malware detection methods, while the table provides an overall distribution of detection reasons.**" - }, - "name": "quarantine - malware heading", - "id": "59f84161-a010-44c2-aec1-b72ed98ccdff" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the ammount of malware emails that are quarantined, summarized daily by the detection method\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has \"Malware\" and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Details = parse_json(DetectionMethods).Malware to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "quarantine - malware trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "a54a8daf-0be2-4c0e-a8d7-4ff0e0879fd2" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the total ammount of malware emails that are quarantined, summarized by the detection method\r\n//(QA 2026-07-14) mv-expand over DetectionMethods.Malware (matching the sibling line chart) so each slice is a clean single method name instead of a bracketed JSON array.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has 'Malware' and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Malware = parse_json(DetectionMethods).Malware to typeof(string)\r\n| where isnotempty(Malware)\r\n| summarize count() by Malware\r\n| sort by count_ desc\r\n| project ['Detection Technology']=Malware, ['Detections']=count_", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Detections", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "quarantine - malware table", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "b5d0d022-cf41-47e5-ae06-cf2176b47758" - }, - { - "type": 1, - "content": { - "json": "### Phishing Email Quarantine Analysis
\r\n\r\n**These visuals break down quarantined phishing emails by their specific detection methods. Microsoft Defender for Office 365 employs multiple phishing detection techniques including impersonation protection, URL detonation, spoof detection, and advanced filters. Understanding which detection methods are most frequently triggered helps optimize anti-phishing policies and identify emerging phishing tactics.
The line chart shows per-{Granularity} trends across all phishing detection methods, while the table provides an overall distribution of detection reasons.**" - }, - "name": "quarantine - phish heading", - "id": "aca50104-cb68-4a8f-82ee-ea8eee25fe14" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the ammount of phish emails that are quarantined, summarized daily by the detection method\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailEvents\r\n| where DetectionMethods has \"Phish\" and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Details = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "quarantine - phish trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "57151360-0577-45ce-8fc6-10a3790865ce" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the total ammount of phish emails that are quarantined, summarized by the detection method\r\n//(QA 2026-07-14) mv-expand over DetectionMethods.Phish (matching the sibling line chart) so each slice is a clean single method name instead of a bracketed JSON array.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has 'Phish' and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Phish = parse_json(DetectionMethods).Phish to typeof(string)\r\n| where isnotempty(Phish)\r\n| summarize count() by Phish\r\n| sort by count_ desc\r\n| project ['Detection Technology']=Phish, ['Detections']=count_", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Detections", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "quarantine - phish pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "df78c64b-76f6-4980-80df-d0d432e780a5" - }, - { - "type": 1, - "content": { - "json": "### Spam Email Quarantine Analysis
\r\n\r\n**These visuals provide detailed insights into quarantined spam emails categorized by detection methods. Spam detection technologies include advanced filters, general filters, bulk email filtering, reputation-based systems (IP, domain, URL), and mixed analysis detection. Analyzing spam quarantine patterns helps fine-tune spam filtering policies to balance security with user productivity and reduce false positives.
The line chart displays per-{Granularity} trends for each spam detection method, while the table shows the overall distribution.**" - }, - "name": "quarantine - spam heading", - "id": "e131910f-0233-474a-a9b8-9f70a49246cf" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the ammount of spam emails that are quarantined, summarized daily by the detection method\r\nlet gran = {Granularity};\r\nlet baseQuery = EmailEvents\r\n| where DetectionMethods has \"Spam\" and DeliveryLocation == \"Quarantine\";\r\nlet agg = materialize(baseQuery\r\n| mv-expand Details = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Details)\r\n| summarize Count = count() by Details, Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from toscalar(agg | summarize min(Timestamp)) to toscalar(agg | summarize max(Timestamp)) step gran\r\n| extend d = 1 | join kind=inner (agg | distinct Details | extend d = 1) on d | project Timestamp, Details\r\n| join kind=leftouter (agg) on Timestamp, Details\r\n| project Timestamp, Details, Count = coalesce(Count, 0)\r\n| sort by Details asc, Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "quarantine - spam trend", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "5762bcc7-bbda-4a3d-91cf-de18fbdd2775" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the total ammount of spam emails that are quarantined, summarized by the detection method\r\n//(QA 2026-07-14) mv-expand over DetectionMethods.Spam (matching the sibling line chart) so each slice is a clean single method name instead of a bracketed JSON array.\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and DetectionMethods has 'Spam' and DeliveryLocation == \"Quarantine\"\r\n| mv-expand Spam = parse_json(DetectionMethods).Spam to typeof(string)\r\n| where isnotempty(Spam)\r\n| summarize count() by Spam\r\n| sort by count_ desc\r\n| project ['Detection Technology']=Spam, ['Detections']=count_", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "formatters": [ - { - "columnMatch": "Detections", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "30ch" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal" - } - } - } - ], - "filter": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "quarantine - spam pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "2995f55b-17f9-458b-8630-e0370d14522a" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "11" - }, - "name": "quarantine - group", - "id": "430294af-c68f-4427-8b55-d552a3d89d42", - "styleSettings": { - "showBorder": true - } - }, - { - "type": 1, - "content": { - "json": "# Security Operations Center (SOC) Insights \r\n\r\n---\r\n\r\nThis tab provides a view for security operations. Combines incident response metrics with investigation insights to evaluate the effectiveness of both automated systems and manual interventions." - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "13" - }, - "name": "soc - tab description", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "fd65243c-514c-4813-978f-fb908226d049" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Security Incident Response Metrics\r\n
\r\n\r\n**Operational efficiency insights.** Tracks incident volume, resolution speed, automation efficacy, and classification accuracy to evaluate SOC performance.

**Recommended action:** Track mean time to close by severity against your SLA and investigate any severity trending upward." - }, - "name": "soc - incident-metrics section header", - "id": "f92c3e24-3e0f-4f4c-8ee9-3ec60832f7b1" - }, - { - "type": 1, - "content": { - "json": "### Email Security Incidents
\r\n\r\n**These visuals display the per-{Granularity} trend of email-related security incidents, as well as the proportion of email incidents compared to the total number of incidents in Defender.**" - }, - "name": "soc - email-incidents heading", - "id": "c1cf6796-6071-4d2e-bf2c-c5e8d2a99a12" - }, - { - "type": 1, - "content": { - "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." - }, - "customWidth": "75", - "name": "soc - email-incidents trend", - "id": "e23cfcda-1017-4fd0-ac71-8a861c450f71" - }, - { - "type": 1, - "content": { - "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." - }, - "customWidth": "25", - "name": "soc - incident-category pie", - "id": "baae2150-1b04-43b4-9713-48fd3cc6247f" - }, - { - "type": 1, - "content": { - "json": "### Average Incident Time To Close (minutes)\r\n**This visual displays the average time, in minutes, to close email-related security incidents (per {Granularity}), split by severity, so you can see how resolution speed changes over time. Reference SLA targets: High 60, Medium 120, Low 240, Informational 480 minutes.**" - }, - "name": "soc - time-to-close heading", - "id": "e23ccc6c-b0f0-407b-8e01-d8b69c40a745" - }, - { - "type": 1, - "content": { - "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." - }, - "name": "soc - sla-by-severity trend", - "id": "3f7d1f17-8d2f-4a1b-a97e-17973812ca6f" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "### Closed Incident Classification (True Positive vs False Positive)\r\n\r\nThis visual shows the distribution of closed email-related incidents classified as True Positive versus False Positive. It helps assess detection accuracy and provides insight into validation trends." - }, - "customWidth": "33.3", - "name": "soc - classification heading", - "styleSettings": { - "margin": "10px" - }, - "id": "48db10ce-8246-4f5e-8b68-f618d9c7f77c" - }, - { - "type": 1, - "content": { - "json": "### True Positive Incident Classification Rate\r\n\r\nThis visual displays the percentage of email-related incidents confirmed as True Positive. It offers a clear measure of classification accuracy and highlights changes in detection effectiveness over time." - }, - "customWidth": "33.3", - "name": "soc - tp-rate heading", - "styleSettings": { - "margin": "10px" - }, - "id": "34a84dbf-609a-407f-afef-f1592eb4a92b" - }, - { - "type": 1, - "content": { - "json": "### Incidents Automated vs Manual Closure\r\n\r\nThis visual illustrates the proportion of email-related incidents closed automatically versus manually. It provides visibility into operational efficiency and the impact of automation on incident resolution.\r\n
⚠️ *You will have to review the underlying query and add any automation system specific to your organization.*" - }, - "customWidth": "33.3", - "name": "soc - auto-vs-manual-closure heading", - "styleSettings": { - "margin": "10px" - }, - "id": "a1fd9136-7a12-4d80-b3e1-e2704a84f734" - }, - { - "type": 1, - "content": { - "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." - }, - "customWidth": "33.3", - "name": "soc - classification pie", - "styleSettings": { - "margin": "10px" - }, - "id": "cfa5b7c5-50cc-4b3b-8bba-1a93c57bff43" - }, - { - "type": 1, - "content": { - "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." - }, - "customWidth": "33.3", - "name": "soc - tp-rate stat", - "styleSettings": { - "margin": "10px" - }, - "id": "eca235aa-38aa-46dd-a569-74dd8f83b2f0" - }, - { - "type": 1, - "content": { - "json": "### ISOC workspace required\n\nThis incident insight depends on the Microsoft Sentinel `SecurityIncident` and `SecurityAlert` tables. It is intentionally unavailable in this workspace-less Defender-only edition. Create an ISOC workspace to use this visual." - }, - "customWidth": "33.3", - "name": "soc - closure pie", - "styleSettings": { - "margin": "10px" - }, - "id": "a4bc160f-1ba6-4779-86cd-ef44422f1e29" - } - ] - }, - "name": "soc - incident-insights group", - "id": "3083ac4d-0bdd-4db7-a5f0-0d41cb67a4eb" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "13" - }, - "name": "soc - incident-metrics group", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "18ff8970-e5f6-4c51-918a-aa693a45d18f" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Investigation & Response Actions\r\n
\r\n\r\n**Remediation efficacy analysis.** Compares automated (AIR) and manual admin actions to evaluate response times and investigation outcomes.\r\n

**Recommended action:** Reduce AIR pending-action latency by reviewing why approvals take long, and increase automation where it is safe to do so." - }, - "name": "soc - air section header", - "id": "5e0b06c8-7774-4eb4-8b7f-572b3732de84" - }, - { - "type": 1, - "content": { - "json": "### Automated Investigation and Response (AIR) Actions (per {Granularity})\r\n\r\nThis visual shows the per-{Granularity} trend of Automated Investigation and Response (AIR) actions, including the number of successful and failed attempts (because of prior remediation)." - }, - "customWidth": "100", - "name": "soc - air-actions heading", - "styleSettings": { - "margin": "10px" - }, - "id": "05f14dec-e76c-413c-83a0-31a05dce65e7" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query attempts to show AIR Efficiency Over Time by displaying the number of successes and failures over time\r\nEmailPostDeliveryEvents\r\n| where ActionType =~ \"Automated Remediation\"\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Count = count() by bin(Timestamp, {Granularity}), ActionResult", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "graphSettings": { - "type": 0, - "topContent": { - "columnMatch": "AlertId", - "formatter": 1 - }, - "centerContent": { - "columnMatch": "Count", - "formatter": 1, - "numberFormat": { - "unit": 17, - "options": { - "maximumSignificantDigits": 3, - "maximumFractionDigits": 2 - } - } - } - }, - "chartSettings": { - "xAxis": "Timestamp" - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "soc - air-efficiency trend", - "styleSettings": { - "margin": "10px" - }, - "id": "ae2a1850-5b7e-49f7-bac4-d888053ab49b" - }, - { - "type": 1, - "content": { - "json": "### Automated Investigation and Response (AIR) Response Time After Email Delivery (per {Granularity})\r\n\r\nThis visual displays the average (per {Granularity}), 80th percentile (p80), 90th percentile (p90) and 99th percentile (p99) time needed, measured in minutes, from email delivery to AIR action. It serves as a SOC metric to monitor responsiveness (security team members reviewing and manually approving AIR Pending Actions) and identify potential latency in automated incident handling. If the latency is high focus on reviewing why reviwing AIR Pending Actions takes longer time for admins and consider auto-aproval of URL, Files and Email clusters. \r\n" - }, - "customWidth": "100", - "name": "soc - air-response-time heading", - "styleSettings": { - "margin": "10px" - }, - "id": "98c66d9e-efdf-40fc-b8b0-be35d7fd97a9" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "// SOC metric: Daily average/p75 delay (in minutes) from email delivery to AIR action\r\nlet deliveries = EmailEvents\r\n | where DeliveryAction == \"Delivered\"// delivered emails\r\n | extend MsgKey = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n | summarize FirstDelivery = min(Timestamp) by MsgKey, Threat = tostring(ThreatTypes);\r\nlet remediations = EmailPostDeliveryEvents\r\n | where ActionType =~ \"Automated Remediation\"// automated remediation events\r\n | extend MsgKey = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n | summarize FirstRemediation = min(Timestamp) by MsgKey;\r\ndeliveries\r\n| join kind=inner remediations on MsgKey\r\n| extend DelayMinutes = datetime_diff(\"minute\", FirstRemediation, FirstDelivery)\r\n| where DelayMinutes >= 0\r\n| summarize ['Avg (min)'] = avg(DelayMinutes),\r\n ['P80 (min)'] = percentile(DelayMinutes, 80),\r\n ['P90 (min)'] = percentile(DelayMinutes, 90),\r\n ['P99 (min)'] = percentile(DelayMinutes, 99),\r\n CountEmails = count()\r\n by bin(FirstRemediation, 1d) ", - "size": 0, - "aggregation": 3, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "areachart", - "gridSettings": { - "sortBy": [ - { - "itemKey": "FirstRemediation", - "sortOrder": 1 - } - ] - }, - "sortBy": [ - { - "itemKey": "FirstRemediation", - "sortOrder": 1 - } - ], - "chartSettings": { - "xAxis": "FirstRemediation", - "yAxis": [ - "P99 (min)", - "P90 (min)", - "P80 (min)", - "Avg (min)" - ], - "showLegend": true - }, - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "100", - "name": "soc - air-latency area", - "styleSettings": { - "margin": "10px" - }, - "id": "900383f1-6443-4d50-b15d-26e4ac11b255" - }, - { - "type": 1, - "content": { - "json": "### Automated Investigation and Response (AIR) Investigation Results Trend\r\n\r\nThis visual displays the per-{Granularity} trend of AIR investigation outcomes, categorized as **Threat Detected** or **Clean**. It helps track the effectiveness of automated investigations over time and highlights patterns in threat detection." - }, - "customWidth": "67", - "name": "soc - air-outcomes heading", - "styleSettings": { - "margin": "10px" - }, - "id": "d1cabfbe-6040-4b6e-9ce5-f48e9973dfc9" - }, - { - "type": 1, - "content": { - "json": "### Investigation Actions Taken: Automated Investigation and Response (AIR) vs Manual (Human)\r\n\r\nThis visual shows whether actions taken after an Automated Investigation and Response (AIR) required manual approval by an administrator or were executed automatically. It provides insight into the level of automation versus human intervention in post-investigation remediation." - }, - "customWidth": "33", - "name": "soc - air-auto-vs-manual heading", - "styleSettings": { - "margin": "10px" - }, - "id": "2f98514b-0172-4c4e-ba25-9a5e4138c570" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "// AIR investigation outcomes by day: ThreatDetected vs. Clean\r\n\r\n// Step 1: Deduplicate automated remediation events by message and recipient\r\nlet AutoRemediations = \r\n EmailPostDeliveryEvents\r\n | where ActionType == \"Automated Remediation\"\r\n | summarize arg_max(Timestamp, ActionResult) by NetworkMessageId, RecipientEmailAddress\r\n | project NetworkMessageId, RecipientEmailAddress, Timestamp;\r\n\r\n// Step 2: Derive threat verdicts using AlertEvidence\r\nlet EvidenceVerdicts =\r\n AlertEvidence\r\n | where EntityType in (\"MailMessage\", \"MailCluster\")\r\n | extend extra = todynamic(AdditionalFields)\r\n // If this is a mail cluster, use provided NetworkMessageIds array; otherwise wrap NetworkMessageId as a single-item array\r\n | extend networkIds = iff(\r\n isnull(extra.NetworkMessageIds) or array_length(extra.NetworkMessageIds) == 0,\r\n pack_array(NetworkMessageId), // create a single-element array using pack_array\r\n extra.NetworkMessageIds // use the array as-is if it exists\r\n )\r\n | mv-expand nmID = networkIds // expand to individual message IDs\r\n // Derive verdict from LastVerdict, ThreatAnalysisSummary, and ThreatIntelligence\r\n | extend \r\n lastVerdict = tolower(tostring(extra.LastVerdict)),\r\n threatAIList = extra.ThreatAnalysisSummary,\r\n threatInt = extra.ThreatIntelligence\r\n | extend verdictFromAnalysis = iff(array_length(threatAIList) > 0, tolower(tostring(threatAIList[0].Verdict)), \"\"),\r\n verdictTI = iff(array_length(threatInt) > 0, \"malicious\", \"\") // any item in ThreatIntelligence indicates malicious\r\n // Mark as threat-detected if verdict is malicious/suspicious or threat evidence is present\r\n | extend ThreatDetectedFlag = \r\n case(\r\n lastVerdict in (\"malicious\",\"suspicious\") or verdictFromAnalysis in (\"malicious\",\"suspicious\")\r\n or verdictTI == \"malicious\",\r\n true,\r\n false\r\n )\r\n // Weight mail clusters by MailCount; default to 1 for single messages\r\n | extend MailCountInt = toint(extra.MailCount)\r\n | extend Weight = iff(EntityType == \"MailCluster\", \r\n coalesce(MailCountInt, 1), // default to 1 if MailCount is missing\r\n 1)\r\n | summarize IsThreatDetected = any(ThreatDetectedFlag), \r\n WeightSum = sum(Weight) \r\n by nmID = tostring(nmID);\r\n\r\n// Step 3: Join remediation events with verdicts and aggregate by day\r\nAutoRemediations\r\n| join kind=leftouter EvidenceVerdicts on $left.NetworkMessageId == $right.nmID\r\n| extend isThreat = coalesce(IsThreatDetected, false), \r\n effectiveWeight= coalesce(WeightSum, 1)\r\n| extend InvestigationOutcome = iif(isThreat, \"Threat Detected\", \"Clean\")\r\n| summarize PreventionCount = sum(effectiveWeight) by Day = bin(Timestamp, {Granularity}), InvestigationOutcome\r\n| order by Day asc, InvestigationOutcome asc", - "size": 0, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "67", - "name": "soc - air-outcomes trend", - "styleSettings": { - "margin": "10px" - }, - "id": "18552ccb-d8d4-45c4-a3cf-072203df9325" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query shows if the action taken after an Automated Investigation required manual approval by and admin or was automatically taken\r\nEmailPostDeliveryEvents\r\n| extend Key = strcat(NetworkMessageId , '-', RecipientEmailAddress) \r\n| summarize arg_max(Timestamp, *) by Key\r\n| where ActionType == \"Automated Remediation\"\r\n| summarize count() by ActionTrigger", - "size": 3, - "showAnalytics": true, - "queryType": "advancedHunting", - "visualization": "piechart", - "timeContext": { - "durationMs": 0 - } - }, - "customWidth": "33", - "name": "soc - air-auto-vs-manual pie", - "styleSettings": { - "margin": "10px", - "padding": "10px" - }, - "id": "03bc6e3c-05de-426d-91d8-b48a36b4ea74" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "### Post-Delivery Actions by Admin\r\n\r\nThis visual displays the number (per {Granularity}) of emails where an administrator performed a post-delivery action. Actions are summarized by type, including **Soft Delete**, **Hard Delete**, **Moved to Junk Folder**, **Moved to Inbox**, and **Quarantine Release**, providing insight into manual intervention trends after email delivery." - }, - "name": "soc - post-delivery-by-admin heading", - "styleSettings": { - "margin": "10px" - }, - "id": "a0961ca9-da58-49c4-9a1c-873c5569bed9" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//This query visualises the daily ammount of emails that had an admin post delivery action, summarizing the data by action type\r\nlet gran = {Granularity};\r\nlet minTime = toscalar(EmailEvents | summarize min(Timestamp));\r\nlet maxTime = toscalar(EmailEvents | summarize max(Timestamp));\r\nlet agg = materialize(EmailPostDeliveryEvents\r\n| where ActionTrigger has \"AdminAction\"\r\n| summarize [\"Soft Delete\"]=countif(Action has 'Soft Delete'), [\"Hard Delete\"]=countif(Action has 'Hard Delete'), [\"Moved to junk folder\"]=countif(Action has 'Moved to junk folder'), [\"Moved to inbox\"]=countif(Action has 'Moved to inbox'), [\"Quarantine release\"]=countif(Action has 'Quarantine release') by Timestamp = bin(Timestamp, gran));\r\nrange Timestamp from bin(minTime, gran) to bin(maxTime, gran) step gran\r\n| join kind=leftouter (agg) on Timestamp\r\n| project Timestamp, [\"Soft Delete\"]=coalesce([\"Soft Delete\"],0), [\"Hard Delete\"]=coalesce([\"Hard Delete\"],0), [\"Moved to junk folder\"]=coalesce([\"Moved to junk folder\"],0), [\"Moved to inbox\"]=coalesce([\"Moved to inbox\"],0), [\"Quarantine release\"]=coalesce([\"Quarantine release\"],0)\r\n| sort by Timestamp asc", - "size": 0, - "showAnalytics": true, - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "linechart", - "timeContext": { - "durationMs": 0 - } - }, - "name": "soc - post-delivery-by-admin trend", - "styleSettings": { - "margin": "10px" - }, - "id": "d2ea8eac-a3db-46b0-bcb4-3abbb95ba4ad" - } - ] - }, - "customWidth": "100", - "name": "soc - post-delivery group", - "id": "ebca14d5-954d-4e35-a225-cb0f8a3ea81b" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "13" - }, - "name": "soc - air group", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "0a05394d-f813-4408-ac4d-8f481ae34c0b" - }, - { - "type": 12, - "content": { - "version": "NotebookGroup/1.0", - "groupType": "editable", - "items": [ - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Top Malicious Email Campaigns (Clustered)\r\n
\r\n\r\n**Groups malicious inbound emails into campaigns (attack waves) using the Email Cluster ID assigned by Microsoft Defender for Office 365, showing one row per campaign with the message count, distinct recipients, sender domains, threat mix and sample subjects. Helps the SOC understand the scale and shape of coordinated attacks rather than viewing individual messages in isolation.**

**Recommended action:** Pivot on the top campaign clusters to hunt related messages and consider blocking shared sender infrastructure." - }, - "name": "soc - campaigns heading", - "id": "d3a9e4c6-1b5f-4c8d-ae34-9f7a1b2c3d45" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Largest malicious inbound email campaigns clustered by EmailClusterId - one row per attack wave (messages, recipients, URL clicks, sender domains, threat mix, sample subjects).\r\n//URL Clicks = clicks by recipients on URLs within the campaign's messages (UrlClickEvents joined via NetworkMessageId).\r\nlet clicksByCluster = UrlClickEvents\r\n| join kind=inner (EmailEvents | where EmailClusterId > 0 | distinct NetworkMessageId, EmailClusterId) on NetworkMessageId\r\n| summarize UrlClicks = count() by EmailClusterId;\r\nlet qrClusters = EmailUrlInfo\r\n| where UrlLocation == \"QRCode\"\r\n| join kind=inner (EmailEvents | where EmailClusterId > 0 | distinct NetworkMessageId, EmailClusterId) on NetworkMessageId\r\n| summarize QrMessages = dcount(NetworkMessageId) by EmailClusterId;\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and EmailClusterId > 0\r\n| where OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Messages = count(),\r\n Recipients = dcount(RecipientEmailAddress),\r\n SenderDomains = dcount(SenderFromDomain),\r\n SampleSenderDomains = make_set(SenderFromDomain, 5),\r\n ThreatTypesRaw = make_set(ThreatTypes, 50),\r\n SampleSubjects = make_set(Subject, 5),\r\n FirstSeen = min(Timestamp),\r\n LastSeen = max(Timestamp)\r\n by EmailClusterId\r\n| join kind=leftouter (clicksByCluster) on EmailClusterId\r\n| extend UrlClicks = coalesce(UrlClicks, 0)\r\n| join kind=leftouter (qrClusters) on EmailClusterId\r\n| extend ['QR Code'] = iif(coalesce(QrMessages, 0) > 0, \"QR code\", \"\")\r\n| extend ThreatMix = array_sort_asc(set_union(split(strcat_array(ThreatTypesRaw, \", \"), \", \"), dynamic([])))\r\n| top 20 by Messages\r\n| project ['Email Cluster ID']=EmailClusterId, ['Messages']=Messages, ['Recipients']=Recipients, ['URL Clicks']=UrlClicks, ['Sender Domains']=SenderDomains, ['Sample Sender Domains']=SampleSenderDomains, ['Threat Mix']=ThreatMix, ['QR Code']=['QR Code'], ['Sample Subjects']=SampleSubjects, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", - "size": 0, - "title": "", - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true, - "formatters": [ - { - "columnMatch": "Messages", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Recipients", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "URL Clicks", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "name": "soc - campaigns table", - "id": "a2a391e1-0e26-4e0e-a8d3-26e3c7132079" - }, - { - "type": 1, - "content": { - "json": "\r\n\r\n\r\n\r\n
Most-Clicked Email Campaigns (Recipient Engagement)\r\n
\r\n\r\n**Ranks malicious inbound campaigns by recipient URL clicks, surfacing the attack waves that reached a mailbox and drew engagement regardless of raw message volume. The highest-volume campaigns are usually quarantined before delivery, so the clusters that draw clicks are often smaller, targeted waves. A non-zero URL Clicks count means a recipient opened a URL within the campaign's messages. Because attackers often mix legitimate URLs with malicious ones to build credibility, and a per-URL threat verdict is not available here, treat these as clicks on potentially malicious URLs that warrant review rather than confirmed malicious clicks.**

**Recommended action:** Focus on these clusters for user follow-up (awareness and, where credentials may be exposed, password reset) and hunt for related messages sharing sender infrastructure." - }, - "name": "soc - mostclicked heading", - "id": "e9e41b47-0434-42e5-8b04-4170ab061b81" - }, - { - "type": 3, - "content": { - "version": "KqlItem/1.0", - "query": "//Malicious inbound campaigns ranked by recipient URL clicks - the attack waves that reached a mailbox and drew engagement, regardless of message volume.\r\n//URL Clicks = clicks by recipients on URLs within the campaign's messages (UrlClickEvents joined via NetworkMessageId).\r\nlet clicksByCluster = UrlClickEvents\r\n| join kind=inner (EmailEvents | where EmailClusterId > 0 | distinct NetworkMessageId, EmailClusterId) on NetworkMessageId\r\n| summarize UrlClicks = count() by EmailClusterId;\r\nlet qrClusters = EmailUrlInfo\r\n| where UrlLocation == \"QRCode\"\r\n| join kind=inner (EmailEvents | where EmailClusterId > 0 | distinct NetworkMessageId, EmailClusterId) on NetworkMessageId\r\n| summarize QrMessages = dcount(NetworkMessageId) by EmailClusterId;\r\nEmailEvents\r\n| where EmailDirection == \"Inbound\" and isnotempty(ThreatTypes) and EmailClusterId > 0\r\n| where OrgLevelPolicy !in (\"Phishing simulation\", \"SecOps Mailbox\")\r\n| extend Key = strcat(NetworkMessageId, \"-\", RecipientEmailAddress)\r\n| summarize arg_max(Timestamp, *) by Key\r\n| summarize Messages = count(),\r\n Recipients = dcount(RecipientEmailAddress),\r\n SenderDomains = dcount(SenderFromDomain),\r\n SampleSenderDomains = make_set(SenderFromDomain, 5),\r\n ThreatTypesRaw = make_set(ThreatTypes, 50),\r\n SampleSubjects = make_set(Subject, 5),\r\n FirstSeen = min(Timestamp),\r\n LastSeen = max(Timestamp)\r\n by EmailClusterId\r\n| join kind=inner (clicksByCluster) on EmailClusterId\r\n| where UrlClicks > 0\r\n| join kind=leftouter (qrClusters) on EmailClusterId\r\n| extend ['QR Code'] = iif(coalesce(QrMessages, 0) > 0, \"QR code\", \"\")\r\n| extend ThreatMix = array_sort_asc(set_union(split(strcat_array(ThreatTypesRaw, \", \"), \", \"), dynamic([])))\r\n| top 20 by UrlClicks\r\n| project ['Email Cluster ID']=EmailClusterId, ['URL Clicks']=UrlClicks, ['Messages']=Messages, ['Recipients']=Recipients, ['Sender Domains']=SenderDomains, ['Sample Sender Domains']=SampleSenderDomains, ['Threat Mix']=ThreatMix, ['QR Code']=['QR Code'], ['Sample Subjects']=SampleSubjects, ['First Seen']=FirstSeen, ['Last Seen']=LastSeen", - "size": 0, - "title": "", - "timeContextFromParameter": "TimeRange", - "queryType": "advancedHunting", - "visualization": "table", - "gridSettings": { - "filter": true, - "formatters": [ - { - "columnMatch": "URL Clicks", - "formatter": 3, - "formatOptions": { - "palette": "redDark", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Messages", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - }, - { - "columnMatch": "Recipients", - "formatter": 3, - "formatOptions": { - "palette": "blue", - "customColumnWidthSetting": "130px" - }, - "numberFormat": { - "unit": 17, - "options": { - "style": "decimal", - "maximumFractionDigits": 1 - } - } - } - ] - }, - "timeContext": { - "durationMs": 0 - } - }, - "name": "soc - mostclicked table", - "id": "1ffe8f97-ad79-47d9-9598-dd73ee54cd8d" - } - ] - }, - "conditionalVisibility": { - "parameterName": "Tab", - "comparison": "isEqualTo", - "value": "13" - }, - "name": "soc - campaigns group", - "styleSettings": { - "margin": "10px", - "padding": "10px", - "showBorder": true - }, - "id": "b8f2a1c4-5d6e-4a7b-9c8d-0e1f2a3b4c5d" - } - ], - "isLocked": false, - "fallbackResourceIds": [], - "$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json" -} diff --git a/Solutions/Microsoft Defender for Office 365/XDR Workbooks/MicrosoftDefenderForOffice365DetectionsAndInsights.json b/Solutions/Microsoft Defender for Office 365/XDR Workbooks/MicrosoftDefenderForOffice365DetectionsAndInsights.json index 3c8db20130e..329376bf24f 100644 --- a/Solutions/Microsoft Defender for Office 365/XDR Workbooks/MicrosoftDefenderForOffice365DetectionsAndInsights.json +++ b/Solutions/Microsoft Defender for Office 365/XDR Workbooks/MicrosoftDefenderForOffice365DetectionsAndInsights.json @@ -14901,12 +14901,14 @@ }, "contentProvenance": { "origin": "native-xdr", + "canonicalPayloadSha256": "66e8c70ef1e7a966f64f23e78b1ab842c184f1661b0cab41527b546daa34f59f", "source": { "path": "Workbook Sources/Native/MicrosoftDefenderForOffice365DetectionsAndInsights.json", "sha256": "7985b58b9c0f12ca79dd7d7ca33a197243c23953508bf81638082ff3a2663b6b" }, "nativeReview": { "origin": "native-xdr", + "canonicalPayloadSha256": "66e8c70ef1e7a966f64f23e78b1ab842c184f1661b0cab41527b546daa34f59f", "source": { "path": "Workbook Sources/Native/MicrosoftDefenderForOffice365DetectionsAndInsights.json", "sha256": "7985b58b9c0f12ca79dd7d7ca33a197243c23953508bf81638082ff3a2663b6b" From 97aac09c6a96e2bd934f194b44d3628ef3441f3b Mon Sep 17 00:00:00 2001 From: kingwil <5839248+kingwil@users.noreply.github.com> Date: Thu, 15 Oct 2026 10:05:37 +0100 Subject: [PATCH 6/6] Add O365 Partner Center usage attribution marker Use the exact O365 offer tracking ID supplied by the owner. Regenerate the additive 3.2.0 candidate with V3.1; the sole semantic ARM addition is the empty unconditional root attribution deployment. Both XDR workbooks and existing Sentinel content remain unchanged. Automatic ARM-TTK reports 47 passes and six failures plus the existing null-Path diagnostic. Partner Center acceptance remains unverified. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../Package/3.2.0.zip | Bin 257672 -> 257827 bytes .../Package/mainTemplate.json | 13 +++++++++++++ .../SolutionMetadata.json | 1 + 3 files changed, 14 insertions(+) diff --git a/Solutions/Microsoft Defender for Office 365/Package/3.2.0.zip b/Solutions/Microsoft Defender for Office 365/Package/3.2.0.zip index 2fc9e487489953aa53685e5af20671008ee4085e..7378e113fc8ee5d8c32f36c7b2299383a9b607ad 100644 GIT binary patch delta 17110 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