diff --git a/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_CommonSecurityLog.yaml b/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_CommonSecurityLog.yaml index 0e07756ac06..92ae798cb54 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_CommonSecurityLog.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_CommonSecurityLog.yaml @@ -25,11 +25,11 @@ query: | // Create a list of top-level domains (TLDs) from the threat feed data for later validation let list_tlds = ThreatIntelligenceIndicator + | where isnotempty(DomainName) // Filter indicators based on the specified time range and active indicators | where TimeGenerated >= ago(ioc_lookBack) | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId | where Active == true and ExpirationDateTime > now() - | where isnotempty(DomainName) // Convert domain names to lowercase for consistency | extend DomainName = tolower(DomainName) // Split domain names into parts and extract the TLD @@ -42,11 +42,11 @@ query: | // Retrieve threat intelligence indicators within the specified time range let Domain_Indicators = ThreatIntelligenceIndicator + // Filter indicators that have a non-empty domain name + | where isnotempty(DomainName) | where TimeGenerated >= ago(ioc_lookBack) | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId | where Active == true and ExpirationDateTime > now() - // Filter indicators that have a non-empty domain name - | where isnotempty(DomainName) | extend TI_DomainEntity = DomainName; // Join threat intelligence indicators with common security logs Domain_Indicators @@ -88,5 +88,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: PA_Url -version: 1.4.0 +version: 1.4.1 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_DnsEvents.yaml b/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_DnsEvents.yaml index 26bb96db16d..36fdfff3e2f 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_DnsEvents.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_DnsEvents.yaml @@ -28,11 +28,11 @@ query: | let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators // Fetch threat intelligence indicators related to domains let Domain_Indicators = ThreatIntelligenceIndicator + // Filter out indicators without domain names + | where isnotempty(DomainName) | where TimeGenerated >= ago(ioc_lookBack) | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId | where Active == true and ExpirationDateTime > now() - // Filter out indicators without domain names - | where isnotempty(DomainName) | extend TI_DomainEntity = DomainName; // Create a list of TLDs in our threat feed for later validation let maxListSize = 100000; // Define the maximum allowed size for each list @@ -81,5 +81,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: Url -version: 1.4.0 +version: 1.4.1 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_PaloAlto.yaml b/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_PaloAlto.yaml index 27a1248acf3..5628c9512be 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_PaloAlto.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_PaloAlto.yaml @@ -28,10 +28,10 @@ query: | // Create a list of top-level domains (TLDs) in our threat feed for later validation of extracted domains let list_tlds = ThreatIntelligenceIndicator + | where isnotempty(DomainName) | where TimeGenerated >= ago(ioc_lookBack) | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId | where Active == true and ExpirationDateTime > now() - | where isnotempty(DomainName) | extend DomainName = tolower(DomainName) | extend parts = split(DomainName, '.') | extend tld = parts[(array_length(parts)-1)] @@ -90,5 +90,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: PA_Url -version: 1.4.0 +version: 1.4.1 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_SecurityAlert.yaml b/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_SecurityAlert.yaml index 31859ac00ce..19724832b92 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_SecurityAlert.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_SecurityAlert.yaml @@ -30,20 +30,20 @@ query: | let ioc_lookBack = 14d; // Lookback time for threat feed data, set to 14 days // Create a list of TLDs in our threat feed for later validation let list_tlds = ThreatIntelligenceIndicator + | where isnotempty(DomainName) | where TimeGenerated >= ago(ioc_lookBack) | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId | where Active == true and ExpirationDateTime > now() - | where isnotempty(DomainName) | extend parts = split(DomainName, '.') | extend tld = parts[(array_length(parts)-1)] | summarize count() by tostring(tld) | summarize make_list(tld); let Domain_Indicators = ThreatIntelligenceIndicator + // Picking up only IOC's that contain the entities we want + | where isnotempty(DomainName) | where TimeGenerated >= ago(ioc_lookBack) | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId | where Active == true and ExpirationDateTime > now() - // Picking up only IOC's that contain the entities we want - | where isnotempty(DomainName) | extend TI_DomainEntity = DomainName; Domain_Indicators // Using innerunique to keep performance fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated @@ -88,5 +88,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: Url -version: 1.4.1 +version: 1.4.2 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_Syslog.yaml b/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_Syslog.yaml index d5115e21608..583024e6802 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_Syslog.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_Syslog.yaml @@ -27,20 +27,20 @@ query: | let ioc_lookBack = 14d; // Define the time range to look back for threat intelligence indicators (14 days) // Create a list of top-level domains (TLDs) from the threat feed for later validation let list_tlds = ThreatIntelligenceIndicator + | where isnotempty(DomainName) | where TimeGenerated > ago(ioc_lookBack) | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId | where Active == true and ExpirationDateTime > now() - | where isnotempty(DomainName) | extend parts = split(DomainName, '.') | extend tld = parts[(array_length(parts)-1)] | summarize count() by tostring(tld) | summarize make_list(tld); // Fetch the latest active domain indicators from the threat intelligence data within the specified time range let Domain_Indicators = ThreatIntelligenceIndicator + | where isnotempty(DomainName) | where TimeGenerated >= ago(ioc_lookBack) | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId | where Active == true and ExpirationDateTime > now() - | where isnotempty(DomainName) | extend TI_DomainEntity = DomainName; // Join the threat intelligence indicators with syslog data on matching domain entities Domain_Indicators @@ -83,5 +83,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: Url -version: 1.4.0 +version: 1.4.1 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_imWebSession.yaml b/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_imWebSession.yaml index 456273bb253..9aab8910ad8 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_imWebSession.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/DomainEntity_imWebSession.yaml @@ -13,6 +13,9 @@ requiredDataConnectors: - connectorId: ThreatIntelligence dataTypes: - ThreatIntelligenceIndicator + - connectorId: ThreatIntelligenceTaxii + dataTypes: + - ThreatIntelligenceIndicator - connectorId: MicrosoftDefenderThreatIntelligence dataTypes: - ThreatIntelligenceIndicator @@ -28,11 +31,11 @@ query: | let ioc_lookBack = 14d; //Create a list of TLDs in our threat feed for later validation let DOMAIN_TI=ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now() - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true // Picking up only IOC's that contain the entities we want - | where isnotempty(DomainName); + | where isnotempty(DomainName) + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now(); let DOMAIN_TI_list= todynamic(toscalar(DOMAIN_TI | summarize NIoCs = dcount(DomainName), Domains = make_set(DomainName) | project Domains=iff(NIoCs > HAS_ANY_MAX, dynamic([]), Domains) )); DOMAIN_TI @@ -68,5 +71,5 @@ customDetails: alertDetailsOverride: alertDisplayNameFormat: A web request from {{SrcIpAddr}} to hostname {{domain}} matched an IoC alertDescriptionFormat: A client with address {{SrcIpAddr}} requested the URL {{Url}}, whose hostname is a known indicator of compromise of {{ThreatType}}. Consult the threat intelligence blade for more information on the indicator. -version: 1.0.4 +version: 1.0.5 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_AzureActivity.yaml b/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_AzureActivity.yaml index 53f1aed8ca4..4e8754bcdd0 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_AzureActivity.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_AzureActivity.yaml @@ -27,11 +27,11 @@ query: | let ioc_lookBack = 14d; let emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'; ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now() - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true //Filtering the table for Email related IOCs + | where TimeGenerated >= ago(ioc_lookBack) | where isnotempty(EmailSenderAddress) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now() // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated | join kind=innerunique ( AzureActivity | where TimeGenerated >= ago(dt_lookBack) and isnotempty(Caller) @@ -62,5 +62,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: Url -version: 1.2.4 +version: 1.2.5 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_OfficeActivity.yaml b/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_OfficeActivity.yaml index 4d57ff925f2..e407db5f33d 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_OfficeActivity.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_OfficeActivity.yaml @@ -27,11 +27,11 @@ query: | let ioc_lookBack = 14d; let emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'; ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now() - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true //Filtering the table for Email related IOCs | where isnotempty(EmailSenderAddress) + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now() // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated | join kind=innerunique ( OfficeActivity | where TimeGenerated >= ago(dt_lookBack) and isnotempty(UserId) @@ -60,5 +60,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: Url -version: 1.2.4 +version: 1.2.5 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_PaloAlto.yaml b/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_PaloAlto.yaml index 04199d7dc70..db7b384ef71 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_PaloAlto.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_PaloAlto.yaml @@ -27,11 +27,11 @@ query: | let ioc_lookBack = 14d; let emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'; ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now() - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true //Filtering the table for Email related IOCs | where isnotempty(EmailSenderAddress) + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now() // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated | join kind=innerunique ( CommonSecurityLog | where TimeGenerated >= ago(dt_lookBack) and isnotempty(DestinationUserID) @@ -61,5 +61,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: Url -version: 1.2.4 +version: 1.2.5 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_SecurityAlert.yaml b/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_SecurityAlert.yaml index d859239f10c..b424fe24528 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_SecurityAlert.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_SecurityAlert.yaml @@ -27,11 +27,11 @@ query: | let ioc_lookBack = 14d; let emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'; ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now() - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true //Filtering the table for Email related IOCs | where isnotempty(EmailSenderAddress) + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now() // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated | join kind=innerunique ( SecurityAlert @@ -67,5 +67,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: Url -version: 1.2.5 +version: 1.2.6 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_SecurityEvent.yaml b/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_SecurityEvent.yaml index 98872d798cc..537c228c671 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_SecurityEvent.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_SecurityEvent.yaml @@ -33,11 +33,11 @@ query: | let ioc_lookBack = 14d; let emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'; ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now() - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true //Filtering the table for Email related IOCs | where isnotempty(EmailSenderAddress) + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now() // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated | join kind=innerunique ( (union isfuzzy=true @@ -85,5 +85,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: Url -version: 1.3.4 +version: 1.3.5 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_SigninLogs.yaml b/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_SigninLogs.yaml index f302b0ddc80..5120be123e1 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_SigninLogs.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/EmailEntity_SigninLogs.yaml @@ -31,11 +31,11 @@ query: | let emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'; let aadFunc = (tableName:string){ ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now() - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true //Filtering the table for Email related IOCs | where isnotempty(EmailSenderAddress) + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now() // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated | join kind=innerunique ( table(tableName) | where TimeGenerated >= ago(dt_lookBack) and isnotempty(UserPrincipalName) @@ -75,5 +75,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: Url -version: 1.2.4 +version: 1.2.5 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/FileHashEntity_CommonSecurityLog.yaml b/Solutions/Threat Intelligence/Analytic Rules/FileHashEntity_CommonSecurityLog.yaml index 5e93d7a428d..9a5e9c581e9 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/FileHashEntity_CommonSecurityLog.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/FileHashEntity_CommonSecurityLog.yaml @@ -26,10 +26,10 @@ query: | let dt_lookBack = 1h; let ioc_lookBack = 14d; let fileHashIndicators = ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now() + | where isnotempty(FileHashValue) + | where TimeGenerated >= ago(ioc_lookBack) | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true - | where isnotempty(FileHashValue); + | where Active == true and ExpirationDateTime > now(); // Handle matches against both lower case and uppercase versions of the hash: (fileHashIndicators | extend FileHashValue = tolower(FileHashValue) | union (fileHashIndicators | extend FileHashValue = toupper(FileHashValue))) @@ -75,5 +75,5 @@ entityMappings: columnName: FileHashValue - identifier: Algorithm columnName: FileHashType -version: 1.3.3 +version: 1.3.4 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/FileHashEntity_SecurityEvent.yaml b/Solutions/Threat Intelligence/Analytic Rules/FileHashEntity_SecurityEvent.yaml index 0f4686c3796..f5d1abb951d 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/FileHashEntity_SecurityEvent.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/FileHashEntity_SecurityEvent.yaml @@ -32,11 +32,11 @@ query: | let dt_lookBack = 1h; let ioc_lookBack = 14d; ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now() - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true | where isnotempty(FileHashValue) | extend FileHashValue = toupper(FileHashValue) + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now() // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated | join kind=innerunique ( union isfuzzy=true (SecurityEvent | where TimeGenerated >= ago(dt_lookBack) @@ -81,5 +81,5 @@ entityMappings: columnName: FileHashValue - identifier: Algorithm columnName: FileHashType -version: 1.4.3 +version: 1.4.4 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AWSCloudTrail.yaml b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AWSCloudTrail.yaml index d660af1aacd..938d6301937 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AWSCloudTrail.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AWSCloudTrail.yaml @@ -27,9 +27,6 @@ query: | let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators // Fetch threat intelligence indicators related to IP addresses let IP_Indicators = ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true and ExpirationDateTime > now() // Filter out indicators without relevant IP address fields | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP) // Select the IP entity based on availability of different IP fields @@ -37,7 +34,10 @@ query: | | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity) // Exclude local addresses using the ipv4_is_private operator and filtering out specific address prefixes - | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."; + | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127." + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now(); // Perform a join between IP indicators and AWSCloudTrail logs to identify potential malicious activity IP_Indicators // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation @@ -70,5 +70,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: Url -version: 1.4.0 +version: 1.4.1 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AppServiceHTTPLogs.yaml b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AppServiceHTTPLogs.yaml index 254f81bf3af..65d67d51af6 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AppServiceHTTPLogs.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AppServiceHTTPLogs.yaml @@ -24,9 +24,6 @@ query: | let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators // Fetch threat intelligence indicators related to IP addresses let IP_Indicators = ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true and ExpirationDateTime > now() // Filter out indicators without relevant IP address fields | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP) // Select the IP entity based on availability of different IP fields @@ -40,7 +37,10 @@ query: | ConfidenceScore > 74, "Medium", "Low") // Exclude local addresses using the ipv4_is_private operator and filtering out specific address prefixes - | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."; + | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127." + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now(); // Perform a join between IP indicators and AppServiceHTTPLogs to identify potential malicious activity IP_Indicators // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation @@ -86,6 +86,6 @@ entityMappings: columnName: _ResourceId alertDetailsOverride: alertSeverityColumnName: AlertPriority -version: 1.5.0 +version: 1.5.1 kind: Scheduled \ No newline at end of file diff --git a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AzureActivity.yaml b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AzureActivity.yaml index 19dc9d3bab4..6b6deec4b0e 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AzureActivity.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AzureActivity.yaml @@ -27,9 +27,6 @@ query: | let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators // Fetch threat intelligence indicators related to IP addresses let IP_Indicators = ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true and ExpirationDateTime > now() // Filter out indicators without relevant IP address fields | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP) // Select the IP entity based on availability of different IP fields @@ -37,7 +34,10 @@ query: | | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity) // Exclude local addresses using the ipv4_is_private operator and filtering out specific address prefixes - | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."; + | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127." + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now(); // Perform a join between IP indicators and AzureActivity logs to identify potential malicious activity IP_Indicators // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated @@ -76,5 +76,5 @@ entityMappings: fieldMappings: - identifier: ResourceId columnName: ResourceId -version: 1.4.0 +version: 1.4.1 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AzureFirewall.yaml b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AzureFirewall.yaml index 84f0a3c58c5..7f645e51dda 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AzureFirewall.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AzureFirewall.yaml @@ -27,9 +27,6 @@ query: | let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators // Fetch threat intelligence indicators related to IP addresses let IP_Indicators = ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true and ExpirationDateTime > now() // Filter out indicators without relevant IP address fields | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP) // Select the IP entity based on availability of different IP fields @@ -37,7 +34,10 @@ query: | | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity) // Exclude local addresses using the ipv4_is_private operator and filtering out specific address prefixes - | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."; + | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127." + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now(); // Perform a join between IP indicators and AzureDiagnostics logs to identify potential malicious activity IP_Indicators // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation @@ -72,5 +72,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: Url -version: 1.3.0 +version: 1.3.1 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AzureKeyVault.yaml b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AzureKeyVault.yaml index d66fa97a017..0c1198617db 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AzureKeyVault.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AzureKeyVault.yaml @@ -27,14 +27,15 @@ query: | let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators // Fetch threat intelligence indicators related to IP addresses let IP_Indicators = ThreatIntelligenceIndicator - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP) | where LatestIndicatorTime >= ago(ioc_lookBack) and ExpirationDateTime > now() | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity) - | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."; + | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127." + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now(); // Perform a join between IP indicators and AzureDiagnostics logs for Key Vault events IP_Indicators // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation @@ -64,5 +65,5 @@ entityMappings: fieldMappings: - identifier: ResourceId columnName: ResourceId -version: 1.3.2 +version: 1.3.3 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AzureNetworkAnalytics.yaml b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AzureNetworkAnalytics.yaml index a40c6d30232..ce8c56f3730 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AzureNetworkAnalytics.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AzureNetworkAnalytics.yaml @@ -24,14 +24,14 @@ query: | let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators // Fetch threat intelligence indicators related to IP addresses let IP_Indicators = ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true and ExpirationDateTime > now() | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP) | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity) - | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."; + | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127." + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now(); // Perform a join between IP indicators and AzureNetworkAnalytics_CL logs for NSG Flow information IP_Indicators // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation @@ -71,5 +71,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: Url -version: 1.4.0 +version: 1.4.1 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AzureSQL.yaml b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AzureSQL.yaml index 02904d27bff..b134efdeba4 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AzureSQL.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_AzureSQL.yaml @@ -27,14 +27,14 @@ query: | let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators // Fetch threat intelligence indicators related to IP addresses let IP_Indicators = ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true and ExpirationDateTime > now() | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP) | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity) - | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."; + | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127." + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now(); // Perform a join between IP indicators and AzureDiagnostics logs for SQL Security Audit events IP_Indicators // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation @@ -64,5 +64,5 @@ entityMappings: fieldMappings: - identifier: Address columnName: ClientIP -version: 1.3.0 +version: 1.3.1 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_CustomSecurityLog.yaml b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_CustomSecurityLog.yaml index 036f8ebcf1e..301c28b631c 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_CustomSecurityLog.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_CustomSecurityLog.yaml @@ -28,14 +28,14 @@ query: | let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators // Fetch threat intelligence indicators related to IP addresses let IP_Indicators = ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true and ExpirationDateTime > now() | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP) | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity) - | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."; + | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127." + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now(); // Perform a join between IP indicators and CommonSecurityLog events IP_Indicators // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation @@ -59,5 +59,5 @@ entityMappings: fieldMappings: - identifier: Address columnName: CS_ipEntity -version: 1.2.0 +version: 1.2.1 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_DnsEvents.yaml b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_DnsEvents.yaml index cf061464552..f7f1e5a338f 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_DnsEvents.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_DnsEvents.yaml @@ -27,14 +27,14 @@ query: | let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators // Fetch threat intelligence indicators related to IP addresses let IP_Indicators = ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true and ExpirationDateTime > now() | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP) | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity) - | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."; + | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127." + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now(); // Perform a join between IP indicators and DNS events IP_Indicators // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation @@ -69,5 +69,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: Url -version: 1.4.0 +version: 1.4.1 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_DuoSecurity.yaml b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_DuoSecurity.yaml index 5b6c8696076..55ff83bef87 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_DuoSecurity.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_DuoSecurity.yaml @@ -26,9 +26,6 @@ query: | let dt_lookBack = 1h; let ioc_lookBack = 14d; ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now() - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true // Picking up only IOC's that contain the entities we want | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP) // As there is potentially more than 1 indicator type for matching IP, taking NetworkIP first, then others if that is empty. @@ -36,6 +33,9 @@ query: | | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity) + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now() | join ( DuoSecurityAuthentication_CL | where TimeGenerated >= ago(dt_lookBack) @@ -44,7 +44,9 @@ query: | | extend Duo_TimeGenerated = isotimestamp_t ) on $left.TI_ipEntity == $right.access_device_ip_s + | where TimeGenerated >= ago(ioc_lookBack) | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now() | project LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, Duo_TimeGenerated, TI_ipEntity, user_name_s, factor_s, result_s, application_name_s, event_type_s, txid_g, user_key_s, access_device_ip_s, access_device_location_city_s, access_device_location_state_s, access_device_location_country_s | extend timestamp = Duo_TimeGenerated, Name = tostring(split(user_name_s, '@', 0)[0]), UPNSuffix = tostring(split(user_name_s, '@', 1)[0]) @@ -59,5 +61,5 @@ entityMappings: fieldMappings: - identifier: Address columnName: access_device_ip_s -version: 1.0.3 +version: 1.0.4 kind: Scheduled \ No newline at end of file diff --git a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_OfficeActivity.yaml b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_OfficeActivity.yaml index 5a20c7ea641..6159f8b9594 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_OfficeActivity.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_OfficeActivity.yaml @@ -27,14 +27,14 @@ query: | let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators // Fetch threat intelligence indicators related to IP addresses let IP_Indicators = ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true and ExpirationDateTime > now() | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP) | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity) - | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."; + | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127." + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now(); // Perform a join between IP indicators and OfficeActivity events IP_Indicators // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation @@ -70,5 +70,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: Url -version: 1.4.0 +version: 1.4.1 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_SigninLogs.yaml b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_SigninLogs.yaml index b50795e12c8..4d41f219404 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_SigninLogs.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_SigninLogs.yaml @@ -30,9 +30,6 @@ query: | let ioc_lookBack = 14d; let aadFunc = (tableName:string){ ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now() - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true // Picking up only IOC's that contain the entities we want | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP) // As there is potentially more than 1 indicator type for matching IP, taking NetworkIP first, then others if that is empty. @@ -40,6 +37,9 @@ query: | | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity) + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now() // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated | join kind=innerunique ( table(tableName) | where TimeGenerated >= ago(dt_lookBack) @@ -74,5 +74,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: Url -version: 1.2.5 +version: 1.2.6 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_VMConnection.yaml b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_VMConnection.yaml index 2abc531a14c..696329dbf50 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_VMConnection.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_VMConnection.yaml @@ -27,14 +27,14 @@ query: | let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators // Fetch threat intelligence indicators related to IP addresses let IP_Indicators = ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true and ExpirationDateTime > now() | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP) | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity) - | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."; + | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127." + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now(); // Perform a join between IP indicators and VMConnection events IP_Indicators // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation @@ -67,5 +67,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: Url -version: 1.4.0 +version: 1.4.1 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_W3CIISLog.yaml b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_W3CIISLog.yaml index 047bbd16aca..6f141c371cf 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_W3CIISLog.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_W3CIISLog.yaml @@ -27,14 +27,14 @@ query: | let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators // Fetch threat intelligence indicators related to IP addresses let IP_Indicators = ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true and ExpirationDateTime > now() | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP) | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity) | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity) - | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."; + | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127." + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now(); // Perform a join between IP indicators and W3CIISLog events IP_Indicators // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation @@ -71,5 +71,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: Url -version: 1.4.0 +version: 1.4.1 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_imNetworkSession.yaml b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_imNetworkSession.yaml index 4868d5e72bf..5c65d42ce91 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_imNetworkSession.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_imNetworkSession.yaml @@ -58,6 +58,9 @@ requiredDataConnectors: dataTypes: - Syslog - CiscoMerakiNativePoller + - connectorId: ThreatIntelligenceTaxii + dataTypes: + - ThreatIntelligenceIndicator queryFrequency: 1h queryPeriod: 14d @@ -70,11 +73,11 @@ query: | let ioc_lookBack = 14d; let IP_TI = materialize ( ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now() - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true | extend TI_ipEntity = coalesce(NetworkIP, NetworkDestinationIP, NetworkSourceIP,EmailSourceIpAddress,"NO_IP") | where TI_ipEntity != "NO_IP" + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now() ); IP_TI // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated @@ -119,5 +122,5 @@ tags: - Schema: ASIMNetworkSession SchemaVersion: 0.2.4 -version: 1.2.4 +version: 1.2.5 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_imWebSession.yaml b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_imWebSession.yaml index 0be5ccd7168..66854aa2d76 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/IPEntity_imWebSession.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/IPEntity_imWebSession.yaml @@ -30,16 +30,16 @@ query: | let dt_lookBack = 1h; let ioc_lookBack = 14d; let IP_TI = ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true and ExpirationDateTime > now() // As there is potentially more than 1 indicator type for matching IP, taking NetworkIP first, then others if that is empty. // Taking the first non-empty value based on potential IOC match availability | extend TI_ipEntity = coalesce(NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, "NO_IP") // Picking up only IOC's that contain the entities we want | where TI_ipEntity != "NO_IP" // Exclude local addresses, using the ipv4_is_private operator - | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127."; + | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith "fe80" and TI_ipEntity !startswith "::" and TI_ipEntity !startswith "127." + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now(); let IP_TI_list = toscalar(IP_TI | summarize NIoCs = dcount(TI_ipEntity), IoCs = make_set(TI_ipEntity) | project IoCs = iff(NIoCs > HAS_ANY_MAX, dynamic([]), IoCs)); @@ -72,5 +72,5 @@ customDetails: alertDetailsOverride: alertDisplayNameFormat: The IP {{SrcIpAddr}} of the web request matches an IP IoC alertDescriptionFormat: The source address {{SrcIpAddr}} of the web request for the URL {{Url}} matches a known indicator of compromise of {{ThreatType}}. Consult the threat intelligence feed for more information about the indicator. -version: 1.2.3 +version: 1.2.4 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/Threat Intel Matches to GitHub Audit Logs.yaml b/Solutions/Threat Intelligence/Analytic Rules/Threat Intel Matches to GitHub Audit Logs.yaml index 576680f6f1f..2b810579557 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/Threat Intel Matches to GitHub Audit Logs.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/Threat Intel Matches to GitHub Audit Logs.yaml @@ -20,8 +20,8 @@ triggerThreshold: 0 tactics: - Impact query: | + let ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators ThreatIntelligenceIndicator - | where Action == true // Picking up only IOC's that contain the entities we want | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP) // Taking the first non-empty value based on potential IOC match availability @@ -33,7 +33,9 @@ query: | | extend GitHubAudit_TimeGenerated = TimeGenerated ) on $left.TI_ipEntity == $right.IPaddress + | where TimeGenerated >= ago(ioc_lookBack) | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now() | project LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, GitHubAudit_TimeGenerated, TI_ipEntity, IPaddress, Actor, Action, Country, OperationType, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress | extend timestamp = GitHubAudit_TimeGenerated, IPCustomEntity = IPaddress, AccountCustomEntity = Actor entityMappings: @@ -45,5 +47,5 @@ entityMappings: fieldMappings: - identifier: Address columnName: IPCustomEntity -version: 1.0.2 +version: 1.0.3 kind: Scheduled \ No newline at end of file diff --git a/Solutions/Threat Intelligence/Analytic Rules/URLEntity_AuditLogs.yaml b/Solutions/Threat Intelligence/Analytic Rules/URLEntity_AuditLogs.yaml index 3e1511c765a..a36057961d2 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/URLEntity_AuditLogs.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/URLEntity_AuditLogs.yaml @@ -26,11 +26,11 @@ query: | let dt_lookBack = 1h; let ioc_lookBack = 14d; ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now() - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true // Picking up only IOC's that contain the entities we want | where isnotempty(Url) + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now() // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated | join kind=innerunique ( AuditLogs @@ -60,5 +60,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: URLCustomEntity -version: 1.2.4 +version: 1.2.5 kind: Scheduled \ No newline at end of file diff --git a/Solutions/Threat Intelligence/Analytic Rules/URLEntity_OfficeActivity.yaml b/Solutions/Threat Intelligence/Analytic Rules/URLEntity_OfficeActivity.yaml index 0a09429b5d5..23a42fcc464 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/URLEntity_OfficeActivity.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/URLEntity_OfficeActivity.yaml @@ -13,6 +13,9 @@ requiredDataConnectors: - connectorId: MicrosoftDefenderThreatIntelligence dataTypes: - ThreatIntelligenceIndicator + - connectorId: ThreatIntelligenceTaxii + dataTypes: + - ThreatIntelligenceIndicator queryFrequency: 1h queryPeriod: 14d triggerOperator: gt @@ -23,11 +26,11 @@ query: | let dt_lookBack = 1h; let ioc_lookBack = 14d; ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now() - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true // Picking up only IOC's that contain the entities we want | where isnotempty(Url) + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now() // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated | join kind=innerunique ( OfficeActivity @@ -57,5 +60,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: Url -version: 1.2.5 +version: 1.2.6 kind: Scheduled diff --git a/Solutions/Threat Intelligence/Analytic Rules/URLEntity_PaloAlto.yaml b/Solutions/Threat Intelligence/Analytic Rules/URLEntity_PaloAlto.yaml index 0b532cdfa8c..6960697068c 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/URLEntity_PaloAlto.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/URLEntity_PaloAlto.yaml @@ -26,11 +26,11 @@ query: | let dt_lookBack = 1h; let ioc_lookBack = 14d; ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now() - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true // Picking up only IOC's that contain the entities we want | where isnotempty(Url) + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now() // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated | join kind=innerunique ( CommonSecurityLog @@ -64,5 +64,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: PA_Url -version: 1.2.3 +version: 1.2.4 kind: Scheduled \ No newline at end of file diff --git a/Solutions/Threat Intelligence/Analytic Rules/URLEntity_SecurityAlerts.yaml b/Solutions/Threat Intelligence/Analytic Rules/URLEntity_SecurityAlerts.yaml index 3ede7de1e37..99d672dd301 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/URLEntity_SecurityAlerts.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/URLEntity_SecurityAlerts.yaml @@ -30,11 +30,11 @@ query: | let ioc_lookBack = 14d; let URLRegex = "((https?|ftp|ldap|wss?|file):\\/\\/(([\\:\\%\\w\\_\\-]+(\\.|@))*((xn--)?[a-zA-Z0-9\\-]+\\.)+(xn--[a-z0-9]+|[A-Za-z]+)|\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{0,3})[.,:\\w@?^=%&\\/~+#-]*[\\w@?^=%&\\/~+#-])"; ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now() - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true // Picking up only IOC's that contain the entities we want | where isnotempty(Url) + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now() // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated | join kind=innerunique ( SecurityAlert @@ -63,5 +63,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: Url -version: 1.2.6 +version: 1.2.7 kind: Scheduled \ No newline at end of file diff --git a/Solutions/Threat Intelligence/Analytic Rules/URLEntity_Syslog.yaml b/Solutions/Threat Intelligence/Analytic Rules/URLEntity_Syslog.yaml index a1f74dad0f9..ce3c31d6d8b 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/URLEntity_Syslog.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/URLEntity_Syslog.yaml @@ -26,11 +26,11 @@ query: | let dt_lookBack = 1h; let ioc_lookBack = 14d; ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now() - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true // Picking up only IOC's that contain the entities we want | where isnotempty(Url) + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now() // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated | join kind=innerunique ( Syslog @@ -56,5 +56,5 @@ entityMappings: fieldMappings: - identifier: Url columnName: Url -version: 1.2.4 +version: 1.2.5 kind: Scheduled \ No newline at end of file diff --git a/Solutions/Threat Intelligence/Analytic Rules/imDns_DomainEntity_DnsEvents.yaml b/Solutions/Threat Intelligence/Analytic Rules/imDns_DomainEntity_DnsEvents.yaml index b8b8d971f0f..f3398976761 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/imDns_DomainEntity_DnsEvents.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/imDns_DomainEntity_DnsEvents.yaml @@ -55,11 +55,11 @@ query: | let dt_lookBack = 1h; let ioc_lookBack = 14d; let DomainTIs= ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now() // Picking up only IOC's that contain the entities we want | where isnotempty(DomainName) - | where Active == true - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId; + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now(); let Domains = DomainTIs | where isnotempty(DomainName) |summarize NDomains=dcount(DomainName), DomainsList=make_set(DomainName) | project DomainList = iff(NDomains > HAS_ANY_MAX, dynamic([]), DomainsList) ; DomainTIs @@ -96,5 +96,5 @@ customDetails: SourceIPAddress: SrcIpAddr DnsQuery: DnsQuery QueryType: DnsQueryType -version: 1.1.4 +version: 1.1.5 kind: Scheduled \ No newline at end of file diff --git a/Solutions/Threat Intelligence/Analytic Rules/imDns_IPEntity_DnsEvents.yaml b/Solutions/Threat Intelligence/Analytic Rules/imDns_IPEntity_DnsEvents.yaml index e14de01d8ad..4ece8c2660b 100644 --- a/Solutions/Threat Intelligence/Analytic Rules/imDns_IPEntity_DnsEvents.yaml +++ b/Solutions/Threat Intelligence/Analytic Rules/imDns_IPEntity_DnsEvents.yaml @@ -55,11 +55,11 @@ query: | let ioc_lookBack = 14d; let IP_TI = ThreatIntelligenceIndicator - | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now() - | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId - | where Active == true | extend IoC = coalesce(NetworkIP, NetworkDestinationIP, NetworkSourceIP,EmailSourceIpAddress,"NO_IP") | where IoC != "NO_IP" + | where TimeGenerated >= ago(ioc_lookBack) + | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId + | where Active == true and ExpirationDateTime > now() ; IP_TI | join kind=innerunique // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated @@ -104,5 +104,5 @@ alertDetailsOverride: alertDisplayNameFormat: The response {{IoC}} to DNS query matched an IoC alertDescriptionFormat: The response address {{IoC}} to a DNS query matched a known indicator of compromise of {{ThreatType}}. Consult the threat intelligence blade for more information on the indicator. -version: 1.2.2 +version: 1.2.3 kind: Scheduled \ No newline at end of file diff --git a/Solutions/Threat Intelligence/Package/3.0.2.zip b/Solutions/Threat Intelligence/Package/3.0.2.zip new file mode 100644 index 00000000000..d68d660d725 Binary files /dev/null and b/Solutions/Threat Intelligence/Package/3.0.2.zip differ diff --git a/Solutions/Threat Intelligence/Package/createUiDefinition.json b/Solutions/Threat Intelligence/Package/createUiDefinition.json index ef11906573f..bc869aff5a8 100644 --- a/Solutions/Threat Intelligence/Package/createUiDefinition.json +++ b/Solutions/Threat Intelligence/Package/createUiDefinition.json @@ -51,100 +51,6 @@ } ], "steps": [ - { - "name": "dataconnectors", - "label": "Data Connectors", - "bladeTitle": "Data Connectors", - "elements": [ - { - "name": "dataconnectors1-text", - "type": "Microsoft.Common.TextBlock", - "options": { - "text": "This solution installs four (4) data connectors for ingesting threat indicators (IP addresses, domains, URLs and file hashes) into Microsoft Sentinel. The ingested threat indicators can be used for correlation to enable monitoring, alerting, and hunting using your threat intelligence." - } - }, - { - "name": "dataconnectors2-text", - "type": "Microsoft.Common.TextBlock", - "options": { - "text": "The data connectors installed are:" - } - }, - { - "name": "DC1", - "type": "Microsoft.Common.Section", - "label": "(1)\t\tThreat Intelligence Platforms", - "elements": [ - { - "name": "DC1-text", - "type": "Microsoft.Common.TextBlock", - "options": { - "text": "Use this connector to send threat indicators to Microsoft Sentinel from your Threat Intelligence Platform (TIP), such as Threat Connect, Palo Alto Networks MindMeld, MISP, or other integrated applications." - } - } - ] - }, - { - "name": "DC2", - "type": "Microsoft.Common.Section", - "label": "(2)\t\tThreat Intelligence - TAXII", - "elements": [ - { - "name": "DC1-text", - "type": "Microsoft.Common.TextBlock", - "options": { - "text": "Use this connector to bring in threat intelligence to Microsoft Sentinel from a TAXII 2.0 or 2.1 server." - } - } - ] - }, - { - "name": "DC3", - "type": "Microsoft.Common.Section", - "label": "(3)\t\tThreat Intelligence Upload Indicators API", - "elements": [ - { - "name": "DC1-text", - "type": "Microsoft.Common.TextBlock", - "options": { - "text": "Microsoft Sentinel offer a data plane API to bring in threat intelligence from your Threat Intelligence Platform (TIP), such as Threat Connect, Palo Alto Networks MineMeld, MISP, or other integrated applications. Threat indicators can include IP addresses, domains, URLs, file hashes and email addresses." - } - } - ] - }, - { - "name": "DC4", - "type": "Microsoft.Common.Section", - "label": "(4)\t\tMicrosoft Defender Threat Intelligence", - "elements": [ - { - "name": "DC1-text", - "type": "Microsoft.Common.TextBlock", - "options": { - "text": "Microsoft Sentinel provides you the capability to import threat intelligence generated by Microsoft to enable monitoring, alerting and hunting. Use this data connector to import Indicators of Compromise (IOCs) from Microsoft Defender Threat Intelligence (MDTI) into Microsoft Sentinel. Threat indicators can include IP addresses, domains, URLs, and file hashes, etc." - } - } - ] - }, - { - "name": "dataconnectors3-text", - "type": "Microsoft.Common.TextBlock", - "options": { - "text": "After installing the solution, configure and enable these data connectors by following guidance in Manage solution view." - } - }, - { - "name": "dataconnectors-link2", - "type": "Microsoft.Common.TextBlock", - "options": { - "link": { - "label": "Learn more about connecting data sources", - "uri": "https://docs.microsoft.com/azure/sentinel/connect-data-sources" - } - } - } - ] - }, { "name": "workbooks", "label": "Workbooks", @@ -250,7 +156,7 @@ "name": "analytic3-text", "type": "Microsoft.Common.TextBlock", "options": { - "text": "This rule identifies Web Sessions for which the target URL hostname is a known IoC. This rule uses the [Advanced Security Information Model (ASIM)](https:/aka.ms/AboutASIM) and supports any web session source that complies with ASIM." + "text": "This rule identifies Web Sessions for which the target URL hostname is a known IoC.

This rule uses the [Advanced Security Information Model (ASIM)](https:/aka.ms/AboutASIM) and supports any web session source that complies with ASIM." } } ] @@ -544,7 +450,7 @@ "name": "analytic24-text", "type": "Microsoft.Common.TextBlock", "options": { - "text": "This rule identifies Web Sessions for which the source IP address is a known IoC. This rule uses the [Advanced Security Information Model (ASIM)](https://aka.ms/AboutASIM) and supports any web session source that complies with ASIM." + "text": "This rule identifies Web Sessions for which the source IP address is a known IoC.

This rule uses the [Advanced Security Information Model (ASIM)](https://aka.ms/AboutASIM) and supports any web session source that complies with ASIM." } } ] @@ -712,7 +618,7 @@ "name": "analytic36-text", "type": "Microsoft.Common.TextBlock", "options": { - "text": "This rule identifies DNS requests for which response IP address is a known IoC. This analytic rule uses [ASIM](https://aka.ms/AboutASIM) and supports any built-in or custom source that supports the ASIM DNS schema." + "text": "This rule identifies DNS requests for which response IP address is a known IoC.

\nThis analytic rule uses [ASIM](https://aka.ms/AboutASIM) and supports any built-in or custom source that supports the ASIM DNS schema." } } ] @@ -726,7 +632,7 @@ "name": "analytic37-text", "type": "Microsoft.Common.TextBlock", "options": { - "text": "This rule identifies a match Network Sessions for which the source or destination IP address is a known IoC. This analytic rule uses [ASIM](https://aka.ms/AboutASIM) and supports any built-in or custom source that supports the ASIM NetworkSession schema" + "text": "This rule identifies a match Network Sessions for which the source or destination IP address is a known IoC.

\nThis analytic rule uses [ASIM](https://aka.ms/AboutASIM) and supports any built-in or custom source that supports the ASIM NetworkSession schema" } } ] @@ -848,4 +754,4 @@ "workspace": "[basics('workspace')]" } } -} +} \ No newline at end of file diff --git a/Solutions/Threat Intelligence/Package/mainTemplate.json b/Solutions/Threat Intelligence/Package/mainTemplate.json index 3421e204aab..a18a6896e76 100644 --- a/Solutions/Threat Intelligence/Package/mainTemplate.json +++ b/Solutions/Threat Intelligence/Package/mainTemplate.json @@ -41,45 +41,9 @@ "email": "support@microsoft.com", "_email": "[variables('email')]", "_solutionName": "Threat Intelligence", - "_solutionVersion": "3.0.1", + "_solutionVersion": "3.0.2", "solutionId": "azuresentinel.azure-sentinel-solution-threatintelligence-taxii", "_solutionId": "[variables('solutionId')]", - "uiConfigId1": "ThreatIntelligenceTaxii", - "_uiConfigId1": "[variables('uiConfigId1')]", - "dataConnectorContentId1": "ThreatIntelligenceTaxii", - "_dataConnectorContentId1": "[variables('dataConnectorContentId1')]", - "dataConnectorId1": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId1'))]", - "_dataConnectorId1": "[variables('dataConnectorId1')]", - "dataConnectorTemplateSpecName1": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-dc-',uniquestring(variables('_dataConnectorContentId1'))))]", - "dataConnectorVersion1": "1.0.0", - "_dataConnectorcontentProductId1": "[concat(take(variables('_solutionId'),50),'-','dc','-', uniqueString(concat(variables('_solutionId'),'-','DataConnector','-',variables('_dataConnectorContentId1'),'-', variables('dataConnectorVersion1'))))]", - "uiConfigId2": "ThreatIntelligence", - "_uiConfigId2": "[variables('uiConfigId2')]", - "dataConnectorContentId2": "ThreatIntelligence", - "_dataConnectorContentId2": "[variables('dataConnectorContentId2')]", - "dataConnectorId2": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId2'))]", - "_dataConnectorId2": "[variables('dataConnectorId2')]", - "dataConnectorTemplateSpecName2": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-dc-',uniquestring(variables('_dataConnectorContentId2'))))]", - "dataConnectorVersion2": "1.0.0", - "_dataConnectorcontentProductId2": "[concat(take(variables('_solutionId'),50),'-','dc','-', uniqueString(concat(variables('_solutionId'),'-','DataConnector','-',variables('_dataConnectorContentId2'),'-', variables('dataConnectorVersion2'))))]", - "uiConfigId3": "ThreatIntelligenceUploadIndicatorsAPI", - "_uiConfigId3": "[variables('uiConfigId3')]", - "dataConnectorContentId3": "ThreatIntelligenceUploadIndicatorsAPI", - "_dataConnectorContentId3": "[variables('dataConnectorContentId3')]", - "dataConnectorId3": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId3'))]", - "_dataConnectorId3": "[variables('dataConnectorId3')]", - "dataConnectorTemplateSpecName3": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-dc-',uniquestring(variables('_dataConnectorContentId3'))))]", - "dataConnectorVersion3": "1.0.0", - "_dataConnectorcontentProductId3": "[concat(take(variables('_solutionId'),50),'-','dc','-', uniqueString(concat(variables('_solutionId'),'-','DataConnector','-',variables('_dataConnectorContentId3'),'-', variables('dataConnectorVersion3'))))]", - "uiConfigId4": "MicrosoftDefenderThreatIntelligence", - "_uiConfigId4": "[variables('uiConfigId4')]", - "dataConnectorContentId4": "MicrosoftDefenderThreatIntelligence", - "_dataConnectorContentId4": "[variables('dataConnectorContentId4')]", - "dataConnectorId4": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId4'))]", - "_dataConnectorId4": "[variables('dataConnectorId4')]", - "dataConnectorTemplateSpecName4": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-dc-',uniquestring(variables('_dataConnectorContentId4'))))]", - "dataConnectorVersion4": "1.0.0", - "_dataConnectorcontentProductId4": "[concat(take(variables('_solutionId'),50),'-','dc','-', uniqueString(concat(variables('_solutionId'),'-','DataConnector','-',variables('_dataConnectorContentId4'),'-', variables('dataConnectorVersion4'))))]", "workbookVersion1": "5.0.0", "workbookContentId1": "ThreatIntelligenceWorkbook", "workbookId1": "[resourceId('Microsoft.Insights/workbooks', variables('workbookContentId1'))]", @@ -117,205 +81,205 @@ "huntingQueryId5": "[resourceId('Microsoft.OperationalInsights/savedSearches', variables('_huntingQuerycontentId5'))]", "huntingQueryTemplateSpecName5": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-hq-',uniquestring(variables('_huntingQuerycontentId5'))))]", "_huntingQuerycontentProductId5": "[concat(take(variables('_solutionId'),50),'-','hq','-', uniqueString(concat(variables('_solutionId'),'-','HuntingQuery','-',variables('_huntingQuerycontentId5'),'-', variables('huntingQueryVersion5'))))]", - "analyticRuleVersion1": "1.4.0", + "analyticRuleVersion1": "1.4.1", "analyticRulecontentId1": "dd0a6029-ecef-4507-89c4-fc355ac52111", "_analyticRulecontentId1": "[variables('analyticRulecontentId1')]", "analyticRuleId1": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId1'))]", "analyticRuleTemplateSpecName1": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId1'))))]", "_analyticRulecontentProductId1": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId1'),'-', variables('analyticRuleVersion1'))))]", - "analyticRuleVersion2": "1.4.0", + "analyticRuleVersion2": "1.4.1", "analyticRulecontentId2": "85aca4d1-5d15-4001-abd9-acb86ca1786a", "_analyticRulecontentId2": "[variables('analyticRulecontentId2')]", "analyticRuleId2": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId2'))]", "analyticRuleTemplateSpecName2": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId2'))))]", "_analyticRulecontentProductId2": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId2'),'-', variables('analyticRuleVersion2'))))]", - "analyticRuleVersion3": "1.0.4", + "analyticRuleVersion3": "1.0.5", "analyticRulecontentId3": "b1832f60-6c3d-4722-a0a5-3d564ee61a63", "_analyticRulecontentId3": "[variables('analyticRulecontentId3')]", "analyticRuleId3": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId3'))]", "analyticRuleTemplateSpecName3": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId3'))))]", "_analyticRulecontentProductId3": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId3'),'-', variables('analyticRuleVersion3'))))]", - "analyticRuleVersion4": "1.4.0", + "analyticRuleVersion4": "1.4.1", "analyticRulecontentId4": "ec21493c-2684-4acd-9bc2-696dbad72426", "_analyticRulecontentId4": "[variables('analyticRulecontentId4')]", "analyticRuleId4": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId4'))]", "analyticRuleTemplateSpecName4": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId4'))))]", "_analyticRulecontentProductId4": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId4'),'-', variables('analyticRuleVersion4'))))]", - "analyticRuleVersion5": "1.4.1", + "analyticRuleVersion5": "1.4.2", "analyticRulecontentId5": "87890d78-3e05-43ec-9ab9-ba32f4e01250", "_analyticRulecontentId5": "[variables('analyticRulecontentId5')]", "analyticRuleId5": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId5'))]", "analyticRuleTemplateSpecName5": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId5'))))]", "_analyticRulecontentProductId5": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId5'),'-', variables('analyticRuleVersion5'))))]", - "analyticRuleVersion6": "1.4.0", + "analyticRuleVersion6": "1.4.1", "analyticRulecontentId6": "532f62c1-fba6-4baa-bbb6-4a32a4ef32fa", "_analyticRulecontentId6": "[variables('analyticRulecontentId6')]", "analyticRuleId6": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId6'))]", "analyticRuleTemplateSpecName6": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId6'))))]", "_analyticRulecontentProductId6": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId6'),'-', variables('analyticRuleVersion6'))))]", - "analyticRuleVersion7": "1.2.4", + "analyticRuleVersion7": "1.2.5", "analyticRulecontentId7": "cca3b4d9-ac39-4109-8b93-65bb284003e6", "_analyticRulecontentId7": "[variables('analyticRulecontentId7')]", "analyticRuleId7": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId7'))]", "analyticRuleTemplateSpecName7": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId7'))))]", "_analyticRulecontentProductId7": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId7'),'-', variables('analyticRuleVersion7'))))]", - "analyticRuleVersion8": "1.2.4", + "analyticRuleVersion8": "1.2.5", "analyticRulecontentId8": "4a3f5ed7-8da5-4ce2-af6f-c9ada45060f2", "_analyticRulecontentId8": "[variables('analyticRulecontentId8')]", "analyticRuleId8": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId8'))]", "analyticRuleTemplateSpecName8": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId8'))))]", "_analyticRulecontentProductId8": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId8'),'-', variables('analyticRuleVersion8'))))]", - "analyticRuleVersion9": "1.2.4", + "analyticRuleVersion9": "1.2.5", "analyticRulecontentId9": "ffcd575b-3d54-482a-a6d8-d0de13b6ac63", "_analyticRulecontentId9": "[variables('analyticRulecontentId9')]", "analyticRuleId9": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId9'))]", "analyticRuleTemplateSpecName9": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId9'))))]", "_analyticRulecontentProductId9": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId9'),'-', variables('analyticRuleVersion9'))))]", - "analyticRuleVersion10": "1.2.5", + "analyticRuleVersion10": "1.2.6", "analyticRulecontentId10": "a2e36ce0-da4d-4b6e-88c6-4e40161c5bfc", "_analyticRulecontentId10": "[variables('analyticRulecontentId10')]", "analyticRuleId10": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId10'))]", "analyticRuleTemplateSpecName10": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId10'))))]", "_analyticRulecontentProductId10": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId10'),'-', variables('analyticRuleVersion10'))))]", - "analyticRuleVersion11": "1.3.4", + "analyticRuleVersion11": "1.3.5", "analyticRulecontentId11": "2fc5d810-c9cc-491a-b564-841427ae0e50", "_analyticRulecontentId11": "[variables('analyticRulecontentId11')]", "analyticRuleId11": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId11'))]", "analyticRuleTemplateSpecName11": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId11'))))]", "_analyticRulecontentProductId11": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId11'),'-', variables('analyticRuleVersion11'))))]", - "analyticRuleVersion12": "1.2.4", + "analyticRuleVersion12": "1.2.5", "analyticRulecontentId12": "30fa312c-31eb-43d8-b0cc-bcbdfb360822", "_analyticRulecontentId12": "[variables('analyticRulecontentId12')]", "analyticRuleId12": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId12'))]", "analyticRuleTemplateSpecName12": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId12'))))]", "_analyticRulecontentProductId12": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId12'),'-', variables('analyticRuleVersion12'))))]", - "analyticRuleVersion13": "1.3.3", + "analyticRuleVersion13": "1.3.4", "analyticRulecontentId13": "5d33fc63-b83b-4913-b95e-94d13f0d379f", "_analyticRulecontentId13": "[variables('analyticRulecontentId13')]", "analyticRuleId13": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId13'))]", "analyticRuleTemplateSpecName13": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId13'))))]", "_analyticRulecontentProductId13": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId13'),'-', variables('analyticRuleVersion13'))))]", - "analyticRuleVersion14": "1.4.3", + "analyticRuleVersion14": "1.4.4", "analyticRulecontentId14": "a7427ed7-04b4-4e3b-b323-08b981b9b4bf", "_analyticRulecontentId14": "[variables('analyticRulecontentId14')]", "analyticRuleId14": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId14'))]", "analyticRuleTemplateSpecName14": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId14'))))]", "_analyticRulecontentProductId14": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId14'),'-', variables('analyticRuleVersion14'))))]", - "analyticRuleVersion15": "1.4.0", + "analyticRuleVersion15": "1.4.1", "analyticRulecontentId15": "f9949656-473f-4503-bf43-a9d9890f7d08", "_analyticRulecontentId15": "[variables('analyticRulecontentId15')]", "analyticRuleId15": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId15'))]", "analyticRuleTemplateSpecName15": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId15'))))]", "_analyticRulecontentProductId15": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId15'),'-', variables('analyticRuleVersion15'))))]", - "analyticRuleVersion16": "1.4.0", + "analyticRuleVersion16": "1.4.1", "analyticRulecontentId16": "f110287e-1358-490d-8147-ed804b328514", "_analyticRulecontentId16": "[variables('analyticRulecontentId16')]", "analyticRuleId16": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId16'))]", "analyticRuleTemplateSpecName16": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId16'))))]", "_analyticRulecontentProductId16": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId16'),'-', variables('analyticRuleVersion16'))))]", - "analyticRuleVersion17": "1.3.2", + "analyticRuleVersion17": "1.4.1", "analyticRulecontentId17": "2441bce9-02e4-407b-8cc7-7d597f38b8b0", "_analyticRulecontentId17": "[variables('analyticRulecontentId17')]", "analyticRuleId17": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId17'))]", "analyticRuleTemplateSpecName17": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId17'))))]", "_analyticRulecontentProductId17": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId17'),'-', variables('analyticRuleVersion17'))))]", - "analyticRuleVersion18": "1.3.0", + "analyticRuleVersion18": "1.3.1", "analyticRulecontentId18": "0b904747-1336-4363-8d84-df2710bfe5e7", "_analyticRulecontentId18": "[variables('analyticRulecontentId18')]", "analyticRuleId18": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId18'))]", "analyticRuleTemplateSpecName18": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId18'))))]", "_analyticRulecontentProductId18": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId18'),'-', variables('analyticRuleVersion18'))))]", - "analyticRuleVersion19": "1.3.1", + "analyticRuleVersion19": "1.3.3", "analyticRulecontentId19": "57c7e832-64eb-411f-8928-4133f01f4a25", "_analyticRulecontentId19": "[variables('analyticRulecontentId19')]", "analyticRuleId19": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId19'))]", "analyticRuleTemplateSpecName19": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId19'))))]", "_analyticRulecontentProductId19": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId19'),'-', variables('analyticRuleVersion19'))))]", - "analyticRuleVersion20": "1.4.0", + "analyticRuleVersion20": "1.4.1", "analyticRulecontentId20": "a4025a76-6490-4e6b-bb69-d02be4b03f07", "_analyticRulecontentId20": "[variables('analyticRulecontentId20')]", "analyticRuleId20": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId20'))]", "analyticRuleTemplateSpecName20": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId20'))))]", "_analyticRulecontentProductId20": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId20'),'-', variables('analyticRuleVersion20'))))]", - "analyticRuleVersion21": "1.3.0", + "analyticRuleVersion21": "1.3.1", "analyticRulecontentId21": "d0aa8969-1bbe-4da3-9e76-09e5f67c9d85", "_analyticRulecontentId21": "[variables('analyticRulecontentId21')]", "analyticRuleId21": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId21'))]", "analyticRuleTemplateSpecName21": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId21'))))]", "_analyticRulecontentProductId21": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId21'),'-', variables('analyticRuleVersion21'))))]", - "analyticRuleVersion22": "1.2.0", + "analyticRuleVersion22": "1.2.1", "analyticRulecontentId22": "66c81ae2-1f89-4433-be00-2fbbd9ba5ebe", "_analyticRulecontentId22": "[variables('analyticRulecontentId22')]", "analyticRuleId22": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId22'))]", "analyticRuleTemplateSpecName22": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId22'))))]", "_analyticRulecontentProductId22": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId22'),'-', variables('analyticRuleVersion22'))))]", - "analyticRuleVersion23": "1.4.0", + "analyticRuleVersion23": "1.4.1", "analyticRulecontentId23": "69b7723c-2889-469f-8b55-a2d355ed9c87", "_analyticRulecontentId23": "[variables('analyticRulecontentId23')]", "analyticRuleId23": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId23'))]", "analyticRuleTemplateSpecName23": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId23'))))]", "_analyticRulecontentProductId23": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId23'),'-', variables('analyticRuleVersion23'))))]", - "analyticRuleVersion24": "1.2.3", + "analyticRuleVersion24": "1.2.4", "analyticRulecontentId24": "e2559891-383c-4caf-ae67-55a008b9f89e", "_analyticRulecontentId24": "[variables('analyticRulecontentId24')]", "analyticRuleId24": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId24'))]", "analyticRuleTemplateSpecName24": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId24'))))]", "_analyticRulecontentProductId24": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId24'),'-', variables('analyticRuleVersion24'))))]", - "analyticRuleVersion25": "1.4.0", + "analyticRuleVersion25": "1.4.1", "analyticRulecontentId25": "f15370f4-c6fa-42c5-9be4-1d308f40284e", "_analyticRulecontentId25": "[variables('analyticRulecontentId25')]", "analyticRuleId25": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId25'))]", "analyticRuleTemplateSpecName25": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId25'))))]", "_analyticRulecontentProductId25": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId25'),'-', variables('analyticRuleVersion25'))))]", - "analyticRuleVersion26": "1.2.5", + "analyticRuleVersion26": "1.2.6", "analyticRulecontentId26": "f2eb15bd-8a88-4b24-9281-e133edfba315", "_analyticRulecontentId26": "[variables('analyticRulecontentId26')]", "analyticRuleId26": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId26'))]", "analyticRuleTemplateSpecName26": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId26'))))]", "_analyticRulecontentProductId26": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId26'),'-', variables('analyticRuleVersion26'))))]", - "analyticRuleVersion27": "1.4.0", + "analyticRuleVersion27": "1.4.1", "analyticRulecontentId27": "9713e3c0-1410-468d-b79e-383448434b2d", "_analyticRulecontentId27": "[variables('analyticRulecontentId27')]", "analyticRuleId27": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId27'))]", "analyticRuleTemplateSpecName27": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId27'))))]", "_analyticRulecontentProductId27": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId27'),'-', variables('analyticRuleVersion27'))))]", - "analyticRuleVersion28": "1.4.0", + "analyticRuleVersion28": "1.4.1", "analyticRulecontentId28": "5e45930c-09b1-4430-b2d1-cc75ada0dc0f", "_analyticRulecontentId28": "[variables('analyticRulecontentId28')]", "analyticRuleId28": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId28'))]", "analyticRuleTemplateSpecName28": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId28'))))]", "_analyticRulecontentProductId28": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId28'),'-', variables('analyticRuleVersion28'))))]", - "analyticRuleVersion29": "1.2.4", + "analyticRuleVersion29": "1.2.5", "analyticRulecontentId29": "712fab52-2a7d-401e-a08c-ff939cc7c25e", "_analyticRulecontentId29": "[variables('analyticRulecontentId29')]", "analyticRuleId29": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId29'))]", "analyticRuleTemplateSpecName29": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId29'))))]", "_analyticRulecontentProductId29": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId29'),'-', variables('analyticRuleVersion29'))))]", - "analyticRuleVersion30": "1.2.5", + "analyticRuleVersion30": "1.2.6", "analyticRulecontentId30": "36a9c9e5-3dc1-4ed9-afaa-1d13617bfc2b", "_analyticRulecontentId30": "[variables('analyticRulecontentId30')]", "analyticRuleId30": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId30'))]", "analyticRuleTemplateSpecName30": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId30'))))]", "_analyticRulecontentProductId30": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId30'),'-', variables('analyticRuleVersion30'))))]", - "analyticRuleVersion31": "1.2.3", + "analyticRuleVersion31": "1.2.4", "analyticRulecontentId31": "106813db-679e-4382-a51b-1bfc463befc3", "_analyticRulecontentId31": "[variables('analyticRulecontentId31')]", "analyticRuleId31": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId31'))]", "analyticRuleTemplateSpecName31": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId31'))))]", "_analyticRulecontentProductId31": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId31'),'-', variables('analyticRuleVersion31'))))]", - "analyticRuleVersion32": "1.2.6", + "analyticRuleVersion32": "1.2.7", "analyticRulecontentId32": "f30a47c1-65fb-42b1-a7f4-00941c12550b", "_analyticRulecontentId32": "[variables('analyticRulecontentId32')]", "analyticRuleId32": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId32'))]", "analyticRuleTemplateSpecName32": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId32'))))]", "_analyticRulecontentProductId32": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId32'),'-', variables('analyticRuleVersion32'))))]", - "analyticRuleVersion33": "1.2.4", + "analyticRuleVersion33": "1.2.5", "analyticRulecontentId33": "b31037ea-6f68-4fbd-bab2-d0d0f44c2fcf", "_analyticRulecontentId33": "[variables('analyticRulecontentId33')]", "analyticRuleId33": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId33'))]", "analyticRuleTemplateSpecName33": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId33'))))]", "_analyticRulecontentProductId33": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId33'),'-', variables('analyticRuleVersion33'))))]", - "analyticRuleVersion34": "1.0.3", + "analyticRuleVersion34": "1.0.4", "analyticRulecontentId34": "d23ed927-5be3-4902-a9c1-85f841eb4fa1", "_analyticRulecontentId34": "[variables('analyticRulecontentId34')]", "analyticRuleId34": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId34'))]", @@ -327,13 +291,13 @@ "analyticRuleId35": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId35'))]", "analyticRuleTemplateSpecName35": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId35'))))]", "_analyticRulecontentProductId35": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId35'),'-', variables('analyticRuleVersion35'))))]", - "analyticRuleVersion36": "1.2.2", + "analyticRuleVersion36": "1.2.3", "analyticRulecontentId36": "67775878-7f8b-4380-ac54-115e1e828901", "_analyticRulecontentId36": "[variables('analyticRulecontentId36')]", "analyticRuleId36": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId36'))]", "analyticRuleTemplateSpecName36": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId36'))))]", "_analyticRulecontentProductId36": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId36'),'-', variables('analyticRuleVersion36'))))]", - "analyticRuleVersion37": "1.2.4", + "analyticRuleVersion37": "1.2.5", "analyticRulecontentId37": "e2399891-383c-4caf-ae67-68a008b9f89e", "_analyticRulecontentId37": "[variables('analyticRulecontentId37')]", "analyticRuleId37": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId37'))]", @@ -345,730 +309,9 @@ "analyticRuleId38": "[resourceId('Microsoft.SecurityInsights/AlertRuleTemplates', variables('analyticRulecontentId38'))]", "analyticRuleTemplateSpecName38": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat(parameters('workspace'),'-ar-',uniquestring(variables('_analyticRulecontentId38'))))]", "_analyticRulecontentProductId38": "[concat(take(variables('_solutionId'),50),'-','ar','-', uniqueString(concat(variables('_solutionId'),'-','AnalyticsRule','-',variables('_analyticRulecontentId38'),'-', variables('analyticRuleVersion38'))))]", - "_solutioncontentProductId": "[concat(take(variables('_solutionId'),50),'-','sl','-', uniqueString(concat(variables('_solutionId'),'-','Solution','-',variables('_solutionId'),'-', variables('_solutionVersion'))))]", - "management": "[concat('https://management','.azure','.com/')]" + "_solutioncontentProductId": "[concat(take(variables('_solutionId'),50),'-','sl','-', uniqueString(concat(variables('_solutionId'),'-','Solution','-',variables('_solutionId'),'-', variables('_solutionVersion'))))]" }, "resources": [ - { - "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", - "apiVersion": "2023-04-01-preview", - "name": "[variables('dataConnectorTemplateSpecName1')]", - "location": "[parameters('workspace-location')]", - "dependsOn": [ - "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" - ], - "properties": { - "description": "Threat Intelligence data connector with template version 3.0.1", - "mainTemplate": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('dataConnectorVersion1')]", - "parameters": {}, - "variables": {}, - "resources": [ - { - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId1'))]", - "apiVersion": "2021-03-01-preview", - "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", - "location": "[parameters('workspace-location')]", - "kind": "StaticUI", - "properties": { - "connectorUiConfig": { - "id": "[variables('_uiConfigId1')]", - "title": "Threat intelligence - TAXII", - "publisher": "Microsoft", - "descriptionMarkdown": "Microsoft Sentinel integrates with TAXII 2.0 and 2.1 data sources to enable monitoring, alerting, and hunting using your threat intelligence. Use this connector to send threat indicators from TAXII servers to Microsoft Sentinel. Threat indicators can include IP addresses, domains, URLs, and file hashes. For more information, see the [Microsoft Sentinel documentation >](https://go.microsoft.com/fwlink/p/?linkid=2224105&wt.mc_id=sentinel_dataconnectordocs_content_cnl_csasci).", - "graphQueries": [ - { - "metricName": "Total data received", - "legend": "ThreatIntelligenceIndicator", - "baseQuery": "ThreatIntelligenceIndicator | where SourceSystem !in (\"SecurityGraph\", \"Azure Sentinel\", \"Microsoft Sentinel\") " - } - ], - "connectivityCriterias": [ - { - "type": "SentinelKinds", - "value": [ - "ThreatIntelligenceTaxii" - ] - } - ], - "dataTypes": [ - { - "name": "ThreatIntelligenceIndicator", - "lastDataReceivedQuery": "ThreatIntelligenceIndicator | where SourceSystem !in (\"SecurityGraph\", \"Azure Sentinel\", \"Microsoft Sentinel\") \n | summarize Time = max(TimeGenerated)\n | where isnotempty(Time)" - } - ] - } - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2023-04-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId1'),'/'))))]", - "properties": { - "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId1'))]", - "contentId": "[variables('_dataConnectorContentId1')]", - "kind": "DataConnector", - "version": "[variables('dataConnectorVersion1')]", - "source": { - "kind": "Solution", - "name": "Threat Intelligence", - "sourceId": "[variables('_solutionId')]" - }, - "author": { - "name": "Microsoft", - "email": "[variables('_email')]" - }, - "support": { - "tier": "Microsoft", - "name": "Microsoft Corporation", - "email": "support@microsoft.com", - "link": "https://support.microsoft.com/" - } - } - } - ] - }, - "packageKind": "Solution", - "packageVersion": "[variables('_solutionVersion')]", - "packageName": "[variables('_solutionName')]", - "packageId": "[variables('_solutionId')]", - "contentSchemaVersion": "3.0.0", - "contentId": "[variables('_dataConnectorContentId1')]", - "contentKind": "DataConnector", - "displayName": "Threat intelligence - TAXII", - "contentProductId": "[variables('_dataConnectorcontentProductId1')]", - "id": "[variables('_dataConnectorcontentProductId1')]", - "version": "[variables('dataConnectorVersion1')]" - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2023-04-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId1'),'/'))))]", - "dependsOn": [ - "[variables('_dataConnectorId1')]" - ], - "location": "[parameters('workspace-location')]", - "properties": { - "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId1'))]", - "contentId": "[variables('_dataConnectorContentId1')]", - "kind": "DataConnector", - "version": "[variables('dataConnectorVersion1')]", - "source": { - "kind": "Solution", - "name": "Threat Intelligence", - "sourceId": "[variables('_solutionId')]" - }, - "author": { - "name": "Microsoft", - "email": "[variables('_email')]" - }, - "support": { - "tier": "Microsoft", - "name": "Microsoft Corporation", - "email": "support@microsoft.com", - "link": "https://support.microsoft.com/" - } - } - }, - { - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId1'))]", - "apiVersion": "2021-03-01-preview", - "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", - "location": "[parameters('workspace-location')]", - "kind": "StaticUI", - "properties": { - "connectorUiConfig": { - "title": "Threat intelligence - TAXII", - "publisher": "Microsoft", - "descriptionMarkdown": "Microsoft Sentinel integrates with TAXII 2.0 and 2.1 data sources to enable monitoring, alerting, and hunting using your threat intelligence. Use this connector to send threat indicators from TAXII servers to Microsoft Sentinel. Threat indicators can include IP addresses, domains, URLs, and file hashes. For more information, see the [Microsoft Sentinel documentation >](https://go.microsoft.com/fwlink/p/?linkid=2224105&wt.mc_id=sentinel_dataconnectordocs_content_cnl_csasci).", - "graphQueries": [ - { - "metricName": "Total data received", - "legend": "ThreatIntelligenceIndicator", - "baseQuery": "ThreatIntelligenceIndicator | where SourceSystem !in (\"SecurityGraph\", \"Azure Sentinel\", \"Microsoft Sentinel\") " - } - ], - "dataTypes": [ - { - "name": "ThreatIntelligenceIndicator", - "lastDataReceivedQuery": "ThreatIntelligenceIndicator | where SourceSystem !in (\"SecurityGraph\", \"Azure Sentinel\", \"Microsoft Sentinel\") \n | summarize Time = max(TimeGenerated)\n | where isnotempty(Time)" - } - ], - "connectivityCriterias": [ - { - "type": "SentinelKinds", - "value": [ - "ThreatIntelligenceTaxii" - ] - } - ], - "id": "[variables('_uiConfigId1')]" - } - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", - "apiVersion": "2023-04-01-preview", - "name": "[variables('dataConnectorTemplateSpecName2')]", - "location": "[parameters('workspace-location')]", - "dependsOn": [ - "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" - ], - "properties": { - "description": "Threat Intelligence data connector with template version 3.0.1", - "mainTemplate": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('dataConnectorVersion2')]", - "parameters": {}, - "variables": {}, - "resources": [ - { - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId2'))]", - "apiVersion": "2021-03-01-preview", - "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", - "location": "[parameters('workspace-location')]", - "kind": "StaticUI", - "properties": { - "connectorUiConfig": { - "id": "[variables('_uiConfigId2')]", - "title": "Threat Intelligence Platforms", - "publisher": "Microsoft", - "descriptionMarkdown": "Microsoft Sentinel integrates with Microsoft Graph Security API data sources to enable monitoring, alerting, and hunting using your threat intelligence. Use this connector to send threat indicators to Microsoft Sentinel from your Threat Intelligence Platform (TIP), such as Threat Connect, Palo Alto Networks MindMeld, MISP, or other integrated applications. Threat indicators can include IP addresses, domains, URLs, and file hashes. For more information, see the [Microsoft Sentinel documentation >](https://go.microsoft.com/fwlink/p/?linkid=2223729&wt.mc_id=sentinel_dataconnectordocs_content_cnl_csasci).", - "graphQueries": [ - { - "metricName": "Total data received", - "legend": "ThreatIntelligenceIndicator", - "baseQuery": "ThreatIntelligenceIndicator | where SourceSystem == \"SecurityGraph\"" - } - ], - "connectivityCriterias": [ - { - "type": "SentinelKinds", - "value": [ - "ThreatIntelligence" - ] - } - ], - "dataTypes": [ - { - "name": "ThreatIntelligenceIndicator", - "lastDataReceivedQuery": "ThreatIntelligenceIndicator | where SourceSystem == \"SecurityGraph\"\n | summarize Time = max(TimeGenerated)\n | where isnotempty(Time)" - } - ] - } - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2023-04-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId2'),'/'))))]", - "properties": { - "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId2'))]", - "contentId": "[variables('_dataConnectorContentId2')]", - "kind": "DataConnector", - "version": "[variables('dataConnectorVersion2')]", - "source": { - "kind": "Solution", - "name": "Threat Intelligence", - "sourceId": "[variables('_solutionId')]" - }, - "author": { - "name": "Microsoft", - "email": "[variables('_email')]" - }, - "support": { - "tier": "Microsoft", - "name": "Microsoft Corporation", - "email": "support@microsoft.com", - "link": "https://support.microsoft.com/" - } - } - } - ] - }, - "packageKind": "Solution", - "packageVersion": "[variables('_solutionVersion')]", - "packageName": "[variables('_solutionName')]", - "packageId": "[variables('_solutionId')]", - "contentSchemaVersion": "3.0.0", - "contentId": "[variables('_dataConnectorContentId2')]", - "contentKind": "DataConnector", - "displayName": "Threat Intelligence Platforms", - "contentProductId": "[variables('_dataConnectorcontentProductId2')]", - "id": "[variables('_dataConnectorcontentProductId2')]", - "version": "[variables('dataConnectorVersion2')]" - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2023-04-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId2'),'/'))))]", - "dependsOn": [ - "[variables('_dataConnectorId2')]" - ], - "location": "[parameters('workspace-location')]", - "properties": { - "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId2'))]", - "contentId": "[variables('_dataConnectorContentId2')]", - "kind": "DataConnector", - "version": "[variables('dataConnectorVersion2')]", - "source": { - "kind": "Solution", - "name": "Threat Intelligence", - "sourceId": "[variables('_solutionId')]" - }, - "author": { - "name": "Microsoft", - "email": "[variables('_email')]" - }, - "support": { - "tier": "Microsoft", - "name": "Microsoft Corporation", - "email": "support@microsoft.com", - "link": "https://support.microsoft.com/" - } - } - }, - { - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId2'))]", - "apiVersion": "2021-03-01-preview", - "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", - "location": "[parameters('workspace-location')]", - "kind": "StaticUI", - "properties": { - "connectorUiConfig": { - "title": "Threat Intelligence Platforms", - "publisher": "Microsoft", - "descriptionMarkdown": "Microsoft Sentinel integrates with Microsoft Graph Security API data sources to enable monitoring, alerting, and hunting using your threat intelligence. Use this connector to send threat indicators to Microsoft Sentinel from your Threat Intelligence Platform (TIP), such as Threat Connect, Palo Alto Networks MindMeld, MISP, or other integrated applications. Threat indicators can include IP addresses, domains, URLs, and file hashes. For more information, see the [Microsoft Sentinel documentation >](https://go.microsoft.com/fwlink/p/?linkid=2223729&wt.mc_id=sentinel_dataconnectordocs_content_cnl_csasci).", - "graphQueries": [ - { - "metricName": "Total data received", - "legend": "ThreatIntelligenceIndicator", - "baseQuery": "ThreatIntelligenceIndicator | where SourceSystem == \"SecurityGraph\"" - } - ], - "dataTypes": [ - { - "name": "ThreatIntelligenceIndicator", - "lastDataReceivedQuery": "ThreatIntelligenceIndicator | where SourceSystem == \"SecurityGraph\"\n | summarize Time = max(TimeGenerated)\n | where isnotempty(Time)" - } - ], - "connectivityCriterias": [ - { - "type": "SentinelKinds", - "value": [ - "ThreatIntelligence" - ] - } - ], - "id": "[variables('_uiConfigId2')]" - } - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", - "apiVersion": "2023-04-01-preview", - "name": "[variables('dataConnectorTemplateSpecName3')]", - "location": "[parameters('workspace-location')]", - "dependsOn": [ - "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" - ], - "properties": { - "description": "Threat Intelligence data connector with template version 3.0.1", - "mainTemplate": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('dataConnectorVersion3')]", - "parameters": {}, - "variables": {}, - "resources": [ - { - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId3'))]", - "apiVersion": "2021-03-01-preview", - "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", - "location": "[parameters('workspace-location')]", - "kind": "GenericUI", - "properties": { - "connectorUiConfig": { - "id": "[variables('_uiConfigId3')]", - "title": "Threat Intelligence Upload Indicators API (Preview)", - "publisher": "Microsoft", - "descriptionMarkdown": "Microsoft Sentinel offer a data plane API to bring in threat intelligence from your Threat Intelligence Platform (TIP), such as Threat Connect, Palo Alto Networks MineMeld, MISP, or other integrated applications. Threat indicators can include IP addresses, domains, URLs, file hashes and email addresses.", - "graphQueries": [ - { - "metricName": "Total indicators received", - "legend": "Connection Events", - "baseQuery": "ThreatIntelligenceIndicator | where SourceSystem != 'Microsoft Sentinel'" - } - ], - "sampleQueries": [ - { - "description": "All Threat Intelligence APIs Indicators", - "query": "ThreatIntelligenceIndicator | where SourceSystem !in ('SecurityGraph', 'Azure Sentinel', 'Microsoft Sentinel')| sort by TimeGenerated desc" - } - ], - "dataTypes": [ - { - "name": "ThreatIntelligenceIndicator", - "lastDataReceivedQuery": "ThreatIntelligenceIndicator| where isnotempty(TimeGenerated) and SourceSystem !in ('SecurityGraph', 'Azure Sentinel', 'Microsoft Sentinel')| summarize Time = max(TimeGenerated)" - } - ], - "connectivityCriterias": [ - { - "type": "IsConnectedQuery", - "value": [ - "ThreatIntelligenceIndicator| where SourceSystem !in ('SecurityGraph', 'Azure Sentinel', 'Microsoft Sentinel') | summarize LastLogReceived = max(TimeGenerated) | project IsConnected = LastLogReceived > ago(30d)" - ] - } - ], - "availability": { - "status": 1, - "isPreview": false - }, - "permissions": { - "resourceProvider": [ - { - "provider": "Microsoft.SecurityInsights/threatintelligence/write", - "permissionsDisplayText": "write permissions are required.", - "providerDisplayName": "Workspace", - "scope": "Workspace", - "requiredPermissions": { - "write": true, - "read": true, - "delete": true - } - } - ] - }, - "instructionSteps": [ - { - "description": "\n>Using an integrated Threat Intelligence Platform (TIP), such as Threat Connect, Palo Alto Networks MineMeld, MISP, and others. \n\n>Calling the Microsoft Sentinel data plane API directly from another application. ", - "title": "You can connect your threat intelligence data sources to Microsoft Sentinel by either: " - }, - { - "title": "Follow These Steps to Connect to your Threat Intelligence: " - }, - { - "description": "[concat('To send request to the APIs, you need to acquire Azure Active Directory access token. You can follow instruction in this page: https://docs.microsoft.com/azure/databricks/dev-tools/api/latest/aad/app-aad-token#get-an-azure-ad-access-token \n - Notice: Please request AAD access token with scope value: ', variables('management'), '.default')]", - "title": "1. Get AAD Access Token" - }, - { - "description": "You can send indicators by calling our Upload Indicators API. For more information about the API, click [here]( https://learn.microsoft.com/azure/sentinel/upload-indicators-api). \n\n>HTTP method: POST \n\n>Endpoint: https://sentinelus.azure-api.net/workspaces/[WorkspaceID]/threatintelligenceindicators:upload?api-version=2022-07-01 \n\n>WorkspaceID: the workspace that the indicators are uploaded to. \n\n\n>Header Value 1: \"Authorization\" = \"Bearer [AAD Access Token from step 1]\" \n\n\n> Header Value 2: \"Content-Type\" = \"application/json\" \n \n>Body: The body is a JSON object containing an array of indicators in STIX format.", - "title": "2. Send indicators to Sentinel" - } - ] - } - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2023-04-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId3'),'/'))))]", - "properties": { - "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId3'))]", - "contentId": "[variables('_dataConnectorContentId3')]", - "kind": "DataConnector", - "version": "[variables('dataConnectorVersion3')]", - "source": { - "kind": "Solution", - "name": "Threat Intelligence", - "sourceId": "[variables('_solutionId')]" - }, - "author": { - "name": "Microsoft", - "email": "[variables('_email')]" - }, - "support": { - "tier": "Microsoft", - "name": "Microsoft Corporation", - "email": "support@microsoft.com", - "link": "https://support.microsoft.com/" - } - } - } - ] - }, - "packageKind": "Solution", - "packageVersion": "[variables('_solutionVersion')]", - "packageName": "[variables('_solutionName')]", - "packageId": "[variables('_solutionId')]", - "contentSchemaVersion": "3.0.0", - "contentId": "[variables('_dataConnectorContentId3')]", - "contentKind": "DataConnector", - "displayName": "Threat Intelligence Upload Indicators API (Preview)", - "contentProductId": "[variables('_dataConnectorcontentProductId3')]", - "id": "[variables('_dataConnectorcontentProductId3')]", - "version": "[variables('dataConnectorVersion3')]" - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2023-04-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId3'),'/'))))]", - "dependsOn": [ - "[variables('_dataConnectorId3')]" - ], - "location": "[parameters('workspace-location')]", - "properties": { - "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId3'))]", - "contentId": "[variables('_dataConnectorContentId3')]", - "kind": "DataConnector", - "version": "[variables('dataConnectorVersion3')]", - "source": { - "kind": "Solution", - "name": "Threat Intelligence", - "sourceId": "[variables('_solutionId')]" - }, - "author": { - "name": "Microsoft", - "email": "[variables('_email')]" - }, - "support": { - "tier": "Microsoft", - "name": "Microsoft Corporation", - "email": "support@microsoft.com", - "link": "https://support.microsoft.com/" - } - } - }, - { - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId3'))]", - "apiVersion": "2021-03-01-preview", - "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", - "location": "[parameters('workspace-location')]", - "kind": "GenericUI", - "properties": { - "connectorUiConfig": { - "title": "Threat Intelligence Upload Indicators API (Preview)", - "publisher": "Microsoft", - "descriptionMarkdown": "Microsoft Sentinel offer a data plane API to bring in threat intelligence from your Threat Intelligence Platform (TIP), such as Threat Connect, Palo Alto Networks MineMeld, MISP, or other integrated applications. Threat indicators can include IP addresses, domains, URLs, file hashes and email addresses.", - "graphQueries": [ - { - "metricName": "Total indicators received", - "legend": "Connection Events", - "baseQuery": "ThreatIntelligenceIndicator | where SourceSystem != 'Microsoft Sentinel'" - } - ], - "dataTypes": [ - { - "name": "ThreatIntelligenceIndicator", - "lastDataReceivedQuery": "ThreatIntelligenceIndicator| where isnotempty(TimeGenerated) and SourceSystem !in ('SecurityGraph', 'Azure Sentinel', 'Microsoft Sentinel')| summarize Time = max(TimeGenerated)" - } - ], - "connectivityCriterias": [ - { - "type": "IsConnectedQuery", - "value": [ - "ThreatIntelligenceIndicator| where SourceSystem !in ('SecurityGraph', 'Azure Sentinel', 'Microsoft Sentinel') | summarize LastLogReceived = max(TimeGenerated) | project IsConnected = LastLogReceived > ago(30d)" - ] - } - ], - "sampleQueries": [ - { - "description": "All Threat Intelligence APIs Indicators", - "query": "ThreatIntelligenceIndicator | where SourceSystem !in ('SecurityGraph', 'Azure Sentinel', 'Microsoft Sentinel')| sort by TimeGenerated desc" - } - ], - "availability": { - "status": 1, - "isPreview": false - }, - "permissions": { - "resourceProvider": [ - { - "provider": "Microsoft.SecurityInsights/threatintelligence/write", - "permissionsDisplayText": "write permissions are required.", - "providerDisplayName": "Workspace", - "scope": "Workspace", - "requiredPermissions": { - "write": true, - "read": true, - "delete": true - } - } - ] - }, - "instructionSteps": [ - { - "description": "\n>Using an integrated Threat Intelligence Platform (TIP), such as Threat Connect, Palo Alto Networks MineMeld, MISP, and others. \n\n>Calling the Microsoft Sentinel data plane API directly from another application. ", - "title": "You can connect your threat intelligence data sources to Microsoft Sentinel by either: " - }, - { - "title": "Follow These Steps to Connect to your Threat Intelligence: " - }, - { - "description": "[concat('To send request to the APIs, you need to acquire Azure Active Directory access token. You can follow instruction in this page: https://docs.microsoft.com/azure/databricks/dev-tools/api/latest/aad/app-aad-token#get-an-azure-ad-access-token \n - Notice: Please request AAD access token with scope value: ', variables('management'), '.default')]", - "title": "1. Get AAD Access Token" - }, - { - "description": "You can send indicators by calling our Upload Indicators API. For more information about the API, click [here]( https://learn.microsoft.com/azure/sentinel/upload-indicators-api). \n\n>HTTP method: POST \n\n>Endpoint: https://sentinelus.azure-api.net/workspaces/[WorkspaceID]/threatintelligenceindicators:upload?api-version=2022-07-01 \n\n>WorkspaceID: the workspace that the indicators are uploaded to. \n\n\n>Header Value 1: \"Authorization\" = \"Bearer [AAD Access Token from step 1]\" \n\n\n> Header Value 2: \"Content-Type\" = \"application/json\" \n \n>Body: The body is a JSON object containing an array of indicators in STIX format.", - "title": "2. Send indicators to Sentinel" - } - ], - "id": "[variables('_uiConfigId3')]" - } - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", - "apiVersion": "2023-04-01-preview", - "name": "[variables('dataConnectorTemplateSpecName4')]", - "location": "[parameters('workspace-location')]", - "dependsOn": [ - "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" - ], - "properties": { - "description": "Threat Intelligence data connector with template version 3.0.1", - "mainTemplate": { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "[variables('dataConnectorVersion4')]", - "parameters": {}, - "variables": {}, - "resources": [ - { - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId4'))]", - "apiVersion": "2021-03-01-preview", - "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", - "location": "[parameters('workspace-location')]", - "kind": "StaticUI", - "properties": { - "connectorUiConfig": { - "id": "[variables('_uiConfigId4')]", - "title": "Microsoft Defender Threat Intelligence (Preview)", - "publisher": "Microsoft", - "descriptionMarkdown": "Microsoft Sentinel provides you the capability to import threat intelligence generated by Microsoft to enable monitoring, alerting and hunting. Use this data connector to import Indicators of Compromise (IOCs) from Microsoft Defender Threat Intelligence (MDTI) into Microsoft Sentinel. Threat indicators can include IP addresses, domains, URLs, and file hashes, etc.", - "graphQueries": [ - { - "metricName": "Total data received", - "legend": "ThreatIntelligenceIndicator", - "baseQuery": "ThreatIntelligenceIndicator\n | where SourceSystem in (\"Microsoft Defender Threat Intelligence\", \"Microsoft Emerging Threat Feed\")" - } - ], - "connectivityCriterias": [ - { - "type": "SentinelKinds", - "value": [ - "MicrosoftThreatIntelligence" - ] - } - ], - "dataTypes": [ - { - "name": "ThreatIntelligenceIndicator", - "lastDataReceivedQuery": "ThreatIntelligenceIndicator \n | where SourceSystem in (\"Microsoft Defender Threat Intelligence\", \"Microsoft Emerging Threat Feed\")\n | summarize Time = max(TimeGenerated)\n | where isnotempty(Time)" - } - ] - } - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2023-04-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId4'),'/'))))]", - "properties": { - "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId4'))]", - "contentId": "[variables('_dataConnectorContentId4')]", - "kind": "DataConnector", - "version": "[variables('dataConnectorVersion4')]", - "source": { - "kind": "Solution", - "name": "Threat Intelligence", - "sourceId": "[variables('_solutionId')]" - }, - "author": { - "name": "Microsoft", - "email": "[variables('_email')]" - }, - "support": { - "tier": "Microsoft", - "name": "Microsoft Corporation", - "email": "support@microsoft.com", - "link": "https://support.microsoft.com/" - } - } - } - ] - }, - "packageKind": "Solution", - "packageVersion": "[variables('_solutionVersion')]", - "packageName": "[variables('_solutionName')]", - "packageId": "[variables('_solutionId')]", - "contentSchemaVersion": "3.0.0", - "contentId": "[variables('_dataConnectorContentId4')]", - "contentKind": "DataConnector", - "displayName": "Microsoft Defender Threat Intelligence (Preview)", - "contentProductId": "[variables('_dataConnectorcontentProductId4')]", - "id": "[variables('_dataConnectorcontentProductId4')]", - "version": "[variables('dataConnectorVersion4')]" - } - }, - { - "type": "Microsoft.OperationalInsights/workspaces/providers/metadata", - "apiVersion": "2023-04-01-preview", - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('DataConnector-', last(split(variables('_dataConnectorId4'),'/'))))]", - "dependsOn": [ - "[variables('_dataConnectorId4')]" - ], - "location": "[parameters('workspace-location')]", - "properties": { - "parentId": "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/dataConnectors', variables('_dataConnectorContentId4'))]", - "contentId": "[variables('_dataConnectorContentId4')]", - "kind": "DataConnector", - "version": "[variables('dataConnectorVersion4')]", - "source": { - "kind": "Solution", - "name": "Threat Intelligence", - "sourceId": "[variables('_solutionId')]" - }, - "author": { - "name": "Microsoft", - "email": "[variables('_email')]" - }, - "support": { - "tier": "Microsoft", - "name": "Microsoft Corporation", - "email": "support@microsoft.com", - "link": "https://support.microsoft.com/" - } - } - }, - { - "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',variables('_dataConnectorContentId4'))]", - "apiVersion": "2021-03-01-preview", - "type": "Microsoft.OperationalInsights/workspaces/providers/dataConnectors", - "location": "[parameters('workspace-location')]", - "kind": "StaticUI", - "properties": { - "connectorUiConfig": { - "title": "Microsoft Defender Threat Intelligence (Preview)", - "publisher": "Microsoft", - "descriptionMarkdown": "Microsoft Sentinel provides you the capability to import threat intelligence generated by Microsoft to enable monitoring, alerting and hunting. Use this data connector to import Indicators of Compromise (IOCs) from Microsoft Defender Threat Intelligence (MDTI) into Microsoft Sentinel. Threat indicators can include IP addresses, domains, URLs, and file hashes, etc.", - "graphQueries": [ - { - "metricName": "Total data received", - "legend": "ThreatIntelligenceIndicator", - "baseQuery": "ThreatIntelligenceIndicator\n | where SourceSystem in (\"Microsoft Defender Threat Intelligence\", \"Microsoft Emerging Threat Feed\")" - } - ], - "dataTypes": [ - { - "name": "ThreatIntelligenceIndicator", - "lastDataReceivedQuery": "ThreatIntelligenceIndicator \n | where SourceSystem in (\"Microsoft Defender Threat Intelligence\", \"Microsoft Emerging Threat Feed\")\n | summarize Time = max(TimeGenerated)\n | where isnotempty(Time)" - } - ], - "connectivityCriterias": [ - { - "type": "SentinelKinds", - "value": [ - "MicrosoftThreatIntelligence" - ] - } - ], - "id": "[variables('_uiConfigId4')]" - } - } - }, { "type": "Microsoft.OperationalInsights/workspaces/providers/contentTemplates", "apiVersion": "2023-04-01-preview", @@ -1078,7 +321,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "ThreatIntelligenceWorkbook Workbook with template version 3.0.1", + "description": "ThreatIntelligenceWorkbook Workbook with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('workbookVersion1')]", @@ -1096,7 +339,7 @@ }, "properties": { "displayName": "[parameters('workbook1-name')]", - "serializedData": "{\"version\":\"Notebook/1.0\",\"items\":[{\"type\":9,\"content\":{\"version\":\"KqlParameterItem/1.0\",\"parameters\":[{\"id\":\"a4b4e975-fa7c-46a3-b669-850aacc88134\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"Help\",\"label\":\"Guide\",\"type\":10,\"isRequired\":true,\"typeSettings\":{\"showDefault\":false},\"jsonData\":\"[\\r\\n {\\\"value\\\": \\\"Yes\\\", \\\"label\\\": \\\"Yes\\\", \\\"selected\\\":true},\\r\\n {\\\"value\\\": \\\"No\\\", \\\"label\\\": \\\"No\\\"}\\r\\n]\"},{\"version\":\"KqlParameterItem/1.0\",\"name\":\"DefaultSubscription_Internal\",\"type\":1,\"isRequired\":true,\"query\":\"where type =~ 'microsoft.operationalinsights/workspaces'\\r\\n| take 1\\r\\n| project subscriptionId\",\"crossComponentResources\":[\"value::selected\"],\"isHiddenWhenLocked\":true,\"queryType\":1,\"resourceType\":\"microsoft.resourcegraph/resources\",\"id\":\"314d02bf-4691-43fa-af59-d67073c8b8fa\"},{\"id\":\"e6ded9a1-a83c-4762-938d-5bf8ff3d3d38\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"Subscription\",\"type\":6,\"isRequired\":true,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"summarize by subscriptionId\\r\\n| project value = strcat(\\\"/subscriptions/\\\", subscriptionId), label = subscriptionId, selected = iff(subscriptionId =~ '{DefaultSubscription_Internal}', true, false)\",\"crossComponentResources\":[\"value::all\"],\"typeSettings\":{\"additionalResourceOptions\":[\"value::all\"],\"showDefault\":false},\"queryType\":1,\"resourceType\":\"microsoft.resourcegraph/resources\",\"value\":[\"value::all\"]},{\"id\":\"e3225ed0-6210-40a1-b2d0-66e42ffa71d6\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"Workspace\",\"type\":5,\"isRequired\":true,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"resources\\r\\n| where type =~ 'microsoft.operationalinsights/workspaces'\\r\\n| order by name asc\\r\\n| summarize Selected = makelist(id, 10), All = makelist(id, 1000)\\r\\n| mvexpand All limit 100\\r\\n| project value = tostring(All), label = tostring(All), selected = iff(Selected contains All, true, false)\",\"crossComponentResources\":[\"{Subscription}\"],\"typeSettings\":{\"additionalResourceOptions\":[\"value::all\"],\"showDefault\":false},\"queryType\":1,\"resourceType\":\"microsoft.resourcegraph/resources\",\"value\":[\"value::all\"]},{\"id\":\"15b2c181-7397-43c1-900a-28e175ae8a6f\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"TimeRange\",\"type\":4,\"isRequired\":true,\"value\":{\"durationMs\":86400000},\"typeSettings\":{\"selectableValues\":[{\"durationMs\":86400000},{\"durationMs\":172800000},{\"durationMs\":604800000}],\"allowCustom\":true},\"timeContextFromParameter\":\"TimeRange\"}],\"style\":\"pills\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},\"name\":\"Parameter Selectors\"},{\"type\":1,\"content\":{\"json\":\"  Please take time to answer a quick survey,\\r\\n[ click here. ](https://forms.office.com/r/n9beey85aP)\"},\"name\":\"Survey\"},{\"type\":1,\"content\":{\"json\":\"# [Threat Intelligence](https://docs.microsoft.com/azure/sentinel/understand-threat-intelligence)\\n---\\n\\nWithin a Security Information and Event Management (SIEM) solution like Microsoft Sentinel, the most commonly used form of CTI is threat indicators, also known as Indicators of Compromise or IoCs. Threat indicators are data that associate observed artifacts such as URLs, file hashes, or IP addresses with known threat activity such as phishing, botnets, or malware. This form of threat intelligence is often called tactical threat intelligence because it can be applied to security products and automation in large scale to detect potential threats to an organization and protect against them. In Microsoft Sentinel, you can use threat indicators to help detect malicious activity observed in your environment and provide context to security investigators to help inform response decisions. [Video Demo](https://youtu.be/4Bet2oVODow)
\\n\"},\"conditionalVisibility\":{\"parameterName\":\"Help\",\"comparison\":\"isEqualTo\",\"value\":\"Yes\"},\"customWidth\":\"79\",\"name\":\"Workbook Overview\"},{\"type\":1,\"content\":{\"json\":\"![Image Name](https://azure.microsoft.com/svghandler/azure-sentinel?width=600&height=315) \"},\"conditionalVisibility\":{\"parameterName\":\"Help\",\"comparison\":\"isEqualTo\",\"value\":\"Yes\"},\"customWidth\":\"20\",\"name\":\"Microsoft Sentinel Logo\"},{\"type\":11,\"content\":{\"version\":\"LinkItem/1.0\",\"style\":\"tabs\",\"links\":[{\"id\":\"18c690d7-7cbd-46c1-b677-1f72692d40cd\",\"cellValue\":\"TAB\",\"linkTarget\":\"parameter\",\"linkLabel\":\"Indicators Ingestion\",\"subTarget\":\"Indicators\",\"preText\":\"Alert rules\",\"style\":\"link\"},{\"id\":\"f88dcf47-af98-4684-9de3-1ee5f48f68fc\",\"cellValue\":\"TAB\",\"linkTarget\":\"parameter\",\"linkLabel\":\"Indicators Search\",\"subTarget\":\"Observed\",\"style\":\"link\"}]},\"name\":\"Tabs link\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"ThreatIntelligenceIndicator\\r\\n// Select all indicators from the table\\r\\n// Create a new column to identify the type of indicator, IP, Domain, URL, File, or Other\\r\\n| extend IndicatorType = iif(isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkIP) or isnotempty(NetworkSourceIP) or isnotempty(NetworkCidrBlock), \\\"IP\\\",\\r\\n iff(isnotempty(Url), \\\"URL\\\",\\r\\n iff(isnotempty(EmailRecipient) or isnotempty(EmailSenderAddress), \\\"Email\\\",\\r\\n iff(isnotempty(FileHashValue), \\\"File\\\",\\r\\n iff(isnotempty(DomainName) or isnotempty(EmailSourceDomain), \\\"Domain\\\",\\r\\n \\\"Other\\\")))))\\r\\n// Summarize and order the data, then render the chart\\r\\n| summarize CountOfIndicators = count() by IndicatorType, bin(TimeGenerated, 1h)\\r\\n| order by CountOfIndicators desc \\r\\n| render barchart kind=stacked \",\"size\":0,\"showAnalytics\":true,\"title\":\"Indicators Imported into Sentinel by Indicator Type and Date\",\"timeContextFromParameter\":\"TimeRange\",\"showExportToExcel\":true,\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"crossComponentResources\":[\"{Workspace}\"]},\"customWidth\":\"50\",\"name\":\"query - 1\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"ThreatIntelligenceIndicator\\r\\n// Select all indicators from the table\\r\\n// Summarize and order the data, then render the chart\\r\\n| summarize CountOfIndicators = count() by SourceSystem, bin(TimeGenerated, 1h)\\r\\n| render barchart kind=stacked\",\"size\":0,\"showAnalytics\":true,\"title\":\"Indicators Imported into Sentinel by Indicator Provider and Date\",\"timeContextFromParameter\":\"TimeRange\",\"showExportToExcel\":true,\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"crossComponentResources\":[\"{Workspace}\"]},\"customWidth\":\"50\",\"name\":\"query - 3\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"ThreatIntelligenceIndicator\\r\\n// Select all indicators from the table\\r\\n| where TimeGenerated < now()\\r\\n// Select only indicators that have not expired\\r\\n and ExpirationDateTime > now()\\r\\n// Select only indicators that are marked active\\r\\n and Active == true\\r\\n// Select only the most recently ingested copy of an indicator\\r\\n| summarize arg_max(TimeGenerated, *) by IndicatorId\\r\\n// Create a new column to identify the type of indicator, IP, Domain, URL, File, or Other\\r\\n| extend IndicatorType = iif(isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkIP) or isnotempty(NetworkSourceIP) or isnotempty(NetworkCidrBlock), \\\"IP\\\",\\r\\n iff(isnotempty(Url), \\\"URL\\\",\\r\\n iff(isnotempty(EmailRecipient) or isnotempty(EmailSenderAddress), \\\"Email\\\",\\r\\n iff(isnotempty(FileHashValue), \\\"File\\\",\\r\\n iff(isnotempty(DomainName) or isnotempty(EmailSourceDomain), \\\"Domain\\\",\\r\\n \\\"Other\\\")))))\\r\\n// Summarize and order the data, then render the chart\\r\\n| summarize CountOfIndicators = count() by IndicatorType\\r\\n| order by CountOfIndicators desc \\r\\n| render barchart kind=unstacked\",\"size\":0,\"showAnalytics\":true,\"title\":\"Active Indicators by Indicator Type\",\"timeContextFromParameter\":\"TimeRange\",\"showExportToExcel\":true,\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"crossComponentResources\":[\"{Workspace}\"]},\"customWidth\":\"50\",\"name\":\"query - 5\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"ThreatIntelligenceIndicator\\r\\n// Select all indicators from the table\\r\\n| where TimeGenerated < now()\\r\\n// Select only indicators that have not expired\\r\\n and ExpirationDateTime > now()\\r\\n// Select only indicators that are marked active\\r\\n and Active == true\\r\\n// Select only the most recently ingested copy of an indicator\\r\\n| summarize arg_max(TimeGenerated, *) by IndicatorId\\r\\n// Summarize and order the data, then render the chart\\r\\n| summarize CountOfIndicators = count() by SourceSystem\\r\\n| order by CountOfIndicators desc \\r\\n| render barchart kind=unstacked\",\"size\":0,\"showAnalytics\":true,\"title\":\"Active Indicators by Indicator Source\",\"timeContextFromParameter\":\"TimeRange\",\"showExportToExcel\":true,\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"crossComponentResources\":[\"{Workspace}\"]},\"customWidth\":\"50\",\"name\":\"query - 7\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"ThreatIntelligenceIndicator\\r\\n// Select all indicators from the table\\r\\n| where TimeGenerated < now()\\r\\n// Select only indicators that have not expired\\r\\n and ExpirationDateTime > now()\\r\\n// Select only indicators that are marked active\\r\\n and Active == true\\r\\n// Select only the most recently ingested copy of an indicator\\r\\n| summarize arg_max(TimeGenerated, *) by IndicatorId\\r\\n// Summarize and order the data, then render the chart\\r\\n| summarize CountOfIndicators = count() by tostring(ConfidenceScore)\\r\\n| order by CountOfIndicators desc \\r\\n| render piechart\",\"size\":0,\"showAnalytics\":true,\"title\":\"Active Indicators by Confidence Score\",\"timeContextFromParameter\":\"TimeRange\",\"showExportToExcel\":true,\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"crossComponentResources\":[\"{Workspace}\"]},\"customWidth\":\"50\",\"name\":\"query - 10\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"let DomainQuery=view() { \\r\\nThreatIntelligenceIndicator\\r\\n| summarize arg_max(TimeGenerated, *) by IndicatorId\\r\\n| where isnotempty(DomainName)\\r\\n| summarize SourceSystemArray=make_set(SourceSystem) by DomainName\\r\\n| summarize count() by tostring(SourceSystemArray)\\r\\n| project SourceSystemArray, count_, EntryType=\\\"DomainEntry\\\"\\r\\n};\\r\\nlet UrlQuery=view(){\\r\\nThreatIntelligenceIndicator\\r\\n| summarize arg_max(TimeGenerated, *) by IndicatorId\\r\\n| where isnotempty(Url)\\r\\n| summarize SourceSystemArray=make_set(SourceSystem) by Url\\r\\n| summarize count() by tostring(SourceSystemArray)\\r\\n| project SourceSystemArray, count_, EntryType=\\\"UrlEntry\\\"\\r\\n};\\r\\nlet FileHashQuery=view(){\\r\\nThreatIntelligenceIndicator\\r\\n| summarize arg_max(TimeGenerated, *) by IndicatorId\\r\\n| where isnotempty(FileHashValue)\\r\\n| summarize SourceSystemArray=make_set(SourceSystem) by FileHashValue\\r\\n| summarize count() by tostring(SourceSystemArray)\\r\\n| project SourceSystemArray, count_, EntryType=\\\"FileHashEntry\\\"\\r\\n};\\r\\nlet IPQuery=view(){\\r\\nThreatIntelligenceIndicator\\r\\n| summarize arg_max(TimeGenerated, *) by IndicatorId\\r\\n| where isnotempty(NetworkIP) or isnotempty(NetworkSourceIP)\\r\\n| summarize SourceSystemArray=make_set(SourceSystem) by NetworkIP, NetworkSourceIP\\r\\n| summarize count() by tostring(SourceSystemArray)\\r\\n| project SourceSystemArray, count_, EntryType=\\\"IPEntry\\\"\\r\\n};\\r\\nlet EmailAddressQuery=view(){\\r\\nThreatIntelligenceIndicator\\r\\n| summarize arg_max(TimeGenerated, *) by IndicatorId\\r\\n| where isnotempty(EmailSenderAddress)\\r\\n| summarize SourceSystemArray=make_set(SourceSystem) by EmailSenderAddress\\r\\n| summarize count() by tostring(SourceSystemArray)\\r\\n| project SourceSystemArray, count_, EntryType=\\\"EmailAddressEntry\\\"\\r\\n};\\r\\nlet EmailMessageQuery=view(){\\r\\nThreatIntelligenceIndicator\\r\\n| summarize arg_max(TimeGenerated, *) by IndicatorId\\r\\n| where isnotempty(EmailSubject)\\r\\n| summarize SourceSystemArray=make_set(SourceSystem) by EmailSubject\\r\\n| summarize count() by tostring(SourceSystemArray)\\r\\n| project SourceSystemArray, count_, EntryType=\\\"EmailMessageEntry\\\"\\r\\n};\\r\\nlet SingleSourceIndicators=view(){\\r\\n DomainQuery\\r\\n | union UrlQuery\\r\\n | union FileHashQuery\\r\\n | union IPQuery\\r\\n | union EmailAddressQuery\\r\\n | union EmailMessageQuery\\r\\n | where array_length(todynamic(SourceSystemArray))==1\\r\\n | summarize sum(count_) by SourceSystemArray\\r\\n | extend counter=1 \\r\\n};\\r\\nlet MultipleSourceIndicators=view(){\\r\\n DomainQuery\\r\\n | union UrlQuery\\r\\n | union FileHashQuery\\r\\n | union IPQuery\\r\\n | union EmailAddressQuery\\r\\n | union EmailMessageQuery\\r\\n | where array_length(todynamic(SourceSystemArray))!=1\\r\\n | summarize sum(count_) by SourceSystemArray\\r\\n | extend counter=1\\r\\n};\\r\\nlet CountOfActiveIndicatorsBySource=view(){\\r\\n ThreatIntelligenceIndicator\\r\\n\\t| summarize arg_max(TimeGenerated, *) by IndicatorId\\r\\n | where ExpirationDateTime > now() and Active == true\\r\\n | summarize count() by SourceSystem\\r\\n | project SourceSystem, count_\\r\\n};\\r\\nSingleSourceIndicators\\r\\n| join kind=fullouter MultipleSourceIndicators on counter \\r\\n| where SourceSystemArray contains todynamic(SourceSystemArray)[0] \\r\\n| order by SourceSystemArray\\r\\n| extend solitary_count=sum_count_\\r\\n| summarize shared_count = sum(sum_count_1) by SourceSystemArray, solitary_count\\r\\n| extend total_count = shared_count + solitary_count\\r\\n| extend unique_percentage = round(toreal(solitary_count)/toreal(total_count)*100, 1)\\r\\n| extend IndicatorSource = tostring(todynamic(SourceSystemArray)[0])\\r\\n| join kind=inner CountOfActiveIndicatorsBySource on $left.IndicatorSource == $right.SourceSystem\\r\\n| order by unique_percentage desc\\r\\n| project Source=IndicatorSource, UniquenessPercentage=unique_percentage, ActiveIndicators = count_\\r\\n\\r\\n\",\"size\":0,\"showAnalytics\":true,\"title\":\"Uniqueness of Threat Intelligence Sources\",\"timeContextFromParameter\":\"TimeRange\",\"showExportToExcel\":true,\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"crossComponentResources\":[\"{Workspace}\"],\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"Source\",\"formatter\":18,\"formatOptions\":{\"thresholdsOptions\":\"icons\",\"thresholdsGrid\":[{\"operator\":\"Default\",\"thresholdValue\":\"\",\"representation\":\"View\",\"text\":\"{0}{1}\"}]}},{\"columnMatch\":\"ActiveIndicators\",\"formatter\":4,\"formatOptions\":{\"palette\":\"blue\"}}],\"filter\":true}},\"customWidth\":\"50\",\"name\":\"query - 12\"}]},\"conditionalVisibility\":{\"parameterName\":\"TAB\",\"comparison\":\"isEqualTo\",\"value\":\"Indicators\"},\"name\":\"Indicators Ingestion\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":9,\"content\":{\"version\":\"KqlParameterItem/1.0\",\"parameters\":[{\"id\":\"9aec751b-07bd-43ba-80b9-f711887dce45\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"Indicator\",\"label\":\"Search Indicator in Events\",\"type\":1,\"value\":\"\",\"timeContext\":{\"durationMs\":7776000000},\"timeContextFromParameter\":\"TimeRange\"}],\"style\":\"pills\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},\"customWidth\":\"50\",\"name\":\"Threat Research Parameters\"},{\"type\":1,\"content\":{\"json\":\"\"},\"customWidth\":\"50\",\"name\":\"text - 9\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"//Add additional lines for desired data columns\\r\\nunion withsource= Table_Name *\\r\\n| where column_ifexists('CallerIpAddress', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DestinationIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FileOriginUrl', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FQDN', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('InitiatingProcessSHA256', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('IpAddress', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('IPAddresses', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('IPAddress', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Name', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('RemoteIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('RemoteUrl', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('RecipientEmailAddress', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('SenderMailFromAddress', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('SourceIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Url', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('SrcIpAddr', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DstIpAddr', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('NetworkSourceIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FileHashValue', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('NetworkIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('NetworkDestinationIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('EmailSourceIpAddress', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('EmailSenderAddress', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DomainName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('AADEmail', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Account', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('AccountName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('AccountUpn', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('AccountUPN', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Caller', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('CompromisedEntity', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DestinationUserID', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DestinationUserName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DisplayName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Email_s', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FullyQualifiedSubjectUserName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('InitiatingProcessAccountUpn', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('MailboxOwnerUPN', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Owner', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('RequesterUpn', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('SourceIdentity', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('SourceUserID', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('SourceUserName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('SubjectUserName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('TargetUser', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('TargetUserName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Upn', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('User_s', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('UserId', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('UserId_', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('UserId_s_s', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('userName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('UserName', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('UserName_s', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('userPrincipalName_s', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('UserPrincipalName_s', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('UserPrincipalName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Computer', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FileHash', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FilePath', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Process', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('CommandLine', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('NewProcessName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('ParentProcessName', '') has \\\"{Indicator}\\\"\\r\\n| summarize count() by Table_Name \\r\\n| project-rename ['Data Table']=Table_Name, ['Logs Count']=count_\\r\\n| sort by ['Logs Count'] desc\",\"size\":0,\"showAnalytics\":true,\"title\":\"Indicators Observed\",\"noDataMessage\":\"No indicators observed within these thresholds\",\"timeContextFromParameter\":\"TimeRange\",\"exportFieldName\":\"Type\",\"exportParameterName\":\"Type\",\"showExportToExcel\":true,\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"crossComponentResources\":[\"{Workspace}\"],\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"Data Table\",\"formatter\":18,\"formatOptions\":{\"thresholdsOptions\":\"icons\",\"thresholdsGrid\":[{\"operator\":\"Default\",\"thresholdValue\":\"\",\"representation\":\"Log\",\"text\":\"{0}{1}\"}]}},{\"columnMatch\":\"Logs Count\",\"formatter\":4,\"formatOptions\":{\"palette\":\"blue\"}}],\"filter\":true}},\"customWidth\":\"50\",\"name\":\"query - 4\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"//Add additional lines for desired data columns\\r\\nunion withsource= Table_Name *\\r\\n| where column_ifexists('CallerIpAddress', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DestinationIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FileOriginUrl', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FQDN', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('InitiatingProcessSHA256', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('IpAddress', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('IPAddresses', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('IPAddress', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Name', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('RemoteIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('RemoteUrl', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('RecipientEmailAddress', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('SenderMailFromAddress', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('SourceIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Url', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('SrcIpAddr', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DstIpAddr', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('NetworkSourceIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FileHashValue', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('NetworkIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('NetworkDestinationIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('EmailSourceIpAddress', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('EmailSenderAddress', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DomainName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('AADEmail', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Account', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('AccountName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('AccountUpn', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('AccountUPN', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Caller', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('CompromisedEntity', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DestinationUserID', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DestinationUserName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DisplayName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Email_s', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FullyQualifiedSubjectUserName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('InitiatingProcessAccountUpn', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('MailboxOwnerUPN', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Owner', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('RequesterUpn', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('SourceIdentity', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('SourceUserID', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('SourceUserName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('SubjectUserName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('TargetUser', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('TargetUserName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Upn', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('User_s', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('UserId', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('UserId_', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('UserId_s_s', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('userName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('UserName', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('UserName_s', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('userPrincipalName_s', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('UserPrincipalName_s', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('UserPrincipalName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Computer', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FileHash', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FilePath', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Process', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('CommandLine', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('NewProcessName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('ParentProcessName', '') has \\\"{Indicator}\\\"\\r\\n| make-series count() default=0 on TimeGenerated from {TimeRange:start} to {TimeRange:end} step 1d by Type\\r\\n| render areachart\",\"size\":0,\"showAnalytics\":true,\"title\":\"Indicators Observed over Time\",\"noDataMessage\":\"No indicators observed within these thresholds\",\"timeContextFromParameter\":\"TimeRange\",\"showExportToExcel\":true,\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"crossComponentResources\":[\"{Workspace}\"],\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"Data Table\",\"formatter\":18,\"formatOptions\":{\"thresholdsOptions\":\"icons\",\"thresholdsGrid\":[{\"operator\":\"Default\",\"thresholdValue\":\"\",\"representation\":\"Log\",\"text\":\"{0}{1}\"}]}},{\"columnMatch\":\"Logs Count\",\"formatter\":4,\"formatOptions\":{\"palette\":\"redBright\"}}],\"filter\":true}},\"customWidth\":\"50\",\"name\":\"query - 4 - Copy\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"let tiObservables = ThreatIntelligenceIndicator\\r\\n | where TimeGenerated < now()\\r\\n | project IndicatorId, ThreatType, Description, Active, IndicatorTime = TimeGenerated, Indicator = strcat(NetworkSourceIP, NetworkIP, NetworkDestinationIP, Url, FileHashValue, EmailSourceIpAddress, EmailSenderAddress, DomainName), SourceSystem;\\r\\nlet alertEntity = SecurityAlert \\r\\n | project parse_json(Entities), SystemAlertId , AlertTime = TimeGenerated\\r\\n | mvexpand(Entities)\\r\\n | extend entity = iif(isnotempty(Entities.Address), Entities.Address,\\r\\n iif(isnotempty(Entities.HostName),strcat(Entities.HostName, \\\".\\\", Entities.DnsDomain),\\r\\n iif(isnotempty(Entities.Url), Entities.Url,\\r\\n iif(isnotempty(Entities.Value), Entities.Value,\\r\\n iif(Entities.Type == \\\"account\\\", strcat(Entities.Name,\\\"@\\\",Entities.UPNSuffix),\\\"\\\")))))\\r\\n | where isnotempty(entity) \\r\\n | project entity, SystemAlertId, AlertTime;\\r\\nlet IncidentAlerts = SecurityIncident\\r\\n | project IncidentTime = TimeGenerated, IncidentNumber, Title, parse_json(AlertIds)\\r\\n | mv-expand AlertIds\\r\\n | project IncidentTime, IncidentNumber, Title, tostring(AlertIds);\\r\\nlet AlertsWithTiObservables = alertEntity\\r\\n | join kind=inner tiObservables on $left.entity == $right.Indicator;\\r\\nlet IncidentsWithAlertsWithTiObservables = AlertsWithTiObservables\\r\\n | join kind=inner IncidentAlerts on $left.SystemAlertId == $right.AlertIds;\\r\\nIncidentsWithAlertsWithTiObservables\\r\\n| where Indicator contains '{Indicator}' or Indicator == \\\"*\\\"\\r\\n| summarize Incidents=dcount(IncidentNumber), Alerts=dcount(SystemAlertId) by Indicator, ThreatType, Source = SourceSystem, Description\\r\\n| sort by Incidents, Alerts desc\",\"size\":0,\"showAnalytics\":true,\"title\":\"Threat Intelligence Alerts\",\"noDataMessage\":\"No indicators observed within these thresholds\",\"timeContextFromParameter\":\"TimeRange\",\"showExportToExcel\":true,\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"crossComponentResources\":[\"{Workspace}\"],\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"ThreatType\",\"formatter\":18,\"formatOptions\":{\"thresholdsOptions\":\"icons\",\"thresholdsGrid\":[{\"operator\":\"==\",\"thresholdValue\":\"Botnet\",\"representation\":\"Command and Control\",\"text\":\"{0}{1}\"},{\"operator\":\"==\",\"thresholdValue\":\"MaliciousUrl\",\"representation\":\"Initial_Access\",\"text\":\"{0}{1}\"},{\"operator\":\"==\",\"thresholdValue\":\"Malware\",\"representation\":\"Execution\",\"text\":\"{0}{1}\"},{\"operator\":\"==\",\"thresholdValue\":\"Phishing\",\"representation\":\"Exfiltration\",\"text\":\"{0}{1}\"},{\"operator\":\"Default\",\"thresholdValue\":\"\",\"representation\":\"Pre attack\",\"text\":\"{0}{1}\"}]}},{\"columnMatch\":\"Source\",\"formatter\":18,\"formatOptions\":{\"thresholdsOptions\":\"icons\",\"thresholdsGrid\":[{\"operator\":\"Default\",\"thresholdValue\":\"\",\"representation\":\"success\",\"text\":\"{0}{1}\"}]}},{\"columnMatch\":\"Incidents\",\"formatter\":4,\"formatOptions\":{\"palette\":\"redBright\"}},{\"columnMatch\":\"Alerts\",\"formatter\":4,\"formatOptions\":{\"palette\":\"orange\"}}],\"filter\":true}},\"name\":\"query - 5\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityIncident\\r\\n| extend SystemAlertId = tostring(AlertIds[0])\\r\\n| join (SecurityAlert \\r\\n| where Entities <> \\\"\\\"\\r\\n| mv-expand parse_json(Entities)\\r\\n| where Entities contains '{Indicator}'\\r\\n| project SystemAlertId, Entities\\r\\n) on SystemAlertId\\r\\n| where Title <> \\\"\\\"\\r\\n| summarize arg_max(TimeGenerated, *) by IncidentNumber\\r\\n| parse IncidentUrl with * '/#asset/Microsoft_Azure_Security_Insights/Incident' IncidentBlade\\r\\n| extend SeverityRank=iff(Severity == \\\"High\\\", 3, iff(Severity == \\\"Medium\\\", 2, iff(Severity == \\\"Low\\\", 1, iff(Severity == \\\"Informational\\\", 0, 0))))\\r\\n| sort by SeverityRank, IncidentNumber desc\\r\\n| project ['Incident Name']=Title, IncidentNumber, Severity, IncidentUrl, FirstActivityTime, IncidentBlade, Entities\\r\\n| limit 2500\",\"size\":0,\"showAnalytics\":true,\"title\":\"Security Incidents\",\"noDataMessage\":\"No incidents observed within these thresholds\",\"timeContextFromParameter\":\"TimeRange\",\"showExportToExcel\":true,\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"crossComponentResources\":[\"{Workspace}\"],\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"Incident Name\",\"formatter\":18,\"formatOptions\":{\"thresholdsOptions\":\"icons\",\"thresholdsGrid\":[{\"operator\":\"Default\",\"thresholdValue\":\"\",\"representation\":\"Alert\",\"text\":\"{0}{1}\"}]}},{\"columnMatch\":\"Severity\",\"formatter\":18,\"formatOptions\":{\"thresholdsOptions\":\"icons\",\"thresholdsGrid\":[{\"operator\":\"==\",\"thresholdValue\":\"High\",\"representation\":\"Sev0\",\"text\":\"{0}{1}\"},{\"operator\":\"==\",\"thresholdValue\":\"Medium\",\"representation\":\"Sev1\",\"text\":\"{0}{1}\"},{\"operator\":\"==\",\"thresholdValue\":\"Low\",\"representation\":\"Sev2\",\"text\":\"{0}{1}\"},{\"operator\":\"Default\",\"thresholdValue\":\"\",\"representation\":\"Sev3\",\"text\":\"{0}{1}\"}]}},{\"columnMatch\":\"IncidentUrl\",\"formatter\":7,\"formatOptions\":{\"linkTarget\":\"OpenBlade\",\"linkLabel\":\"Incident >>\",\"bladeOpenContext\":{\"bladeName\":\"CaseBlade\",\"extensionName\":\"Microsoft_Azure_Security_Insights\",\"bladeParameters\":[{\"name\":\"id\",\"source\":\"column\",\"value\":\"IncidentBlade\"}]}}},{\"columnMatch\":\"IncidentBlade\",\"formatter\":5}],\"rowLimit\":2500,\"filter\":true,\"sortBy\":[{\"itemKey\":\"IncidentNumber\",\"sortOrder\":2}]},\"sortBy\":[{\"itemKey\":\"IncidentNumber\",\"sortOrder\":2}]},\"name\":\"query - 3\"}]},\"conditionalVisibility\":{\"parameterName\":\"TAB\",\"comparison\":\"isEqualTo\",\"value\":\"Observed\"},\"name\":\"Indicators Observed\"}],\"fromTemplateId\":\"sentinel-ThreatIntelligence\",\"$schema\":\"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"}\r\n", + "serializedData": "{\"version\":\"Notebook/1.0\",\"items\":[{\"type\":9,\"content\":{\"version\":\"KqlParameterItem/1.0\",\"parameters\":[{\"id\":\"a4b4e975-fa7c-46a3-b669-850aacc88134\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"Help\",\"label\":\"Guide\",\"type\":10,\"isRequired\":true,\"typeSettings\":{\"showDefault\":false},\"jsonData\":\"[\\r\\n {\\\"value\\\": \\\"Yes\\\", \\\"label\\\": \\\"Yes\\\", \\\"selected\\\":true},\\r\\n {\\\"value\\\": \\\"No\\\", \\\"label\\\": \\\"No\\\"}\\r\\n]\"},{\"version\":\"KqlParameterItem/1.0\",\"name\":\"DefaultSubscription_Internal\",\"type\":1,\"isRequired\":true,\"query\":\"where type =~ 'microsoft.operationalinsights/workspaces'\\r\\n| take 1\\r\\n| project subscriptionId\",\"crossComponentResources\":[\"value::selected\"],\"isHiddenWhenLocked\":true,\"queryType\":1,\"resourceType\":\"microsoft.resourcegraph/resources\",\"id\":\"314d02bf-4691-43fa-af59-d67073c8b8fa\"},{\"id\":\"e6ded9a1-a83c-4762-938d-5bf8ff3d3d38\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"Subscription\",\"type\":6,\"isRequired\":true,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"summarize by subscriptionId\\r\\n| project value = strcat(\\\"/subscriptions/\\\", subscriptionId), label = subscriptionId, selected = iff(subscriptionId =~ '{DefaultSubscription_Internal}', true, false)\",\"crossComponentResources\":[\"value::all\"],\"typeSettings\":{\"additionalResourceOptions\":[\"value::all\"],\"showDefault\":false},\"queryType\":1,\"resourceType\":\"microsoft.resourcegraph/resources\",\"value\":[\"value::all\"]},{\"id\":\"e3225ed0-6210-40a1-b2d0-66e42ffa71d6\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"Workspace\",\"type\":5,\"isRequired\":true,\"multiSelect\":true,\"quote\":\"'\",\"delimiter\":\",\",\"query\":\"resources\\r\\n| where type =~ 'microsoft.operationalinsights/workspaces'\\r\\n| order by name asc\\r\\n| summarize Selected = makelist(id, 10), All = makelist(id, 1000)\\r\\n| mvexpand All limit 100\\r\\n| project value = tostring(All), label = tostring(All), selected = iff(Selected contains All, true, false)\",\"crossComponentResources\":[\"{Subscription}\"],\"typeSettings\":{\"additionalResourceOptions\":[\"value::all\"],\"showDefault\":false},\"queryType\":1,\"resourceType\":\"microsoft.resourcegraph/resources\",\"value\":[\"value::all\"]},{\"id\":\"15b2c181-7397-43c1-900a-28e175ae8a6f\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"TimeRange\",\"type\":4,\"isRequired\":true,\"value\":{\"durationMs\":86400000},\"typeSettings\":{\"selectableValues\":[{\"durationMs\":86400000},{\"durationMs\":172800000},{\"durationMs\":604800000}],\"allowCustom\":true},\"timeContextFromParameter\":\"TimeRange\"}],\"style\":\"pills\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},\"name\":\"Parameter Selectors\"},{\"type\":1,\"content\":{\"json\":\"  Please take time to answer a quick survey,\\r\\n[ click here. ](https://forms.office.com/r/n9beey85aP)\"},\"name\":\"Survey\"},{\"type\":1,\"content\":{\"json\":\"# [Threat Intelligence](https://docs.microsoft.com/azure/sentinel/understand-threat-intelligence)\\n---\\n\\nWithin a Security Information and Event Management (SIEM) solution like Microsoft Sentinel, the most commonly used form of CTI is threat indicators, also known as Indicators of Compromise or IoCs. Threat indicators are data that associate observed artifacts such as URLs, file hashes, or IP addresses with known threat activity such as phishing, botnets, or malware. This form of threat intelligence is often called tactical threat intelligence because it can be applied to security products and automation in large scale to detect potential threats to an organization and protect against them. In Microsoft Sentinel, you can use threat indicators to help detect malicious activity observed in your environment and provide context to security investigators to help inform response decisions. [Video Demo](https://youtu.be/4Bet2oVODow)
\\n\"},\"conditionalVisibility\":{\"parameterName\":\"Help\",\"comparison\":\"isEqualTo\",\"value\":\"Yes\"},\"customWidth\":\"79\",\"name\":\"Workbook Overview\"},{\"type\":1,\"content\":{\"json\":\"![Image Name](https://azure.microsoft.com/svghandler/azure-sentinel?width=600&height=315) \"},\"conditionalVisibility\":{\"parameterName\":\"Help\",\"comparison\":\"isEqualTo\",\"value\":\"Yes\"},\"customWidth\":\"20\",\"name\":\"Microsoft Sentinel Logo\"},{\"type\":11,\"content\":{\"version\":\"LinkItem/1.0\",\"style\":\"tabs\",\"links\":[{\"id\":\"18c690d7-7cbd-46c1-b677-1f72692d40cd\",\"cellValue\":\"TAB\",\"linkTarget\":\"parameter\",\"linkLabel\":\"Indicators Ingestion\",\"subTarget\":\"Indicators\",\"preText\":\"Alert rules\",\"style\":\"link\"},{\"id\":\"f88dcf47-af98-4684-9de3-1ee5f48f68fc\",\"cellValue\":\"TAB\",\"linkTarget\":\"parameter\",\"linkLabel\":\"Indicators Search\",\"subTarget\":\"Observed\",\"style\":\"link\"}]},\"name\":\"Tabs link\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"ThreatIntelligenceIndicator\\r\\n// Select all indicators from the table\\r\\n// Create a new column to identify the type of indicator, IP, Domain, URL, File, or Other\\r\\n| extend IndicatorType = iif(isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkIP) or isnotempty(NetworkSourceIP) or isnotempty(NetworkCidrBlock), \\\"IP\\\",\\r\\n iff(isnotempty(Url), \\\"URL\\\",\\r\\n iff(isnotempty(EmailRecipient) or isnotempty(EmailSenderAddress), \\\"Email\\\",\\r\\n iff(isnotempty(FileHashValue), \\\"File\\\",\\r\\n iff(isnotempty(DomainName) or isnotempty(EmailSourceDomain), \\\"Domain\\\",\\r\\n \\\"Other\\\")))))\\r\\n// Summarize and order the data, then render the chart\\r\\n| summarize CountOfIndicators = count() by IndicatorType, bin(TimeGenerated, 1h)\\r\\n| order by CountOfIndicators desc \\r\\n| render barchart kind=stacked \",\"size\":0,\"showAnalytics\":true,\"title\":\"Indicators Imported into Sentinel by Indicator Type and Date\",\"timeContextFromParameter\":\"TimeRange\",\"showExportToExcel\":true,\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"crossComponentResources\":[\"{Workspace}\"]},\"customWidth\":\"50\",\"name\":\"query - 1\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"ThreatIntelligenceIndicator\\r\\n// Select all indicators from the table\\r\\n// Summarize and order the data, then render the chart\\r\\n| summarize CountOfIndicators = count() by SourceSystem, bin(TimeGenerated, 1h)\\r\\n| render barchart kind=stacked\",\"size\":0,\"showAnalytics\":true,\"title\":\"Indicators Imported into Sentinel by Indicator Provider and Date\",\"timeContextFromParameter\":\"TimeRange\",\"showExportToExcel\":true,\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"crossComponentResources\":[\"{Workspace}\"]},\"customWidth\":\"50\",\"name\":\"query - 3\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"ThreatIntelligenceIndicator\\r\\n// Select all indicators from the table\\r\\n| where TimeGenerated < now()\\r\\n// Select only indicators that have not expired\\r\\n and ExpirationDateTime > now()\\r\\n// Select only indicators that are marked active\\r\\n and Active == true\\r\\n// Select only the most recently ingested copy of an indicator\\r\\n| summarize arg_max(TimeGenerated, *) by IndicatorId\\r\\n// Create a new column to identify the type of indicator, IP, Domain, URL, File, or Other\\r\\n| extend IndicatorType = iif(isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkIP) or isnotempty(NetworkSourceIP) or isnotempty(NetworkCidrBlock), \\\"IP\\\",\\r\\n iff(isnotempty(Url), \\\"URL\\\",\\r\\n iff(isnotempty(EmailRecipient) or isnotempty(EmailSenderAddress), \\\"Email\\\",\\r\\n iff(isnotempty(FileHashValue), \\\"File\\\",\\r\\n iff(isnotempty(DomainName) or isnotempty(EmailSourceDomain), \\\"Domain\\\",\\r\\n \\\"Other\\\")))))\\r\\n// Summarize and order the data, then render the chart\\r\\n| summarize CountOfIndicators = count() by IndicatorType\\r\\n| order by CountOfIndicators desc \\r\\n| render barchart kind=unstacked\",\"size\":0,\"showAnalytics\":true,\"title\":\"Active Indicators by Indicator Type\",\"timeContextFromParameter\":\"TimeRange\",\"showExportToExcel\":true,\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"crossComponentResources\":[\"{Workspace}\"]},\"customWidth\":\"50\",\"name\":\"query - 5\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"ThreatIntelligenceIndicator\\r\\n// Select all indicators from the table\\r\\n| where TimeGenerated < now()\\r\\n// Select only indicators that have not expired\\r\\n and ExpirationDateTime > now()\\r\\n// Select only indicators that are marked active\\r\\n and Active == true\\r\\n// Select only the most recently ingested copy of an indicator\\r\\n| summarize arg_max(TimeGenerated, *) by IndicatorId\\r\\n// Summarize and order the data, then render the chart\\r\\n| summarize CountOfIndicators = count() by SourceSystem\\r\\n| order by CountOfIndicators desc \\r\\n| render barchart kind=unstacked\",\"size\":0,\"showAnalytics\":true,\"title\":\"Active Indicators by Indicator Source\",\"timeContextFromParameter\":\"TimeRange\",\"showExportToExcel\":true,\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"crossComponentResources\":[\"{Workspace}\"]},\"customWidth\":\"50\",\"name\":\"query - 7\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"ThreatIntelligenceIndicator\\r\\n// Select all indicators from the table\\r\\n| where TimeGenerated < now()\\r\\n// Select only indicators that have not expired\\r\\n and ExpirationDateTime > now()\\r\\n// Select only indicators that are marked active\\r\\n and Active == true\\r\\n// Select only the most recently ingested copy of an indicator\\r\\n| summarize arg_max(TimeGenerated, *) by IndicatorId\\r\\n// Summarize and order the data, then render the chart\\r\\n| summarize CountOfIndicators = count() by tostring(ConfidenceScore)\\r\\n| order by CountOfIndicators desc \\r\\n| render piechart\",\"size\":0,\"showAnalytics\":true,\"title\":\"Active Indicators by Confidence Score\",\"timeContextFromParameter\":\"TimeRange\",\"showExportToExcel\":true,\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"crossComponentResources\":[\"{Workspace}\"]},\"customWidth\":\"50\",\"name\":\"query - 10\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"let DomainQuery=view() { \\r\\nThreatIntelligenceIndicator\\r\\n| summarize arg_max(TimeGenerated, *) by IndicatorId\\r\\n| where isnotempty(DomainName)\\r\\n| summarize SourceSystemArray=make_set(SourceSystem) by DomainName\\r\\n| summarize count() by tostring(SourceSystemArray)\\r\\n| project SourceSystemArray, count_, EntryType=\\\"DomainEntry\\\"\\r\\n};\\r\\nlet UrlQuery=view(){\\r\\nThreatIntelligenceIndicator\\r\\n| summarize arg_max(TimeGenerated, *) by IndicatorId\\r\\n| where isnotempty(Url)\\r\\n| summarize SourceSystemArray=make_set(SourceSystem) by Url\\r\\n| summarize count() by tostring(SourceSystemArray)\\r\\n| project SourceSystemArray, count_, EntryType=\\\"UrlEntry\\\"\\r\\n};\\r\\nlet FileHashQuery=view(){\\r\\nThreatIntelligenceIndicator\\r\\n| summarize arg_max(TimeGenerated, *) by IndicatorId\\r\\n| where isnotempty(FileHashValue)\\r\\n| summarize SourceSystemArray=make_set(SourceSystem) by FileHashValue\\r\\n| summarize count() by tostring(SourceSystemArray)\\r\\n| project SourceSystemArray, count_, EntryType=\\\"FileHashEntry\\\"\\r\\n};\\r\\nlet IPQuery=view(){\\r\\nThreatIntelligenceIndicator\\r\\n| summarize arg_max(TimeGenerated, *) by IndicatorId\\r\\n| where isnotempty(NetworkIP) or isnotempty(NetworkSourceIP)\\r\\n| summarize SourceSystemArray=make_set(SourceSystem) by NetworkIP, NetworkSourceIP\\r\\n| summarize count() by tostring(SourceSystemArray)\\r\\n| project SourceSystemArray, count_, EntryType=\\\"IPEntry\\\"\\r\\n};\\r\\nlet EmailAddressQuery=view(){\\r\\nThreatIntelligenceIndicator\\r\\n| summarize arg_max(TimeGenerated, *) by IndicatorId\\r\\n| where isnotempty(EmailSenderAddress)\\r\\n| summarize SourceSystemArray=make_set(SourceSystem) by EmailSenderAddress\\r\\n| summarize count() by tostring(SourceSystemArray)\\r\\n| project SourceSystemArray, count_, EntryType=\\\"EmailAddressEntry\\\"\\r\\n};\\r\\nlet EmailMessageQuery=view(){\\r\\nThreatIntelligenceIndicator\\r\\n| summarize arg_max(TimeGenerated, *) by IndicatorId\\r\\n| where isnotempty(EmailSubject)\\r\\n| summarize SourceSystemArray=make_set(SourceSystem) by EmailSubject\\r\\n| summarize count() by tostring(SourceSystemArray)\\r\\n| project SourceSystemArray, count_, EntryType=\\\"EmailMessageEntry\\\"\\r\\n};\\r\\nlet SingleSourceIndicators=view(){\\r\\n DomainQuery\\r\\n | union UrlQuery\\r\\n | union FileHashQuery\\r\\n | union IPQuery\\r\\n | union EmailAddressQuery\\r\\n | union EmailMessageQuery\\r\\n | where array_length(todynamic(SourceSystemArray))==1\\r\\n | summarize sum(count_) by SourceSystemArray\\r\\n | extend counter=1 \\r\\n};\\r\\nlet MultipleSourceIndicators=view(){\\r\\n DomainQuery\\r\\n | union UrlQuery\\r\\n | union FileHashQuery\\r\\n | union IPQuery\\r\\n | union EmailAddressQuery\\r\\n | union EmailMessageQuery\\r\\n | where array_length(todynamic(SourceSystemArray))!=1\\r\\n | summarize sum(count_) by SourceSystemArray\\r\\n | extend counter=1\\r\\n};\\r\\nlet CountOfActiveIndicatorsBySource=view(){\\r\\n ThreatIntelligenceIndicator\\r\\n\\t| summarize arg_max(TimeGenerated, *) by IndicatorId\\r\\n | where ExpirationDateTime > now() and Active == true\\r\\n | summarize count() by SourceSystem\\r\\n | project SourceSystem, count_\\r\\n};\\r\\nSingleSourceIndicators\\r\\n| join kind=fullouter MultipleSourceIndicators on counter \\r\\n| where SourceSystemArray contains todynamic(SourceSystemArray)[0] \\r\\n| order by SourceSystemArray\\r\\n| extend solitary_count=sum_count_\\r\\n| summarize shared_count = sum(sum_count_1) by SourceSystemArray, solitary_count\\r\\n| extend total_count = shared_count + solitary_count\\r\\n| extend unique_percentage = round(toreal(solitary_count)/toreal(total_count)*100, 1)\\r\\n| extend IndicatorSource = tostring(todynamic(SourceSystemArray)[0])\\r\\n| join kind=inner CountOfActiveIndicatorsBySource on $left.IndicatorSource == $right.SourceSystem\\r\\n| order by unique_percentage desc\\r\\n| project Source=IndicatorSource, UniquenessPercentage=unique_percentage, ActiveIndicators = count_\\r\\n\\r\\n\",\"size\":0,\"showAnalytics\":true,\"title\":\"Uniqueness of Threat Intelligence Sources\",\"timeContextFromParameter\":\"TimeRange\",\"showExportToExcel\":true,\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"crossComponentResources\":[\"{Workspace}\"],\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"Source\",\"formatter\":18,\"formatOptions\":{\"thresholdsOptions\":\"icons\",\"thresholdsGrid\":[{\"operator\":\"Default\",\"representation\":\"View\",\"text\":\"{0}{1}\"}]}},{\"columnMatch\":\"ActiveIndicators\",\"formatter\":4,\"formatOptions\":{\"palette\":\"blue\"}}],\"filter\":true}},\"customWidth\":\"50\",\"name\":\"query - 12\"}]},\"conditionalVisibility\":{\"parameterName\":\"TAB\",\"comparison\":\"isEqualTo\",\"value\":\"Indicators\"},\"name\":\"Indicators Ingestion\"},{\"type\":12,\"content\":{\"version\":\"NotebookGroup/1.0\",\"groupType\":\"editable\",\"items\":[{\"type\":9,\"content\":{\"version\":\"KqlParameterItem/1.0\",\"parameters\":[{\"id\":\"9aec751b-07bd-43ba-80b9-f711887dce45\",\"version\":\"KqlParameterItem/1.0\",\"name\":\"Indicator\",\"label\":\"Search Indicator in Events\",\"type\":1,\"value\":\"\",\"timeContext\":{\"durationMs\":7776000000},\"timeContextFromParameter\":\"TimeRange\"}],\"style\":\"pills\",\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\"},\"customWidth\":\"50\",\"name\":\"Threat Research Parameters\"},{\"type\":1,\"content\":{\"json\":\"\"},\"customWidth\":\"50\",\"name\":\"text - 9\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"//Add additional lines for desired data columns\\r\\nunion withsource= Table_Name *\\r\\n| where column_ifexists('CallerIpAddress', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DestinationIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FileOriginUrl', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FQDN', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('InitiatingProcessSHA256', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('IpAddress', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('IPAddresses', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('IPAddress', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Name', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('RemoteIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('RemoteUrl', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('RecipientEmailAddress', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('SenderMailFromAddress', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('SourceIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Url', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('SrcIpAddr', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DstIpAddr', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('NetworkSourceIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FileHashValue', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('NetworkIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('NetworkDestinationIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('EmailSourceIpAddress', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('EmailSenderAddress', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DomainName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('AADEmail', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Account', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('AccountName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('AccountUpn', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('AccountUPN', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Caller', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('CompromisedEntity', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DestinationUserID', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DestinationUserName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DisplayName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Email_s', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FullyQualifiedSubjectUserName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('InitiatingProcessAccountUpn', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('MailboxOwnerUPN', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Owner', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('RequesterUpn', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('SourceIdentity', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('SourceUserID', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('SourceUserName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('SubjectUserName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('TargetUser', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('TargetUserName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Upn', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('User_s', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('UserId', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('UserId_', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('UserId_s_s', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('userName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('UserName', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('UserName_s', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('userPrincipalName_s', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('UserPrincipalName_s', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('UserPrincipalName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Computer', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FileHash', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FilePath', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Process', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('CommandLine', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('NewProcessName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('ParentProcessName', '') has \\\"{Indicator}\\\"\\r\\n| summarize count() by Table_Name \\r\\n| project-rename ['Data Table']=Table_Name, ['Logs Count']=count_\\r\\n| sort by ['Logs Count'] desc\",\"size\":0,\"showAnalytics\":true,\"title\":\"Indicators Observed\",\"noDataMessage\":\"No indicators observed within these thresholds\",\"timeContextFromParameter\":\"TimeRange\",\"exportFieldName\":\"Type\",\"exportParameterName\":\"Type\",\"showExportToExcel\":true,\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"crossComponentResources\":[\"{Workspace}\"],\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"Data Table\",\"formatter\":18,\"formatOptions\":{\"thresholdsOptions\":\"icons\",\"thresholdsGrid\":[{\"operator\":\"Default\",\"representation\":\"Log\",\"text\":\"{0}{1}\"}]}},{\"columnMatch\":\"Logs Count\",\"formatter\":4,\"formatOptions\":{\"palette\":\"blue\"}}],\"filter\":true}},\"customWidth\":\"50\",\"name\":\"query - 4\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"//Add additional lines for desired data columns\\r\\nunion withsource= Table_Name *\\r\\n| where column_ifexists('CallerIpAddress', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DestinationIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FileOriginUrl', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FQDN', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('InitiatingProcessSHA256', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('IpAddress', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('IPAddresses', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('IPAddress', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Name', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('RemoteIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('RemoteUrl', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('RecipientEmailAddress', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('SenderMailFromAddress', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('SourceIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Url', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('SrcIpAddr', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DstIpAddr', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('NetworkSourceIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FileHashValue', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('NetworkIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('NetworkDestinationIP', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('EmailSourceIpAddress', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('EmailSenderAddress', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DomainName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('AADEmail', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Account', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('AccountName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('AccountUpn', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('AccountUPN', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Caller', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('CompromisedEntity', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DestinationUserID', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DestinationUserName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('DisplayName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Email_s', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FullyQualifiedSubjectUserName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('InitiatingProcessAccountUpn', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('MailboxOwnerUPN', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Owner', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('RequesterUpn', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('SourceIdentity', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('SourceUserID', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('SourceUserName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('SubjectUserName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('TargetUser', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('TargetUserName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Upn', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('User_s', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('UserId', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('UserId_', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('UserId_s_s', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('userName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('UserName', '') has \\\"{Indicator}\\\" \\r\\nor column_ifexists('UserName_s', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('userPrincipalName_s', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('UserPrincipalName_s', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('UserPrincipalName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Computer', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FileHash', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('FilePath', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('Process', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('CommandLine', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('NewProcessName', '') has \\\"{Indicator}\\\"\\r\\nor column_ifexists('ParentProcessName', '') has \\\"{Indicator}\\\"\\r\\n| make-series count() default=0 on TimeGenerated from {TimeRange:start} to {TimeRange:end} step 1d by Type\\r\\n| render areachart\",\"size\":0,\"showAnalytics\":true,\"title\":\"Indicators Observed over Time\",\"noDataMessage\":\"No indicators observed within these thresholds\",\"timeContextFromParameter\":\"TimeRange\",\"showExportToExcel\":true,\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"crossComponentResources\":[\"{Workspace}\"],\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"Data Table\",\"formatter\":18,\"formatOptions\":{\"thresholdsOptions\":\"icons\",\"thresholdsGrid\":[{\"operator\":\"Default\",\"representation\":\"Log\",\"text\":\"{0}{1}\"}]}},{\"columnMatch\":\"Logs Count\",\"formatter\":4,\"formatOptions\":{\"palette\":\"redBright\"}}],\"filter\":true}},\"customWidth\":\"50\",\"name\":\"query - 4 - Copy\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"let tiObservables = ThreatIntelligenceIndicator\\r\\n | where TimeGenerated < now()\\r\\n | project IndicatorId, ThreatType, Description, Active, IndicatorTime = TimeGenerated, Indicator = strcat(NetworkSourceIP, NetworkIP, NetworkDestinationIP, Url, FileHashValue, EmailSourceIpAddress, EmailSenderAddress, DomainName), SourceSystem;\\r\\nlet alertEntity = SecurityAlert \\r\\n | project parse_json(Entities), SystemAlertId , AlertTime = TimeGenerated\\r\\n | mvexpand(Entities)\\r\\n | extend entity = iif(isnotempty(Entities.Address), Entities.Address,\\r\\n iif(isnotempty(Entities.HostName),strcat(Entities.HostName, \\\".\\\", Entities.DnsDomain),\\r\\n iif(isnotempty(Entities.Url), Entities.Url,\\r\\n iif(isnotempty(Entities.Value), Entities.Value,\\r\\n iif(Entities.Type == \\\"account\\\", strcat(Entities.Name,\\\"@\\\",Entities.UPNSuffix),\\\"\\\")))))\\r\\n | where isnotempty(entity) \\r\\n | project entity, SystemAlertId, AlertTime;\\r\\nlet IncidentAlerts = SecurityIncident\\r\\n | project IncidentTime = TimeGenerated, IncidentNumber, Title, parse_json(AlertIds)\\r\\n | mv-expand AlertIds\\r\\n | project IncidentTime, IncidentNumber, Title, tostring(AlertIds);\\r\\nlet AlertsWithTiObservables = alertEntity\\r\\n | join kind=inner tiObservables on $left.entity == $right.Indicator;\\r\\nlet IncidentsWithAlertsWithTiObservables = AlertsWithTiObservables\\r\\n | join kind=inner IncidentAlerts on $left.SystemAlertId == $right.AlertIds;\\r\\nIncidentsWithAlertsWithTiObservables\\r\\n| where Indicator contains '{Indicator}' or Indicator == \\\"*\\\"\\r\\n| summarize Incidents=dcount(IncidentNumber), Alerts=dcount(SystemAlertId) by Indicator, ThreatType, Source = SourceSystem, Description\\r\\n| sort by Incidents, Alerts desc\",\"size\":0,\"showAnalytics\":true,\"title\":\"Threat Intelligence Alerts\",\"noDataMessage\":\"No indicators observed within these thresholds\",\"timeContextFromParameter\":\"TimeRange\",\"showExportToExcel\":true,\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"crossComponentResources\":[\"{Workspace}\"],\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"ThreatType\",\"formatter\":18,\"formatOptions\":{\"thresholdsOptions\":\"icons\",\"thresholdsGrid\":[{\"operator\":\"==\",\"thresholdValue\":\"Botnet\",\"representation\":\"Command and Control\",\"text\":\"{0}{1}\"},{\"operator\":\"==\",\"thresholdValue\":\"MaliciousUrl\",\"representation\":\"Initial_Access\",\"text\":\"{0}{1}\"},{\"operator\":\"==\",\"thresholdValue\":\"Malware\",\"representation\":\"Execution\",\"text\":\"{0}{1}\"},{\"operator\":\"==\",\"thresholdValue\":\"Phishing\",\"representation\":\"Exfiltration\",\"text\":\"{0}{1}\"},{\"operator\":\"Default\",\"representation\":\"Pre attack\",\"text\":\"{0}{1}\"}]}},{\"columnMatch\":\"Source\",\"formatter\":18,\"formatOptions\":{\"thresholdsOptions\":\"icons\",\"thresholdsGrid\":[{\"operator\":\"Default\",\"representation\":\"success\",\"text\":\"{0}{1}\"}]}},{\"columnMatch\":\"Incidents\",\"formatter\":4,\"formatOptions\":{\"palette\":\"redBright\"}},{\"columnMatch\":\"Alerts\",\"formatter\":4,\"formatOptions\":{\"palette\":\"orange\"}}],\"filter\":true}},\"name\":\"query - 5\"},{\"type\":3,\"content\":{\"version\":\"KqlItem/1.0\",\"query\":\"SecurityIncident\\r\\n| extend SystemAlertId = tostring(AlertIds[0])\\r\\n| join (SecurityAlert \\r\\n| where Entities <> \\\"\\\"\\r\\n| mv-expand parse_json(Entities)\\r\\n| where Entities contains '{Indicator}'\\r\\n| project SystemAlertId, Entities\\r\\n) on SystemAlertId\\r\\n| where Title <> \\\"\\\"\\r\\n| summarize arg_max(TimeGenerated, *) by IncidentNumber\\r\\n| parse IncidentUrl with * '/#asset/Microsoft_Azure_Security_Insights/Incident' IncidentBlade\\r\\n| extend SeverityRank=iff(Severity == \\\"High\\\", 3, iff(Severity == \\\"Medium\\\", 2, iff(Severity == \\\"Low\\\", 1, iff(Severity == \\\"Informational\\\", 0, 0))))\\r\\n| sort by SeverityRank, IncidentNumber desc\\r\\n| project ['Incident Name']=Title, IncidentNumber, Severity, IncidentUrl, FirstActivityTime, IncidentBlade, Entities\\r\\n| limit 2500\",\"size\":0,\"showAnalytics\":true,\"title\":\"Security Incidents\",\"noDataMessage\":\"No incidents observed within these thresholds\",\"timeContextFromParameter\":\"TimeRange\",\"showExportToExcel\":true,\"queryType\":0,\"resourceType\":\"microsoft.operationalinsights/workspaces\",\"crossComponentResources\":[\"{Workspace}\"],\"gridSettings\":{\"formatters\":[{\"columnMatch\":\"Incident Name\",\"formatter\":18,\"formatOptions\":{\"thresholdsOptions\":\"icons\",\"thresholdsGrid\":[{\"operator\":\"Default\",\"representation\":\"Alert\",\"text\":\"{0}{1}\"}]}},{\"columnMatch\":\"Severity\",\"formatter\":18,\"formatOptions\":{\"thresholdsOptions\":\"icons\",\"thresholdsGrid\":[{\"operator\":\"==\",\"thresholdValue\":\"High\",\"representation\":\"Sev0\",\"text\":\"{0}{1}\"},{\"operator\":\"==\",\"thresholdValue\":\"Medium\",\"representation\":\"Sev1\",\"text\":\"{0}{1}\"},{\"operator\":\"==\",\"thresholdValue\":\"Low\",\"representation\":\"Sev2\",\"text\":\"{0}{1}\"},{\"operator\":\"Default\",\"representation\":\"Sev3\",\"text\":\"{0}{1}\"}]}},{\"columnMatch\":\"IncidentUrl\",\"formatter\":7,\"formatOptions\":{\"linkTarget\":\"OpenBlade\",\"linkLabel\":\"Incident >>\",\"bladeOpenContext\":{\"bladeName\":\"CaseBlade\",\"extensionName\":\"Microsoft_Azure_Security_Insights\",\"bladeParameters\":[{\"name\":\"id\",\"source\":\"column\",\"value\":\"IncidentBlade\"}]}}},{\"columnMatch\":\"IncidentBlade\",\"formatter\":5}],\"rowLimit\":2500,\"filter\":true,\"sortBy\":[{\"itemKey\":\"IncidentNumber\",\"sortOrder\":2}]},\"sortBy\":[{\"itemKey\":\"IncidentNumber\",\"sortOrder\":2}]},\"name\":\"query - 3\"}]},\"conditionalVisibility\":{\"parameterName\":\"TAB\",\"comparison\":\"isEqualTo\",\"value\":\"Observed\"},\"name\":\"Indicators Observed\"}],\"fromTemplateId\":\"sentinel-ThreatIntelligence\",\"$schema\":\"https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json\"}\n", "version": "1.0", "sourceId": "[variables('workspaceResourceId')]", "category": "sentinel" @@ -1107,7 +350,7 @@ "apiVersion": "2022-01-01-preview", "name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/',concat('Workbook-', last(split(variables('workbookId1'),'/'))))]", "properties": { - "description": "@{workbookKey=ThreatIntelligenceWorkbook; logoFileName=; description=Gain insights into threat indicators ingestion and search for indicators at scale across Microsoft 1st Party, 3rd Party, On-Premises, Hybrid, and Multi-Cloud Workloads. Indicators Search facilitates a simple interface for finding IP, File, Hash, Sender and more across your data. Seamless pivots to correlate indicators with Microsoft Sentinel: Incidents to make your threat intelligence actionable.; dataTypesDependencies=System.Object[]; dataConnectorsDependencies=System.Object[]; previewImagesFileNames=System.Object[]; version=5.0.0; title=Threat Intelligence; templateRelativePath=ThreatIntelligence.json; subtitle=; provider=Microsoft}.description", + "description": "@{workbookKey=ThreatIntelligenceWorkbook; logoFileName=Azure_Sentinel.svg; description=Gain insights into threat indicators ingestion and search for indicators at scale across Microsoft 1st Party, 3rd Party, On-Premises, Hybrid, and Multi-Cloud Workloads. Indicators Search facilitates a simple interface for finding IP, File, Hash, Sender and more across your data. Seamless pivots to correlate indicators with Microsoft Sentinel: Incidents to make your threat intelligence actionable.; dataTypesDependencies=System.Object[]; dataConnectorsDependencies=System.Object[]; previewImagesFileNames=System.Object[]; version=5.0.0; title=Threat Intelligence; templateRelativePath=ThreatIntelligence.json; subtitle=; provider=Microsoft}.description", "parentId": "[variables('workbookId1')]", "contentId": "[variables('_workbookContentId1')]", "kind": "Workbook", @@ -1174,7 +417,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "FileEntity_OfficeActivity_HuntingQueries Hunting Query with template version 3.0.1", + "description": "FileEntity_OfficeActivity_HuntingQueries Hunting Query with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('huntingQueryVersion1')]", @@ -1255,7 +498,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "FileEntity_SecurityEvent_HuntingQueries Hunting Query with template version 3.0.1", + "description": "FileEntity_SecurityEvent_HuntingQueries Hunting Query with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('huntingQueryVersion2')]", @@ -1336,7 +579,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "FileEntity_Syslog_HuntingQueries Hunting Query with template version 3.0.1", + "description": "FileEntity_Syslog_HuntingQueries Hunting Query with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('huntingQueryVersion3')]", @@ -1417,7 +660,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "FileEntity_VMConnection_HuntingQueries Hunting Query with template version 3.0.1", + "description": "FileEntity_VMConnection_HuntingQueries Hunting Query with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('huntingQueryVersion4')]", @@ -1498,7 +741,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "FileEntity_WireData_HuntingQueries Hunting Query with template version 3.0.1", + "description": "FileEntity_WireData_HuntingQueries Hunting Query with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('huntingQueryVersion5')]", @@ -1579,7 +822,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "DomainEntity_CommonSecurityLog_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "DomainEntity_CommonSecurityLog_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion1')]", @@ -1596,7 +839,7 @@ "description": "Identifies a match in CommonSecurityLog table from any Domain IOC from TI", "displayName": "TI map Domain entity to CommonSecurityLog", "enabled": false, - "query": "let dt_lookBack = 1h; // Look back 1 hour\nlet ioc_lookBack = 14d; // Look back 14 days\n// Create a list of top-level domains (TLDs) from the threat feed data for later validation\nlet list_tlds =\n ThreatIntelligenceIndicator\n // Filter indicators based on the specified time range and active indicators\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(DomainName)\n // Convert domain names to lowercase for consistency\n | extend DomainName = tolower(DomainName)\n // Split domain names into parts and extract the TLD\n | extend parts = split(DomainName, '.')\n | extend tld = parts[(array_length(parts) - 1)]\n // Count the occurrences of each TLD\n | summarize count() by tostring(tld)\n // Create a list of TLDs\n | summarize make_list(tld);\n// Retrieve threat intelligence indicators within the specified time range\nlet Domain_Indicators =\n ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n // Filter indicators that have a non-empty domain name\n | where isnotempty(DomainName)\n | extend TI_DomainEntity = DomainName;\n// Join threat intelligence indicators with common security logs\nDomain_Indicators\n| join kind=innerunique (\n CommonSecurityLog\n // Filter common security logs based on the specified time range\n | extend IngestionTime = ingestion_time()\n | where IngestionTime > ago(dt_lookBack)\n | where DeviceEventClassID =~ 'url'\n // Uncomment the line below to only alert on allowed connections\n //| where DeviceAction !~ \"block-url\"\n // Extract the domain from RequestURL, if not present, extract it from AdditionalExtensions\n | extend PA_Url = column_ifexists(\"RequestURL\", \"None\")\n | extend PA_Url = iif(isempty(PA_Url) and AdditionalExtensions !startswith \"PanOS\", extract(\"([^\\\\\\\"]+)\", 1, tolower(AdditionalExtensions)), trim('\"', PA_Url))\n | extend PA_Url = iif(PA_Url !startswith \"http://\" and ApplicationProtocol !~ \"ssl\", strcat('http://', PA_Url), iif(PA_Url !startswith \"https://\" and ApplicationProtocol =~ \"ssl\", strcat('https://', PA_Url), PA_Url))\n | extend Domain = trim('\"', tostring(parse_url(PA_Url).Host))\n | where isnotempty(Domain)\n | extend Domain = tolower(Domain)\n | extend parts = split(Domain, '.')\n | extend tld = parts[(array_length(parts) - 1)]\n // Validate parsed domain by checking if the TLD is in the threat feed's TLD list\n | where tld in~ (list_tlds)\n | extend CommonSecurityLog_TimeGenerated = TimeGenerated\n) on $left.TI_DomainEntity == $right.Domain\n| where CommonSecurityLog_TimeGenerated < ExpirationDateTime\n| summarize CommonSecurityLog_TimeGenerated = arg_max(CommonSecurityLog_TimeGenerated, *) by IndicatorId\n| project CommonSecurityLog_TimeGenerated, Description, ActivityGroupNames, PA_Url, Domain, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, DeviceAction, DestinationIP, DestinationPort, DeviceName, SourceIP, SourcePort, ApplicationProtocol, RequestMethod, Type, TI_DomainEntity\n| extend timestamp = CommonSecurityLog_TimeGenerated\n", + "query": "let dt_lookBack = 1h; // Look back 1 hour\nlet ioc_lookBack = 14d; // Look back 14 days\n// Create a list of top-level domains (TLDs) from the threat feed data for later validation\nlet list_tlds =\n ThreatIntelligenceIndicator\n // Filter indicators based on the specified time range and active indicators\n | where TimeGenerated >= ago(ioc_lookBack)\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(DomainName)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n // Convert domain names to lowercase for consistency\n | extend DomainName = tolower(DomainName)\n // Split domain names into parts and extract the TLD\n | extend parts = split(DomainName, '.')\n | extend tld = parts[(array_length(parts) - 1)]\n // Count the occurrences of each TLD\n | summarize count() by tostring(tld)\n // Create a list of TLDs\n | summarize make_list(tld);\n// Retrieve threat intelligence indicators within the specified time range\nlet Domain_Indicators =\n ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | where Active == true and ExpirationDateTime > now()\n // Filter indicators that have a non-empty domain name\n | where isnotempty(DomainName)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | extend TI_DomainEntity = DomainName;\n// Join threat intelligence indicators with common security logs\nDomain_Indicators\n| join kind=innerunique (\n CommonSecurityLog\n // Filter common security logs based on the specified time range\n | extend IngestionTime = ingestion_time()\n | where IngestionTime > ago(dt_lookBack)\n | where DeviceEventClassID =~ 'url'\n // Uncomment the line below to only alert on allowed connections\n //| where DeviceAction !~ \"block-url\"\n // Extract the domain from RequestURL, if not present, extract it from AdditionalExtensions\n | extend PA_Url = column_ifexists(\"RequestURL\", \"None\")\n | extend PA_Url = iif(isempty(PA_Url) and AdditionalExtensions !startswith \"PanOS\", extract(\"([^\\\\\\\"]+)\", 1, tolower(AdditionalExtensions)), trim('\"', PA_Url))\n | extend PA_Url = iif(PA_Url !startswith \"http://\" and ApplicationProtocol !~ \"ssl\", strcat('http://', PA_Url), iif(PA_Url !startswith \"https://\" and ApplicationProtocol =~ \"ssl\", strcat('https://', PA_Url), PA_Url))\n | extend Domain = trim('\"', tostring(parse_url(PA_Url).Host))\n | where isnotempty(Domain)\n | extend Domain = tolower(Domain)\n | extend parts = split(Domain, '.')\n | extend tld = parts[(array_length(parts) - 1)]\n // Validate parsed domain by checking if the TLD is in the threat feed's TLD list\n | where tld in~ (list_tlds)\n | extend CommonSecurityLog_TimeGenerated = TimeGenerated\n) on $left.TI_DomainEntity == $right.Domain\n| where CommonSecurityLog_TimeGenerated < ExpirationDateTime\n| summarize CommonSecurityLog_TimeGenerated = arg_max(CommonSecurityLog_TimeGenerated, *) by IndicatorId\n| project CommonSecurityLog_TimeGenerated, Description, ActivityGroupNames, PA_Url, Domain, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, DeviceAction, DestinationIP, DestinationPort, DeviceName, SourceIP, SourcePort, ApplicationProtocol, RequestMethod, Type, TI_DomainEntity\n| extend timestamp = CommonSecurityLog_TimeGenerated\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -1630,31 +873,31 @@ ], "entityMappings": [ { - "entityType": "Host", "fieldMappings": [ { - "identifier": "HostName", - "columnName": "DeviceName" + "columnName": "DeviceName", + "identifier": "HostName" } - ] + ], + "entityType": "Host" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "SourceIP" + "columnName": "SourceIP", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "PA_Url" + "columnName": "PA_Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -1710,7 +953,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "DomainEntity_DnsEvents_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "DomainEntity_DnsEvents_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion2')]", @@ -1727,7 +970,7 @@ "description": "Identifies a match in DnsEvents from any Domain IOC from TI", "displayName": "TI map Domain entity to DnsEvents", "enabled": false, - "query": "// Define the lookback periods for time-based filters\nlet dt_lookBack = 1h; // Look back 1 hour for DNS events\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to domains\nlet Domain_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n // Filter out indicators without domain names\n | where isnotempty(DomainName)\n | extend TI_DomainEntity = DomainName;\n// Create a list of TLDs in our threat feed for later validation\nlet maxListSize = 100000; // Define the maximum allowed size for each list\nlet list_tlds = Domain_Indicators\n | extend parts = split(DomainName, '.')\n | extend tld = parts[(array_length(parts)-1)]\n | summarize count() by tostring(tld)\n | project tld\n | summarize make_list(tld, maxListSize);\n// Perform a join between domain indicators and DNS events to identify potential malicious activity\nDomain_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n DnsEvents\n | where TimeGenerated > ago(dt_lookBack)\n // Extract domain patterns from syslog message\n | where isnotempty(Name)\n | extend parts = split(Name, '.')\n | extend tld = parts[(array_length(parts)-1)]\n // Validate parsed domain by checking if the TLD is in the list of TLDs in our threat feed\n | where tld in~ (list_tlds)\n | extend DNS_TimeGenerated = TimeGenerated\n ) on $left.TI_DomainEntity==$right.Name\n // Filter out DNS events that occurred after the expiration of the corresponding indicator\n | where DNS_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and Name, and keep the DNS event with the latest timestamp\n | summarize DNS_TimeGenerated = arg_max(DNS_TimeGenerated, *) by IndicatorId, Name\n // Select the desired output fields\n | project DNS_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, Url, Computer, ClientIP, Name, QueryType, Type, TI_DomainEntity\n // Extract hostname and DNS domain from the Computer field\n | extend HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.'))\n // Rename the timestamp field\n | extend timestamp = DNS_TimeGenerated\n", + "query": "// Define the lookback periods for time-based filters\nlet dt_lookBack = 1h; // Look back 1 hour for DNS events\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to domains\nlet Domain_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | where Active == true and ExpirationDateTime > now()\n // Filter out indicators without domain names\n | where isnotempty(DomainName)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | extend TI_DomainEntity = DomainName;\n// Create a list of TLDs in our threat feed for later validation\nlet maxListSize = 100000; // Define the maximum allowed size for each list\nlet list_tlds = Domain_Indicators\n | extend parts = split(DomainName, '.')\n | extend tld = parts[(array_length(parts)-1)]\n | summarize count() by tostring(tld)\n | project tld\n | summarize make_list(tld, maxListSize);\n// Perform a join between domain indicators and DNS events to identify potential malicious activity\nDomain_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n DnsEvents\n | where TimeGenerated > ago(dt_lookBack)\n // Extract domain patterns from syslog message\n | where isnotempty(Name)\n | extend parts = split(Name, '.')\n | extend tld = parts[(array_length(parts)-1)]\n // Validate parsed domain by checking if the TLD is in the list of TLDs in our threat feed\n | where tld in~ (list_tlds)\n | extend DNS_TimeGenerated = TimeGenerated\n ) on $left.TI_DomainEntity==$right.Name\n // Filter out DNS events that occurred after the expiration of the corresponding indicator\n | where DNS_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and Name, and keep the DNS event with the latest timestamp\n | summarize DNS_TimeGenerated = arg_max(DNS_TimeGenerated, *) by IndicatorId, Name\n // Select the desired output fields\n | project DNS_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, Url, Computer, ClientIP, Name, QueryType, Type, TI_DomainEntity\n // Extract hostname and DNS domain from the Computer field\n | extend HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.'))\n // Rename the timestamp field\n | extend timestamp = DNS_TimeGenerated\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -1767,35 +1010,35 @@ ], "entityMappings": [ { - "entityType": "Host", "fieldMappings": [ { - "identifier": "HostName", - "columnName": "HostName" + "columnName": "HostName", + "identifier": "HostName" }, { - "identifier": "DnsDomain", - "columnName": "DnsDomain" + "columnName": "DnsDomain", + "identifier": "DnsDomain" } - ] + ], + "entityType": "Host" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "ClientIP" + "columnName": "ClientIP", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -1851,7 +1094,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "DomainEntity_imWebSession_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "DomainEntity_imWebSession_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion3')]", @@ -1868,7 +1111,7 @@ "description": "This rule identifies Web Sessions for which the target URL hostname is a known IoC.

This rule uses the [Advanced Security Information Model (ASIM)](https:/aka.ms/AboutASIM) and supports any web session source that complies with ASIM.", "displayName": "TI map Domain entity to Web Session Events (ASIM Web Session schema)", "enabled": false, - "query": "let HAS_ANY_MAX = 10000;\nlet dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\n//Create a list of TLDs in our threat feed for later validation\nlet DOMAIN_TI=ThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n| where Active == true\n// Picking up only IOC's that contain the entities we want\n| where isnotempty(DomainName);\nlet DOMAIN_TI_list= todynamic(toscalar(DOMAIN_TI | summarize NIoCs = dcount(DomainName), Domains = make_set(DomainName) \n | project Domains=iff(NIoCs > HAS_ANY_MAX, dynamic([]), Domains) ));\nDOMAIN_TI\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n _Im_WebSession(starttime=ago(dt_lookBack), url_has_any= DOMAIN_TI_list )\n //Extract domain patterns from syslog message\n | extend domain = tostring(parse_url(Url)[\"Host\"])\n | where isnotempty(domain)\n | extend tld = tostring(split(domain, '.')[-1])\n | extend Event_TimeGenerated = TimeGenerated\n) on $left.DomainName==$right.domain\n| where Event_TimeGenerated < ExpirationDateTime\n| summarize Event_TimeGenerated = arg_max(Event_TimeGenerated , *) by IndicatorId, domain\n| project Event_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, domain, SrcIpAddr, Url \n", + "query": "let HAS_ANY_MAX = 10000;\nlet dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\n//Create a list of TLDs in our threat feed for later validation\nlet DOMAIN_TI=ThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| where Active == true\n// Picking up only IOC's that contain the entities we want\n| where isnotempty(DomainName)\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId;\nlet DOMAIN_TI_list= todynamic(toscalar(DOMAIN_TI | summarize NIoCs = dcount(DomainName), Domains = make_set(DomainName) \n | project Domains=iff(NIoCs > HAS_ANY_MAX, dynamic([]), Domains) ));\nDOMAIN_TI\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n _Im_WebSession(starttime=ago(dt_lookBack), url_has_any= DOMAIN_TI_list )\n //Extract domain patterns from syslog message\n | extend domain = tostring(parse_url(Url)[\"Host\"])\n | where isnotempty(domain)\n | extend tld = tostring(split(domain, '.')[-1])\n | extend Event_TimeGenerated = TimeGenerated\n) on $left.DomainName==$right.domain\n| where Event_TimeGenerated < ExpirationDateTime\n| summarize Event_TimeGenerated = arg_max(Event_TimeGenerated , *) by IndicatorId, domain\n| project Event_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, domain, SrcIpAddr, Url \n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -1896,6 +1139,12 @@ "ThreatIntelligenceIndicator" ] }, + { + "connectorId": "ThreatIntelligenceTaxii", + "dataTypes": [ + "ThreatIntelligenceIndicator" + ] + }, { "connectorId": "MicrosoftDefenderThreatIntelligence", "dataTypes": [ @@ -1908,32 +1157,32 @@ ], "entityMappings": [ { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "SrcIpAddr" + "columnName": "SrcIpAddr", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ], "customDetails": { - "IoCExpirationTime": "ExpirationDateTime", - "IndicatorId": "IndicatorId", - "IoCConfidenceScore": "ConfidenceScore", "IoCDescription": "Description", - "EventTime": "Event_TimeGenerated", + "IoCConfidenceScore": "ConfidenceScore", + "ActivityGroupNames": "ActivityGroupNames", + "IndicatorId": "IndicatorId", "ThreatType": "ThreatType", - "ActivityGroupNames": "ActivityGroupNames" + "EventTime": "Event_TimeGenerated", + "IoCExpirationTime": "ExpirationDateTime" }, "alertDetailsOverride": { "alertDisplayNameFormat": "A web request from {{SrcIpAddr}} to hostname {{domain}} matched an IoC", @@ -1992,7 +1241,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "DomainEntity_PaloAlto_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "DomainEntity_PaloAlto_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion4')]", @@ -2009,7 +1258,7 @@ "description": "Identifies a match in Palo Alto data in CommonSecurityLog table from any Domain IOC from TI", "displayName": "TI map Domain entity to PaloAlto", "enabled": false, - "query": "let dt_lookBack = 1h; // Duration to look back for recent logs (1 hour)\nlet ioc_lookBack = 14d; // Duration to look back for recent threat intelligence indicators (14 days)\n// Create a list of top-level domains (TLDs) in our threat feed for later validation of extracted domains\nlet list_tlds = \n ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(DomainName)\n | extend DomainName = tolower(DomainName)\n | extend parts = split(DomainName, '.')\n | extend tld = parts[(array_length(parts)-1)]\n | summarize count() by tostring(tld)\n | summarize make_list(tld);\nlet Domain_Indicators = \n ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n // Filter to pick up only IOC's that contain the entities we want (in this case, DomainName)\n | where isnotempty(DomainName)\n | extend TI_DomainEntity = DomainName;\nDomain_Indicators\n // Join with CommonSecurityLog to find potential malicious activity\n | join kind=innerunique (\n CommonSecurityLog\n | extend IngestionTime = ingestion_time()\n | where IngestionTime > ago(dt_lookBack)\n | where DeviceVendor =~ 'Palo Alto Networks'\n | where DeviceEventClassID =~ 'url'\n // Uncomment the line below to only alert on allowed connections\n // | where DeviceAction !~ \"block-url\"\n // Extract domain from RequestURL, if not present, extract it from AdditionalExtensions\n | extend PA_Url = coalesce(RequestURL, \"None\")\n | extend PA_Url = iif(isempty(PA_Url) and AdditionalExtensions !startswith \"PanOS\", extract(\"([^\\\"]+)\", 1, tolower(AdditionalExtensions)), trim('\"', PA_Url))\n | extend PA_Url = iif(PA_Url !in~ ('None', 'http://None', 'https://None') and PA_Url !startswith \"http://\" and PA_Url !startswith \"https://\" and ApplicationProtocol !~ \"ssl\", strcat('http://', PA_Url), PA_Url)\n | extend PA_Url = iif(PA_Url !in~ ('None', 'http://None', 'https://None') and PA_Url !startswith \"https://\" and ApplicationProtocol =~ \"ssl\", strcat('https://', PA_Url), PA_Url)\n | extend Domain = trim(@\"\"\"\", tostring(parse_url(PA_Url).Host))\n | where isnotempty(Domain)\n | extend Domain = tolower(Domain)\n | extend parts = split(Domain, '.')\n // Split out the top-level domain (TLD) for the purpose of checking if we have any TI indicators with this TLD to match on\n | extend tld = parts[(array_length(parts)-1)]\n // Validate parsed domain by checking TLD against TLDs from the threat feed and drop domains where there is no chance of a match\n | where tld in~ (list_tlds)\n | extend CommonSecurityLog_TimeGenerated = TimeGenerated\n ) on $left.TI_DomainEntity == $right.Domain\n | where CommonSecurityLog_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and Domain and keep only the latest CommonSecurityLog_TimeGenerated\n | summarize CommonSecurityLog_TimeGenerated = arg_max(CommonSecurityLog_TimeGenerated, *) by IndicatorId, Domain\n // Select the desired fields for the final result set\n | project CommonSecurityLog_TimeGenerated, Description, ActivityGroupNames, PA_Url, Domain, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, DeviceAction, DestinationIP, DestinationPort, DeviceName, SourceIP, SourcePort, ApplicationProtocol, RequestMethod, Type, TI_DomainEntity\n // Add a new field 'timestamp' for convenience, using the CommonSecurityLog_TimeGenerated as its value\n | extend timestamp = CommonSecurityLog_TimeGenerated\n", + "query": "let dt_lookBack = 1h; // Duration to look back for recent logs (1 hour)\nlet ioc_lookBack = 14d; // Duration to look back for recent threat intelligence indicators (14 days)\n// Create a list of top-level domains (TLDs) in our threat feed for later validation of extracted domains\nlet list_tlds = \n ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(DomainName)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | extend DomainName = tolower(DomainName)\n | extend parts = split(DomainName, '.')\n | extend tld = parts[(array_length(parts)-1)]\n | summarize count() by tostring(tld)\n | summarize make_list(tld);\nlet Domain_Indicators = \n ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n // Filter to pick up only IOC's that contain the entities we want (in this case, DomainName)\n | where isnotempty(DomainName)\n | extend TI_DomainEntity = DomainName;\nDomain_Indicators\n // Join with CommonSecurityLog to find potential malicious activity\n | join kind=innerunique (\n CommonSecurityLog\n | extend IngestionTime = ingestion_time()\n | where IngestionTime > ago(dt_lookBack)\n | where DeviceVendor =~ 'Palo Alto Networks'\n | where DeviceEventClassID =~ 'url'\n // Uncomment the line below to only alert on allowed connections\n // | where DeviceAction !~ \"block-url\"\n // Extract domain from RequestURL, if not present, extract it from AdditionalExtensions\n | extend PA_Url = coalesce(RequestURL, \"None\")\n | extend PA_Url = iif(isempty(PA_Url) and AdditionalExtensions !startswith \"PanOS\", extract(\"([^\\\"]+)\", 1, tolower(AdditionalExtensions)), trim('\"', PA_Url))\n | extend PA_Url = iif(PA_Url !in~ ('None', 'http://None', 'https://None') and PA_Url !startswith \"http://\" and PA_Url !startswith \"https://\" and ApplicationProtocol !~ \"ssl\", strcat('http://', PA_Url), PA_Url)\n | extend PA_Url = iif(PA_Url !in~ ('None', 'http://None', 'https://None') and PA_Url !startswith \"https://\" and ApplicationProtocol =~ \"ssl\", strcat('https://', PA_Url), PA_Url)\n | extend Domain = trim(@\"\"\"\", tostring(parse_url(PA_Url).Host))\n | where isnotempty(Domain)\n | extend Domain = tolower(Domain)\n | extend parts = split(Domain, '.')\n // Split out the top-level domain (TLD) for the purpose of checking if we have any TI indicators with this TLD to match on\n | extend tld = parts[(array_length(parts)-1)]\n // Validate parsed domain by checking TLD against TLDs from the threat feed and drop domains where there is no chance of a match\n | where tld in~ (list_tlds)\n | extend CommonSecurityLog_TimeGenerated = TimeGenerated\n ) on $left.TI_DomainEntity == $right.Domain\n | where CommonSecurityLog_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and Domain and keep only the latest CommonSecurityLog_TimeGenerated\n | summarize CommonSecurityLog_TimeGenerated = arg_max(CommonSecurityLog_TimeGenerated, *) by IndicatorId, Domain\n // Select the desired fields for the final result set\n | project CommonSecurityLog_TimeGenerated, Description, ActivityGroupNames, PA_Url, Domain, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, DeviceAction, DestinationIP, DestinationPort, DeviceName, SourceIP, SourcePort, ApplicationProtocol, RequestMethod, Type, TI_DomainEntity\n // Add a new field 'timestamp' for convenience, using the CommonSecurityLog_TimeGenerated as its value\n | extend timestamp = CommonSecurityLog_TimeGenerated\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -2049,31 +1298,31 @@ ], "entityMappings": [ { - "entityType": "Host", "fieldMappings": [ { - "identifier": "HostName", - "columnName": "DeviceName" + "columnName": "DeviceName", + "identifier": "HostName" } - ] + ], + "entityType": "Host" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "SourceIP" + "columnName": "SourceIP", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "PA_Url" + "columnName": "PA_Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -2129,7 +1378,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "DomainEntity_SecurityAlert_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "DomainEntity_SecurityAlert_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion5')]", @@ -2146,7 +1395,7 @@ "description": "Identifies a match in SecurityAlert table from any Domain IOC from TI", "displayName": "TI map Domain entity to SecurityAlert", "enabled": false, - "query": "let dt_lookBack = 1h; // Lookback time for recent data, set to 1 hour\nlet ioc_lookBack = 14d; // Lookback time for threat feed data, set to 14 days\n// Create a list of TLDs in our threat feed for later validation\nlet list_tlds = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(DomainName)\n | extend parts = split(DomainName, '.')\n | extend tld = parts[(array_length(parts)-1)]\n | summarize count() by tostring(tld)\n | summarize make_list(tld);\nlet Domain_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n // Picking up only IOC's that contain the entities we want\n | where isnotempty(DomainName)\n | extend TI_DomainEntity = DomainName;\nDomain_Indicators\n // Using innerunique to keep performance fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n | join kind=innerunique (\n SecurityAlert\n | where TimeGenerated > ago(dt_lookBack)\n | extend MSTI = case(AlertName has \"TI map\" and VendorName == \"Microsoft\" and ProductName == 'Azure Sentinel', true, false)\n | where MSTI == false\n // Extract domain patterns from message\n | extend domain = todynamic(dynamic_to_json(extract_all(@\"(((xn--)?[a-z0-9\\-]+\\.)+([a-z]+|(xn--[a-z0-9]+)))\", dynamic([1,1]), tolower(Entities))))\n | mv-expand domain\n | extend domain = tostring(domain[0])\n | extend parts = split(domain, '.')\n // Split out the TLD\n | extend tld = parts[(array_length(parts)-1)]\n // Validate parsed domain by checking if the TLD is in the list of TLDs in our threat feed\n | where tld in~ (list_tlds)\n // Converting Entities into dynamic data type and use mv-expand to unpack the array\n | extend EntitiesDynamicArray = parse_json(Entities)\n | mv-apply EntitiesDynamicArray on\n (summarize\n HostName = take_anyif(tostring(EntitiesDynamicArray.HostName), EntitiesDynamicArray.Type == \"host\"),\n IP_addr = take_anyif(tostring(EntitiesDynamicArray.Address), EntitiesDynamicArray.Type == \"ip\")\n )\n | extend Alert_TimeGenerated = TimeGenerated\n | extend Alert_Description = Description\n ) on $left.TI_DomainEntity == $right.domain\n | where Alert_TimeGenerated < ExpirationDateTime\n | summarize Alert_TimeGenerated = arg_max(Alert_TimeGenerated, *) by IndicatorId, AlertName\n | project Alert_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, DomainName, AlertName, Alert_Description, ProviderName, AlertSeverity, ConfidenceLevel, HostName, IP_addr, Url, Entities, Type, TI_DomainEntity\n | extend timestamp = Alert_TimeGenerated\n", + "query": "let dt_lookBack = 1h; // Lookback time for recent data, set to 1 hour\nlet ioc_lookBack = 14d; // Lookback time for threat feed data, set to 14 days\n// Create a list of TLDs in our threat feed for later validation\nlet list_tlds = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(DomainName)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | extend parts = split(DomainName, '.')\n | extend tld = parts[(array_length(parts)-1)]\n | summarize count() by tostring(tld)\n | summarize make_list(tld);\nlet Domain_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | where Active == true and ExpirationDateTime > now()\n // Picking up only IOC's that contain the entities we want\n | where isnotempty(DomainName)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | extend TI_DomainEntity = DomainName;\nDomain_Indicators\n // Using innerunique to keep performance fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n | join kind=innerunique (\n SecurityAlert\n | where TimeGenerated > ago(dt_lookBack)\n | extend MSTI = case(AlertName has \"TI map\" and VendorName == \"Microsoft\" and ProductName == 'Azure Sentinel', true, false)\n | where MSTI == false\n // Extract domain patterns from message\n | extend domain = todynamic(dynamic_to_json(extract_all(@\"(((xn--)?[a-z0-9\\-]+\\.)+([a-z]+|(xn--[a-z0-9]+)))\", dynamic([1,1]), tolower(Entities))))\n | mv-expand domain\n | extend domain = tostring(domain[0])\n | extend parts = split(domain, '.')\n // Split out the TLD\n | extend tld = parts[(array_length(parts)-1)]\n // Validate parsed domain by checking if the TLD is in the list of TLDs in our threat feed\n | where tld in~ (list_tlds)\n // Converting Entities into dynamic data type and use mv-expand to unpack the array\n | extend EntitiesDynamicArray = parse_json(Entities)\n | mv-apply EntitiesDynamicArray on\n (summarize\n HostName = take_anyif(tostring(EntitiesDynamicArray.HostName), EntitiesDynamicArray.Type == \"host\"),\n IP_addr = take_anyif(tostring(EntitiesDynamicArray.Address), EntitiesDynamicArray.Type == \"ip\")\n )\n | extend Alert_TimeGenerated = TimeGenerated\n | extend Alert_Description = Description\n ) on $left.TI_DomainEntity == $right.domain\n | where Alert_TimeGenerated < ExpirationDateTime\n | summarize Alert_TimeGenerated = arg_max(Alert_TimeGenerated, *) by IndicatorId, AlertName\n | project Alert_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, DomainName, AlertName, Alert_Description, ProviderName, AlertSeverity, ConfidenceLevel, HostName, IP_addr, Url, Entities, Type, TI_DomainEntity\n | extend timestamp = Alert_TimeGenerated\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -2192,31 +1441,31 @@ ], "entityMappings": [ { - "entityType": "Host", "fieldMappings": [ { - "identifier": "HostName", - "columnName": "HostName" + "columnName": "HostName", + "identifier": "HostName" } - ] + ], + "entityType": "Host" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "IP_addr" + "columnName": "IP_addr", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -2272,7 +1521,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "DomainEntity_Syslog_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "DomainEntity_Syslog_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion6')]", @@ -2289,7 +1538,7 @@ "description": "Identifies a match in Syslog table from any Domain IOC from TI", "displayName": "TI map Domain entity to Syslog", "enabled": false, - "query": "let dt_lookBack = 1h; // Define the time range to look back for syslog data (1 hour)\nlet ioc_lookBack = 14d; // Define the time range to look back for threat intelligence indicators (14 days)\n// Create a list of top-level domains (TLDs) from the threat feed for later validation\nlet list_tlds = ThreatIntelligenceIndicator\n | where TimeGenerated > ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(DomainName)\n | extend parts = split(DomainName, '.')\n | extend tld = parts[(array_length(parts)-1)]\n | summarize count() by tostring(tld)\n | summarize make_list(tld);\n// Fetch the latest active domain indicators from the threat intelligence data within the specified time range\nlet Domain_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(DomainName)\n | extend TI_DomainEntity = DomainName;\n// Join the threat intelligence indicators with syslog data on matching domain entities\nDomain_Indicators\n | join kind=innerunique (\n Syslog\n | where TimeGenerated > ago(dt_lookBack)\n // Extract domain patterns from syslog messages\n | extend domain = extract(\"(([a-z0-9]+(-[a-z0-9]+)*\\\\.)+[a-z]{2,})\",1, tolower(SyslogMessage))\n | where isnotempty(domain)\n | extend parts = split(domain, '.')\n // Split out the top-level domain (TLD)\n | extend tld = parts[(array_length(parts)-1)]\n // Validate parsed domain by checking if the TLD is in the list of TLDs in our threat feed\n | where tld in~ (list_tlds)\n | extend Syslog_TimeGenerated = TimeGenerated\n ) on $left.TI_DomainEntity==$right.domain\n | where Syslog_TimeGenerated < ExpirationDateTime\n // Retrieve the latest syslog timestamp for each indicator and domain combination\n | summarize Syslog_TimeGenerated = arg_max(Syslog_TimeGenerated, *) by IndicatorId, domain\n // Select the desired columns for the final result set\n | project Syslog_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, SyslogMessage, Computer, ProcessName, domain, HostIP, Url, Type, TI_DomainEntity\n // Extract the hostname from the Computer field\n | extend HostName = tostring(split(Computer, '.', 0)[0])\n // Extract the DNS domain from the Computer field\n | extend DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.'))\n // Assign the Syslog_TimeGenerated value to the timestamp field\n | extend timestamp = Syslog_TimeGenerated\n", + "query": "let dt_lookBack = 1h; // Define the time range to look back for syslog data (1 hour)\nlet ioc_lookBack = 14d; // Define the time range to look back for threat intelligence indicators (14 days)\n// Create a list of top-level domains (TLDs) from the threat feed for later validation\nlet list_tlds = ThreatIntelligenceIndicator\n | where TimeGenerated > ago(ioc_lookBack)\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(DomainName)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | extend parts = split(DomainName, '.')\n | extend tld = parts[(array_length(parts)-1)]\n | summarize count() by tostring(tld)\n | summarize make_list(tld);\n// Fetch the latest active domain indicators from the threat intelligence data within the specified time range\nlet Domain_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(DomainName)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | extend TI_DomainEntity = DomainName;\n// Join the threat intelligence indicators with syslog data on matching domain entities\nDomain_Indicators\n | join kind=innerunique (\n Syslog\n | where TimeGenerated > ago(dt_lookBack)\n // Extract domain patterns from syslog messages\n | extend domain = extract(\"(([a-z0-9]+(-[a-z0-9]+)*\\\\.)+[a-z]{2,})\",1, tolower(SyslogMessage))\n | where isnotempty(domain)\n | extend parts = split(domain, '.')\n // Split out the top-level domain (TLD)\n | extend tld = parts[(array_length(parts)-1)]\n // Validate parsed domain by checking if the TLD is in the list of TLDs in our threat feed\n | where tld in~ (list_tlds)\n | extend Syslog_TimeGenerated = TimeGenerated\n ) on $left.TI_DomainEntity==$right.domain\n | where Syslog_TimeGenerated < ExpirationDateTime\n // Retrieve the latest syslog timestamp for each indicator and domain combination\n | summarize Syslog_TimeGenerated = arg_max(Syslog_TimeGenerated, *) by IndicatorId, domain\n // Select the desired columns for the final result set\n | project Syslog_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, SyslogMessage, Computer, ProcessName, domain, HostIP, Url, Type, TI_DomainEntity\n // Extract the hostname from the Computer field\n | extend HostName = tostring(split(Computer, '.', 0)[0])\n // Extract the DNS domain from the Computer field\n | extend DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.'))\n // Assign the Syslog_TimeGenerated value to the timestamp field\n | extend timestamp = Syslog_TimeGenerated\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -2329,35 +1578,35 @@ ], "entityMappings": [ { - "entityType": "Host", "fieldMappings": [ { - "identifier": "HostName", - "columnName": "HostName" + "columnName": "HostName", + "identifier": "HostName" }, { - "identifier": "DnsDomain", - "columnName": "DnsDomain" + "columnName": "DnsDomain", + "identifier": "DnsDomain" } - ] + ], + "entityType": "Host" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "HostIP" + "columnName": "HostIP", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -2413,7 +1662,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "EmailEntity_AzureActivity_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "EmailEntity_AzureActivity_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion7')]", @@ -2430,7 +1679,7 @@ "description": "Identifies a match in AzureActivity table from any Email IOC from TI", "displayName": "TI map Email entity to AzureActivity", "enabled": false, - "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$';\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n| where Active == true\n//Filtering the table for Email related IOCs\n| where isnotempty(EmailSenderAddress)\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n AzureActivity | where TimeGenerated >= ago(dt_lookBack) and isnotempty(Caller)\n | extend Caller = tolower(Caller)\n | where Caller matches regex emailregex\n | extend AzureActivity_TimeGenerated = TimeGenerated\n)\non $left.EmailSenderAddress == $right.Caller\n| where AzureActivity_TimeGenerated < ExpirationDateTime\n| summarize AzureActivity_TimeGenerated = arg_max(AzureActivity_TimeGenerated, *) by IndicatorId, Caller\n| project AzureActivity_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, Url, EmailSenderName, EmailRecipient,\nEmailSourceDomain, EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType, Caller, Level, CallerIpAddress, CategoryValue, OperationNameValue, ActivityStatusValue,\nResourceGroup, SubscriptionId\n| extend Name = tostring(split(Caller, '@', 0)[0]), UPNSuffix = tostring(split(Caller, '@', 1)[0])\n| extend timestamp = AzureActivity_TimeGenerated\n", + "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$';\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| where Active == true\n//Filtering the table for Email related IOCs\n| where isnotempty(EmailSenderAddress)\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n AzureActivity | where TimeGenerated >= ago(dt_lookBack) and isnotempty(Caller)\n | extend Caller = tolower(Caller)\n | where Caller matches regex emailregex\n | extend AzureActivity_TimeGenerated = TimeGenerated\n)\non $left.EmailSenderAddress == $right.Caller\n| where AzureActivity_TimeGenerated < ExpirationDateTime\n| summarize AzureActivity_TimeGenerated = arg_max(AzureActivity_TimeGenerated, *) by IndicatorId, Caller\n| project AzureActivity_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, Url, EmailSenderName, EmailRecipient,\nEmailSourceDomain, EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType, Caller, Level, CallerIpAddress, CategoryValue, OperationNameValue, ActivityStatusValue,\nResourceGroup, SubscriptionId\n| extend Name = tostring(split(Caller, '@', 0)[0]), UPNSuffix = tostring(split(Caller, '@', 1)[0])\n| extend timestamp = AzureActivity_TimeGenerated\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -2470,35 +1719,35 @@ ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "identifier": "Name", - "columnName": "Name" + "columnName": "Name", + "identifier": "Name" }, { - "identifier": "UPNSuffix", - "columnName": "UPNSuffix" + "columnName": "UPNSuffix", + "identifier": "UPNSuffix" } - ] + ], + "entityType": "Account" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "CallerIpAddress" + "columnName": "CallerIpAddress", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -2554,7 +1803,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "EmailEntity_OfficeActivity_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "EmailEntity_OfficeActivity_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion8')]", @@ -2571,7 +1820,7 @@ "description": "Identifies a match in OfficeActivity table from any Email IOC from TI", "displayName": "TI map Email entity to OfficeActivity", "enabled": false, - "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$';\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n| where Active == true\n//Filtering the table for Email related IOCs\n| where isnotempty(EmailSenderAddress)\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n OfficeActivity | where TimeGenerated >= ago(dt_lookBack) and isnotempty(UserId)\n | where UserId matches regex emailregex\n | extend OfficeActivity_TimeGenerated = TimeGenerated\n)\non $left.EmailSenderAddress == $right.UserId\n| where OfficeActivity_TimeGenerated < ExpirationDateTime\n| summarize OfficeActivity_TimeGenerated = arg_max(OfficeActivity_TimeGenerated, *) by IndicatorId, UserId\n| project OfficeActivity_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\nEmailSenderName, EmailRecipient, EmailSourceDomain, EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType, UserId, ClientIP, Operation, UserType, RecordType, OfficeWorkload, Parameters\n| extend Name = tostring(split(UserId, '@', 0)[0]), UPNSuffix = tostring(split(UserId, '@', 1)[0])\n| extend timestamp = OfficeActivity_TimeGenerated\n", + "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$';\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| where Active == true\n//Filtering the table for Email related IOCs\n| where isnotempty(EmailSenderAddress)\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n OfficeActivity | where TimeGenerated >= ago(dt_lookBack) and isnotempty(UserId)\n | where UserId matches regex emailregex\n | extend OfficeActivity_TimeGenerated = TimeGenerated\n)\non $left.EmailSenderAddress == $right.UserId\n| where OfficeActivity_TimeGenerated < ExpirationDateTime\n| summarize OfficeActivity_TimeGenerated = arg_max(OfficeActivity_TimeGenerated, *) by IndicatorId, UserId\n| project OfficeActivity_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\nEmailSenderName, EmailRecipient, EmailSourceDomain, EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType, UserId, ClientIP, Operation, UserType, RecordType, OfficeWorkload, Parameters\n| extend Name = tostring(split(UserId, '@', 0)[0]), UPNSuffix = tostring(split(UserId, '@', 1)[0])\n| extend timestamp = OfficeActivity_TimeGenerated\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -2611,35 +1860,35 @@ ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "identifier": "Name", - "columnName": "Name" + "columnName": "Name", + "identifier": "Name" }, { - "identifier": "UPNSuffix", - "columnName": "UPNSuffix" + "columnName": "UPNSuffix", + "identifier": "UPNSuffix" } - ] + ], + "entityType": "Account" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "ClientIP" + "columnName": "ClientIP", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -2695,7 +1944,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "EmailEntity_PaloAlto_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "EmailEntity_PaloAlto_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion9')]", @@ -2712,7 +1961,7 @@ "description": "Identifies a match in CommonSecurityLog table from any Email IOC from TI", "displayName": "TI map Email entity to PaloAlto CommonSecurityLog", "enabled": false, - "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$';\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n| where Active == true\n//Filtering the table for Email related IOCs\n| where isnotempty(EmailSenderAddress)\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n CommonSecurityLog | where TimeGenerated >= ago(dt_lookBack) and isnotempty(DestinationUserID)\n // Filtering PAN Logs for specific event type to match relevant email entities\n | where DeviceVendor == \"Palo Alto Networks\" and DeviceEventClassID == \"wildfire\" and ApplicationProtocol in (\"smtp\",\"pop3\")\n | extend DestinationUserID = tolower(DestinationUserID)\n | where DestinationUserID matches regex emailregex\n | extend CommonSecurityLog_TimeGenerated = TimeGenerated\n)\non $left.EmailSenderAddress == $right.DestinationUserID\n| where CommonSecurityLog_TimeGenerated < ExpirationDateTime\n| summarize CommonSecurityLog_TimeGenerated = arg_max(CommonSecurityLog_TimeGenerated, *) by IndicatorId, DestinationUserID\n| project CommonSecurityLog_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, EmailSenderName, EmailRecipient,\nEmailSourceDomain, EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType, DestinationUserID, DeviceEventClassID, LogSeverity, DeviceAction, SourceIP, SourcePort,\nDestinationIP, DestinationPort, Protocol, ApplicationProtocol\n| extend timestamp = CommonSecurityLog_TimeGenerated\n", + "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$';\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| where Active == true\n//Filtering the table for Email related IOCs\n| where isnotempty(EmailSenderAddress)\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n CommonSecurityLog | where TimeGenerated >= ago(dt_lookBack) and isnotempty(DestinationUserID)\n // Filtering PAN Logs for specific event type to match relevant email entities\n | where DeviceVendor == \"Palo Alto Networks\" and DeviceEventClassID == \"wildfire\" and ApplicationProtocol in (\"smtp\",\"pop3\")\n | extend DestinationUserID = tolower(DestinationUserID)\n | where DestinationUserID matches regex emailregex\n | extend CommonSecurityLog_TimeGenerated = TimeGenerated\n)\non $left.EmailSenderAddress == $right.DestinationUserID\n| where CommonSecurityLog_TimeGenerated < ExpirationDateTime\n| summarize CommonSecurityLog_TimeGenerated = arg_max(CommonSecurityLog_TimeGenerated, *) by IndicatorId, DestinationUserID\n| project CommonSecurityLog_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, EmailSenderName, EmailRecipient,\nEmailSourceDomain, EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType, DestinationUserID, DeviceEventClassID, LogSeverity, DeviceAction, SourceIP, SourcePort,\nDestinationIP, DestinationPort, Protocol, ApplicationProtocol\n| extend timestamp = CommonSecurityLog_TimeGenerated\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -2752,31 +2001,31 @@ ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "identifier": "Name", - "columnName": "DestinationUserID" + "columnName": "DestinationUserID", + "identifier": "Name" } - ] + ], + "entityType": "Account" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "SourceIP" + "columnName": "SourceIP", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -2832,7 +2081,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "EmailEntity_SecurityAlert_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "EmailEntity_SecurityAlert_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion10')]", @@ -2849,7 +2098,7 @@ "description": "Identifies a match in SecurityAlert table from any Email IOC from TI which will extend coverage to datatypes such as MCAS, StorageThreatProtection and many others", "displayName": "TI map Email entity to SecurityAlert", "enabled": false, - "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$';\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n| where Active == true\n//Filtering the table for Email related IOCs\n| where isnotempty(EmailSenderAddress)\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n SecurityAlert\n | where TimeGenerated >= ago(dt_lookBack)\n | extend MSTI = case(AlertName has \"TI map\" and VendorName == \"Microsoft\" and ProductName == 'Azure Sentinel', true, false)\n | where MSTI == false\n // Converting Entities into dynamic data type and use mv-expand to unpack the array\n | extend EntitiesDynamicArray = parse_json(Entities) | mv-expand EntitiesDynamicArray\n // Parsing relevant entity column to filter type account and creating new column by combining account and UPNSuffix\n | extend Entitytype = tostring(parse_json(EntitiesDynamicArray).Type), EntityName = tostring(parse_json(EntitiesDynamicArray).Name),\n EntityUPNSuffix = tostring(parse_json(EntitiesDynamicArray).UPNSuffix)\n | where Entitytype =~ \"account\"\n | extend EntityEmail = tolower(strcat(EntityName, \"@\", EntityUPNSuffix))\n | where EntityEmail matches regex emailregex\n | extend Alert_TimeGenerated = TimeGenerated\n)\non $left.EmailSenderAddress == $right.EntityEmail\n| where Alert_TimeGenerated < ExpirationDateTime\n| summarize Alert_TimeGenerated = arg_max(Alert_TimeGenerated, *) by IndicatorId, AlertName\n| project Alert_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\nEmailSenderName, EmailRecipient, EmailSourceDomain, EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType, EntityEmail, AlertName, AlertType,\nAlertSeverity, Entities, ProviderName, VendorName\n| extend Name = tostring(split(EntityEmail, '@', 0)[0]), UPNSuffix = tostring(split(EntityEmail, '@', 1)[0])\n| extend timestamp = Alert_TimeGenerated\n", + "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$';\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| where Active == true\n//Filtering the table for Email related IOCs\n| where isnotempty(EmailSenderAddress)\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n SecurityAlert\n | where TimeGenerated >= ago(dt_lookBack)\n | extend MSTI = case(AlertName has \"TI map\" and VendorName == \"Microsoft\" and ProductName == 'Azure Sentinel', true, false)\n | where MSTI == false\n // Converting Entities into dynamic data type and use mv-expand to unpack the array\n | extend EntitiesDynamicArray = parse_json(Entities) | mv-expand EntitiesDynamicArray\n // Parsing relevant entity column to filter type account and creating new column by combining account and UPNSuffix\n | extend Entitytype = tostring(parse_json(EntitiesDynamicArray).Type), EntityName = tostring(parse_json(EntitiesDynamicArray).Name),\n EntityUPNSuffix = tostring(parse_json(EntitiesDynamicArray).UPNSuffix)\n | where Entitytype =~ \"account\"\n | extend EntityEmail = tolower(strcat(EntityName, \"@\", EntityUPNSuffix))\n | where EntityEmail matches regex emailregex\n | extend Alert_TimeGenerated = TimeGenerated\n)\non $left.EmailSenderAddress == $right.EntityEmail\n| where Alert_TimeGenerated < ExpirationDateTime\n| summarize Alert_TimeGenerated = arg_max(Alert_TimeGenerated, *) by IndicatorId, AlertName\n| project Alert_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\nEmailSenderName, EmailRecipient, EmailSourceDomain, EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType, EntityEmail, AlertName, AlertType,\nAlertSeverity, Entities, ProviderName, VendorName\n| extend Name = tostring(split(EntityEmail, '@', 0)[0]), UPNSuffix = tostring(split(EntityEmail, '@', 1)[0])\n| extend timestamp = Alert_TimeGenerated\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -2889,26 +2138,26 @@ ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "identifier": "Name", - "columnName": "Name" + "columnName": "Name", + "identifier": "Name" }, { - "identifier": "UPNSuffix", - "columnName": "UPNSuffix" + "columnName": "UPNSuffix", + "identifier": "UPNSuffix" } - ] + ], + "entityType": "Account" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -2964,7 +2213,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "EmailEntity_SecurityEvent_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "EmailEntity_SecurityEvent_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion11')]", @@ -2981,7 +2230,7 @@ "description": "Identifies a match in SecurityEvent table from any Email IOC from TI", "displayName": "TI map Email entity to SecurityEvent", "enabled": false, - "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$';\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n| where Active == true\n//Filtering the table for Email related IOCs\n| where isnotempty(EmailSenderAddress)\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n(union isfuzzy=true\n(SecurityEvent\n| where TimeGenerated >= ago(dt_lookBack) and isnotempty(TargetUserName)\n//Normalizing the column to lower case for exact match with EmailSenderAddress column\n| extend TargetUserName = tolower(TargetUserName)\n// renaming timestamp column so it is clear the log this came from SecurityEvent table\n| extend SecurityEvent_TimeGenerated = TimeGenerated\n),\n(WindowsEvent\n| where TimeGenerated >= ago(dt_lookBack)\n| extend TargetUserName = tostring(EventData.TargetUserName)\n| where isnotempty(TargetUserName)\n//Normalizing the column to lower case for exact match with EmailSenderAddress column\n| extend TargetUserName = tolower(TargetUserName)\n// renaming timestamp column so it is clear the log this came from SecurityEvent table\n| extend SecurityEvent_TimeGenerated = TimeGenerated\n))\n)\non $left.EmailSenderAddress == $right.TargetUserName\n| where SecurityEvent_TimeGenerated < ExpirationDateTime\n| summarize SecurityEvent_TimeGenerated = arg_max(SecurityEvent_TimeGenerated, *) by IndicatorId, TargetUserName\n| project SecurityEvent_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\nEmailSenderName, EmailRecipient, EmailSourceDomain, EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType, Computer, EventID, TargetUserName, Activity, IpAddress, AccountType,\nLogonTypeName, LogonProcessName, Status, SubStatus\n| extend HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.'))\n| extend timestamp = SecurityEvent_TimeGenerated\n", + "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$';\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| where Active == true\n//Filtering the table for Email related IOCs\n| where isnotempty(EmailSenderAddress)\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n(union isfuzzy=true\n(SecurityEvent\n| where TimeGenerated >= ago(dt_lookBack) and isnotempty(TargetUserName)\n//Normalizing the column to lower case for exact match with EmailSenderAddress column\n| extend TargetUserName = tolower(TargetUserName)\n// renaming timestamp column so it is clear the log this came from SecurityEvent table\n| extend SecurityEvent_TimeGenerated = TimeGenerated\n),\n(WindowsEvent\n| where TimeGenerated >= ago(dt_lookBack)\n| extend TargetUserName = tostring(EventData.TargetUserName)\n| where isnotempty(TargetUserName)\n//Normalizing the column to lower case for exact match with EmailSenderAddress column\n| extend TargetUserName = tolower(TargetUserName)\n// renaming timestamp column so it is clear the log this came from SecurityEvent table\n| extend SecurityEvent_TimeGenerated = TimeGenerated\n))\n)\non $left.EmailSenderAddress == $right.TargetUserName\n| where SecurityEvent_TimeGenerated < ExpirationDateTime\n| summarize SecurityEvent_TimeGenerated = arg_max(SecurityEvent_TimeGenerated, *) by IndicatorId, TargetUserName\n| project SecurityEvent_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\nEmailSenderName, EmailRecipient, EmailSourceDomain, EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType, Computer, EventID, TargetUserName, Activity, IpAddress, AccountType,\nLogonTypeName, LogonProcessName, Status, SubStatus\n| extend HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.'))\n| extend timestamp = SecurityEvent_TimeGenerated\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -3033,44 +2282,44 @@ ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "identifier": "Name", - "columnName": "TargetUserName" + "columnName": "TargetUserName", + "identifier": "Name" } - ] + ], + "entityType": "Account" }, { - "entityType": "Host", "fieldMappings": [ { - "identifier": "HostName", - "columnName": "HostName" + "columnName": "HostName", + "identifier": "HostName" }, { - "identifier": "DnsDomain", - "columnName": "DnsDomain" + "columnName": "DnsDomain", + "identifier": "DnsDomain" } - ] + ], + "entityType": "Host" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "IpAddress" + "columnName": "IpAddress", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -3126,7 +2375,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "EmailEntity_SigninLogs_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "EmailEntity_SigninLogs_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion12')]", @@ -3143,7 +2392,7 @@ "description": "Identifies a match in SigninLogs table from any Email IOC from TI", "displayName": "TI map Email entity to SigninLogs", "enabled": false, - "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$';\nlet aadFunc = (tableName:string){\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n| where Active == true\n//Filtering the table for Email related IOCs\n| where isnotempty(EmailSenderAddress)\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n table(tableName) | where TimeGenerated >= ago(dt_lookBack) and isnotempty(UserPrincipalName)\n //Normalizing the column to lower case for exact match with EmailSenderAddress column\n | extend UserPrincipalName = tolower(UserPrincipalName)\n | where UserPrincipalName matches regex emailregex\n | extend Status = todynamic(DeviceDetail), LocationDetails = todynamic(LocationDetails)\n | extend StatusCode = tostring(Status.errorCode), StatusDetails = tostring(Status.additionalDetails)\n | extend State = tostring(LocationDetails.state), City = tostring(LocationDetails.city), Region = tostring(LocationDetails.countryOrRegion)\n // renaming timestamp column so it is clear the log this came from SigninLogs table\n | extend SigninLogs_TimeGenerated = TimeGenerated, Type = Type\n)\non $left.EmailSenderAddress == $right.UserPrincipalName\n| where SigninLogs_TimeGenerated < ExpirationDateTime\n| summarize SigninLogs_TimeGenerated = arg_max(SigninLogs_TimeGenerated, *) by IndicatorId, UserPrincipalName\n| project SigninLogs_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\nEmailSenderName, EmailRecipient, EmailSourceDomain, EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType, IPAddress, UserPrincipalName, AppDisplayName,\nStatusCode, StatusDetails, NetworkIP, NetworkDestinationIP, NetworkSourceIP, Type\n| extend Name = tostring(split(UserPrincipalName, '@', 0)[0]), UPNSuffix = tostring(split(UserPrincipalName, '@', 1)[0])\n| extend timestamp = SigninLogs_TimeGenerated\n};\nlet aadSignin = aadFunc(\"SigninLogs\");\nlet aadNonInt = aadFunc(\"AADNonInteractiveUserSignInLogs\");\nunion isfuzzy=true aadSignin, aadNonInt\n", + "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet emailregex = @'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$';\nlet aadFunc = (tableName:string){\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| where Active == true\n//Filtering the table for Email related IOCs\n| where isnotempty(EmailSenderAddress)\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n table(tableName) | where TimeGenerated >= ago(dt_lookBack) and isnotempty(UserPrincipalName)\n //Normalizing the column to lower case for exact match with EmailSenderAddress column\n | extend UserPrincipalName = tolower(UserPrincipalName)\n | where UserPrincipalName matches regex emailregex\n | extend Status = todynamic(DeviceDetail), LocationDetails = todynamic(LocationDetails)\n | extend StatusCode = tostring(Status.errorCode), StatusDetails = tostring(Status.additionalDetails)\n | extend State = tostring(LocationDetails.state), City = tostring(LocationDetails.city), Region = tostring(LocationDetails.countryOrRegion)\n // renaming timestamp column so it is clear the log this came from SigninLogs table\n | extend SigninLogs_TimeGenerated = TimeGenerated, Type = Type\n)\non $left.EmailSenderAddress == $right.UserPrincipalName\n| where SigninLogs_TimeGenerated < ExpirationDateTime\n| summarize SigninLogs_TimeGenerated = arg_max(SigninLogs_TimeGenerated, *) by IndicatorId, UserPrincipalName\n| project SigninLogs_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\nEmailSenderName, EmailRecipient, EmailSourceDomain, EmailSourceIpAddress, EmailSubject, FileHashValue, FileHashType, IPAddress, UserPrincipalName, AppDisplayName,\nStatusCode, StatusDetails, NetworkIP, NetworkDestinationIP, NetworkSourceIP, Type\n| extend Name = tostring(split(UserPrincipalName, '@', 0)[0]), UPNSuffix = tostring(split(UserPrincipalName, '@', 1)[0])\n| extend timestamp = SigninLogs_TimeGenerated\n};\nlet aadSignin = aadFunc(\"SigninLogs\");\nlet aadNonInt = aadFunc(\"AADNonInteractiveUserSignInLogs\");\nunion isfuzzy=true aadSignin, aadNonInt\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -3189,35 +2438,35 @@ ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "identifier": "Name", - "columnName": "Name" + "columnName": "Name", + "identifier": "Name" }, { - "identifier": "UPNSuffix", - "columnName": "UPNSuffix" + "columnName": "UPNSuffix", + "identifier": "UPNSuffix" } - ] + ], + "entityType": "Account" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "IPAddress" + "columnName": "IPAddress", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -3273,7 +2522,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "FileHashEntity_CommonSecurityLog_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "FileHashEntity_CommonSecurityLog_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion13')]", @@ -3290,7 +2539,7 @@ "description": "Identifies a match in CommonSecurityLog Event data from any FileHash IOC from TI", "displayName": "TI map File Hash to CommonSecurityLog Event", "enabled": false, - "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet fileHashIndicators = ThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n| where Active == true\n| where isnotempty(FileHashValue);\n// Handle matches against both lower case and uppercase versions of the hash:\n(fileHashIndicators | extend FileHashValue = tolower(FileHashValue)\n| union (fileHashIndicators | extend FileHashValue = toupper(FileHashValue)))\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n CommonSecurityLog | where TimeGenerated >= ago(dt_lookBack)\n | where isnotempty(FileHash)\n | extend CommonSecurityLog_TimeGenerated = TimeGenerated\n )\non $left.FileHashValue == $right.FileHash\n| where CommonSecurityLog_TimeGenerated < ExpirationDateTime\n| summarize CommonSecurityLog_TimeGenerated = arg_max(CommonSecurityLog_TimeGenerated, *) by IndicatorId, FileHashValue\n| project CommonSecurityLog_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\nSourceIP, SourcePort, DestinationIP, DestinationPort, SourceUserID, SourceUserName, DeviceName, DeviceAction,\nRequestURL, DestinationUserName, DestinationUserID, ApplicationProtocol, Activity, FileHashValue, FileHashType\n| extend HostName = tostring(split(DeviceName, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(DeviceName, '.'), 1, -1), '.'))\n| extend Name = tostring(split(SourceUserName, '@', 0)[0]), UPNSuffix = tostring(split(SourceUserName, '@', 1)[0])\n| extend timestamp = CommonSecurityLog_TimeGenerated\n", + "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet fileHashIndicators = ThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| where Active == true\n| where isnotempty(FileHashValue)\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId;\n// Handle matches against both lower case and uppercase versions of the hash:\n(fileHashIndicators | extend FileHashValue = tolower(FileHashValue)\n| union (fileHashIndicators | extend FileHashValue = toupper(FileHashValue)))\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n CommonSecurityLog | where TimeGenerated >= ago(dt_lookBack)\n | where isnotempty(FileHash)\n | extend CommonSecurityLog_TimeGenerated = TimeGenerated\n )\non $left.FileHashValue == $right.FileHash\n| where CommonSecurityLog_TimeGenerated < ExpirationDateTime\n| summarize CommonSecurityLog_TimeGenerated = arg_max(CommonSecurityLog_TimeGenerated, *) by IndicatorId, FileHashValue\n| project CommonSecurityLog_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\nSourceIP, SourcePort, DestinationIP, DestinationPort, SourceUserID, SourceUserName, DeviceName, DeviceAction,\nRequestURL, DestinationUserName, DestinationUserID, ApplicationProtocol, Activity, FileHashValue, FileHashType\n| extend HostName = tostring(split(DeviceName, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(DeviceName, '.'), 1, -1), '.'))\n| extend Name = tostring(split(SourceUserName, '@', 0)[0]), UPNSuffix = tostring(split(SourceUserName, '@', 1)[0])\n| extend timestamp = CommonSecurityLog_TimeGenerated\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -3330,61 +2579,61 @@ ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "identifier": "Name", - "columnName": "Name" + "columnName": "Name", + "identifier": "Name" }, { - "identifier": "UPNSuffix", - "columnName": "UPNSuffix" + "columnName": "UPNSuffix", + "identifier": "UPNSuffix" } - ] + ], + "entityType": "Account" }, { - "entityType": "Host", "fieldMappings": [ { - "identifier": "HostName", - "columnName": "HostName" + "columnName": "HostName", + "identifier": "HostName" }, { - "identifier": "DnsDomain", - "columnName": "DnsDomain" + "columnName": "DnsDomain", + "identifier": "DnsDomain" } - ] + ], + "entityType": "Host" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "SourceIP" + "columnName": "SourceIP", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" }, { - "entityType": "FileHash", "fieldMappings": [ { - "identifier": "Value", - "columnName": "FileHashValue" + "columnName": "FileHashValue", + "identifier": "Value" }, { - "identifier": "Algorithm", - "columnName": "FileHashType" + "columnName": "FileHashType", + "identifier": "Algorithm" } - ] + ], + "entityType": "FileHash" } ] } @@ -3440,7 +2689,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "FileHashEntity_SecurityEvent_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "FileHashEntity_SecurityEvent_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion14')]", @@ -3457,7 +2706,7 @@ "description": "Identifies a match in Security Event data from any File Hash IOC from TI", "displayName": "TI map File Hash to Security Event", "enabled": false, - "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n| where Active == true\n| where isnotempty(FileHashValue)\n| extend FileHashValue = toupper(FileHashValue)\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique ( union isfuzzy=true\n (SecurityEvent | where TimeGenerated >= ago(dt_lookBack)\n | where EventID in (\"8003\",\"8002\",\"8005\")\n | where isnotempty(FileHash)\n | extend SecurityEvent_TimeGenerated = TimeGenerated, Event = EventID, FileHash = toupper(FileHash)\n ),\n (WindowsEvent | where TimeGenerated >= ago(dt_lookBack)\n | where EventID in (\"8003\",\"8002\",\"8005\")\n | where isnotempty(EventData.FileHash)\n | extend SecurityEvent_TimeGenerated = TimeGenerated, Event = EventID, FileHash = toupper(EventData.FileHash)\n )\n)\non $left.FileHashValue == $right.FileHash\n| where SecurityEvent_TimeGenerated < ExpirationDateTime\n| summarize SecurityEvent_TimeGenerated = arg_max(SecurityEvent_TimeGenerated, *) by IndicatorId, FileHash\n| project SecurityEvent_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\nProcess, FileHash, Computer, Account, Event, FileHashValue, FileHashType\n| extend NTDomain = tostring(split(Account, '\\\\', 0)[0]), Name = tostring(split(Account, '\\\\', 1)[0])\n| extend HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.')) \n| extend timestamp = SecurityEvent_TimeGenerated\n", + "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| where Active == true\n| where isnotempty(FileHashValue)\n| extend FileHashValue = toupper(FileHashValue)\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique ( union isfuzzy=true\n (SecurityEvent | where TimeGenerated >= ago(dt_lookBack)\n | where EventID in (\"8003\",\"8002\",\"8005\")\n | where isnotempty(FileHash)\n | extend SecurityEvent_TimeGenerated = TimeGenerated, Event = EventID, FileHash = toupper(FileHash)\n ),\n (WindowsEvent | where TimeGenerated >= ago(dt_lookBack)\n | where EventID in (\"8003\",\"8002\",\"8005\")\n | where isnotempty(EventData.FileHash)\n | extend SecurityEvent_TimeGenerated = TimeGenerated, Event = EventID, FileHash = toupper(EventData.FileHash)\n )\n)\non $left.FileHashValue == $right.FileHash\n| where SecurityEvent_TimeGenerated < ExpirationDateTime\n| summarize SecurityEvent_TimeGenerated = arg_max(SecurityEvent_TimeGenerated, *) by IndicatorId, FileHash\n| project SecurityEvent_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\nProcess, FileHash, Computer, Account, Event, FileHashValue, FileHashType\n| extend NTDomain = tostring(split(Account, '\\\\', 0)[0]), Name = tostring(split(Account, '\\\\', 1)[0])\n| extend HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.')) \n| extend timestamp = SecurityEvent_TimeGenerated\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -3509,52 +2758,52 @@ ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "identifier": "Name", - "columnName": "Name" + "columnName": "Name", + "identifier": "Name" }, { - "identifier": "NTDomain", - "columnName": "NTDomain" + "columnName": "NTDomain", + "identifier": "NTDomain" } - ] + ], + "entityType": "Account" }, { - "entityType": "Host", "fieldMappings": [ { - "identifier": "HostName", - "columnName": "HostName" + "columnName": "HostName", + "identifier": "HostName" }, { - "identifier": "DnsDomain", - "columnName": "DnsDomain" + "columnName": "DnsDomain", + "identifier": "DnsDomain" } - ] + ], + "entityType": "Host" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" }, { - "entityType": "FileHash", "fieldMappings": [ { - "identifier": "Value", - "columnName": "FileHashValue" + "columnName": "FileHashValue", + "identifier": "Value" }, { - "identifier": "Algorithm", - "columnName": "FileHashType" + "columnName": "FileHashType", + "identifier": "Algorithm" } - ] + ], + "entityType": "FileHash" } ] } @@ -3610,7 +2859,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "IPEntity_AppServiceHTTPLogs_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "IPEntity_AppServiceHTTPLogs_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion15')]", @@ -3627,7 +2876,7 @@ "description": "Identifies a match in AppServiceHTTPLogs from any IP IOC from TI", "displayName": "TI map IP entity to AppServiceHTTPLogs", "enabled": false, - "query": "let dt_lookBack = 1h; // Look back 1 hour for AppServiceHTTPLogs\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n // Filter out indicators without relevant IP address fields\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n // Select the IP entity based on availability of different IP fields\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n // Exclude local addresses using the ipv4_is_private operator and filtering out specific address prefixes\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\";\n// Perform a join between IP indicators and AppServiceHTTPLogs to identify potential malicious activity\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n AppServiceHTTPLogs | where TimeGenerated >= ago(dt_lookBack)\n | where isnotempty(CIp)\n | extend WebApp = split(_ResourceId, '/')[8]\n | extend AppService_TimeGenerated = TimeGenerated // Rename time column for clarity\n )\n on $left.TI_ipEntity == $right.CIp\n // Filter out logs that occurred after the expiration of the corresponding indicator\n | where AppService_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and CIp, and keep the log entry with the latest timestamp\n | summarize AppService_TimeGenerated = arg_max(AppService_TimeGenerated, *) by IndicatorId, CIp\n // Select the desired output fields\n | project AppService_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, TI_ipEntity, CsUsername, WebApp = split(_ResourceId, '/')[8], CIp, CsHost, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, _ResourceId, Type\n // Extract hostname and DNS domain from the CsHost field\n | extend HostName = tostring(split(CsHost, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(CsHost, '.'), 1, -1), '.'))\n // Rename the timestamp field\n | extend timestamp = AppService_TimeGenerated\n", + "query": "let dt_lookBack = 1h; // Look back 1 hour for AppServiceHTTPLogs\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | where Active == true and ExpirationDateTime > now()\n // Filter out indicators without relevant IP address fields\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n // Select the IP entity based on availability of different IP fields\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n // Exclude local addresses using the ipv4_is_private operator and filtering out specific address prefixes\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\"\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId;\n// Perform a join between IP indicators and AppServiceHTTPLogs to identify potential malicious activity\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n AppServiceHTTPLogs | where TimeGenerated >= ago(dt_lookBack)\n | where isnotempty(CIp)\n | extend WebApp = split(_ResourceId, '/')[8]\n | extend AppService_TimeGenerated = TimeGenerated // Rename time column for clarity\n )\n on $left.TI_ipEntity == $right.CIp\n // Filter out logs that occurred after the expiration of the corresponding indicator\n | where AppService_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and CIp, and keep the log entry with the latest timestamp\n | summarize AppService_TimeGenerated = arg_max(AppService_TimeGenerated, *) by IndicatorId, CIp\n // Select the desired output fields\n | project AppService_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, TI_ipEntity, CsUsername, WebApp = split(_ResourceId, '/')[8], CIp, CsHost, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, _ResourceId, Type\n // Extract hostname and DNS domain from the CsHost field\n | extend HostName = tostring(split(CsHost, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(CsHost, '.'), 1, -1), '.'))\n // Rename the timestamp field\n | extend timestamp = AppService_TimeGenerated\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -3661,53 +2910,53 @@ ], "entityMappings": [ { - "entityType": "Host", "fieldMappings": [ { - "identifier": "HostName", - "columnName": "HostName" + "columnName": "HostName", + "identifier": "HostName" }, { - "identifier": "DnsDomain", - "columnName": "DnsDomain" + "columnName": "DnsDomain", + "identifier": "DnsDomain" } - ] + ], + "entityType": "Host" }, { - "entityType": "Account", "fieldMappings": [ { - "identifier": "Name", - "columnName": "CsUsername" + "columnName": "CsUsername", + "identifier": "Name" } - ] + ], + "entityType": "Account" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "CIp" + "columnName": "CIp", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" }, { - "entityType": "AzureResource", "fieldMappings": [ { - "identifier": "ResourceId", - "columnName": "_ResourceId" + "columnName": "_ResourceId", + "identifier": "ResourceId" } - ] + ], + "entityType": "AzureResource" } ] } @@ -3763,7 +3012,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "IPEntity_AWSCloudTrail_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "IPEntity_AWSCloudTrail_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion16')]", @@ -3780,7 +3029,7 @@ "description": "Identifies a match in AWSCloudTrail from any IP IOC from TI", "displayName": "TI map IP entity to AWSCloudTrail", "enabled": false, - "query": "let dt_lookBack = 1h; // Look back 1 hour for AWSCloudTrail logs\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n // Filter out indicators without relevant IP address fields\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n // Select the IP entity based on availability of different IP fields\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n // Exclude local addresses using the ipv4_is_private operator and filtering out specific address prefixes\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\";\n// Perform a join between IP indicators and AWSCloudTrail logs to identify potential malicious activity\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n AWSCloudTrail\n | where TimeGenerated >= ago(dt_lookBack)\n | extend AWSCloudTrail_TimeGenerated = TimeGenerated // Rename time column for clarity\n )\n on $left.TI_ipEntity == $right.SourceIpAddress\n // Filter out logs that occurred after the expiration of the corresponding indicator\n | where AWSCloudTrail_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and SourceIpAddress, and keep the log entry with the latest timestamp\n | summarize AWSCloudTrail_TimeGenerated = arg_max(AWSCloudTrail_TimeGenerated, *) by IndicatorId, SourceIpAddress\n // Select the desired output fields\n | project AWSCloudTrail_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\n TI_ipEntity, EventName, EventTypeName, UserIdentityAccountId, UserIdentityPrincipalid, UserIdentityUserName, SourceIpAddress,\n NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type\n // Rename the timestamp field\n | extend timestamp = AWSCloudTrail_TimeGenerated\n", + "query": "let dt_lookBack = 1h; // Look back 1 hour for AWSCloudTrail logs\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | where Active == true and ExpirationDateTime > now()\n // Filter out indicators without relevant IP address fields\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n // Select the IP entity based on availability of different IP fields\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n // Exclude local addresses using the ipv4_is_private operator and filtering out specific address prefixes\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\"\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId;\n// Perform a join between IP indicators and AWSCloudTrail logs to identify potential malicious activity\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n AWSCloudTrail\n | where TimeGenerated >= ago(dt_lookBack)\n | extend AWSCloudTrail_TimeGenerated = TimeGenerated // Rename time column for clarity\n )\n on $left.TI_ipEntity == $right.SourceIpAddress\n // Filter out logs that occurred after the expiration of the corresponding indicator\n | where AWSCloudTrail_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and SourceIpAddress, and keep the log entry with the latest timestamp\n | summarize AWSCloudTrail_TimeGenerated = arg_max(AWSCloudTrail_TimeGenerated, *) by IndicatorId, SourceIpAddress\n // Select the desired output fields\n | project AWSCloudTrail_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\n TI_ipEntity, EventName, EventTypeName, UserIdentityAccountId, UserIdentityPrincipalid, UserIdentityUserName, SourceIpAddress,\n NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type\n // Rename the timestamp field\n | extend timestamp = AWSCloudTrail_TimeGenerated\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -3820,31 +3069,31 @@ ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "identifier": "ObjectGuid", - "columnName": "UserIdentityUserName" + "columnName": "UserIdentityUserName", + "identifier": "ObjectGuid" } - ] + ], + "entityType": "Account" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "SourceIpAddress" + "columnName": "SourceIpAddress", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -3900,7 +3149,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "IPEntity_AzureActivity_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "IPEntity_AzureActivity_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion17')]", @@ -3917,7 +3166,7 @@ "description": "This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in AzureActivity.", "displayName": "TI Map IP Entity to AzureActivity", "enabled": false, - "query": "let dt_lookBack = 1h; // Look back 1 hour for AzureActivity logs\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n // Filter out indicators without relevant IP address fields\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n // Select the IP entity based on availability of different IP fields\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n // Exclude local addresses using the ipv4_is_private operator and filtering out specific address prefixes\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\";\n// Perform a join between IP indicators and AzureActivity logs to identify potential malicious activity\nIP_Indicators\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n AzureActivity | where TimeGenerated >= ago(dt_lookBack)\n // renaming time column so it is clear the log this came from\n | extend AzureActivity_TimeGenerated = TimeGenerated\n)\non $left.TI_ipEntity == $right.CallerIpAddress\n| where AzureActivity_TimeGenerated < ExpirationDateTime\n| summarize AzureActivity_TimeGenerated = arg_max(AzureActivity_TimeGenerated, *) by IndicatorId, CallerIpAddress\n| project AzureActivity_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, TI_ipEntity, CallerIpAddress, \nCaller, OperationNameValue, ActivityStatusValue, CategoryValue, ResourceId, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type\n| extend timestamp = AzureActivity_TimeGenerated\n| extend Name = iif(Caller has '@', tostring(split(Caller,'@',0)[0]), \"\")\n| extend UPNSuffix = iif(Caller has '@', tostring(split(Caller,'@',1)[0]), \"\")\n| extend AadUserId = iif(Caller !has '@', tostring(Caller), \"\")\n", + "query": "let dt_lookBack = 1h; // Look back 1 hour for AzureActivity logs\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | where Active == true and ExpirationDateTime > now()\n // Filter out indicators without relevant IP address fields\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n // Select the IP entity based on availability of different IP fields\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n // Exclude local addresses using the ipv4_is_private operator and filtering out specific address prefixes\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\"\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId;\n// Perform a join between IP indicators and AzureActivity logs to identify potential malicious activity\nIP_Indicators\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n AzureActivity | where TimeGenerated >= ago(dt_lookBack)\n // renaming time column so it is clear the log this came from\n | extend AzureActivity_TimeGenerated = TimeGenerated\n)\non $left.TI_ipEntity == $right.CallerIpAddress\n| where AzureActivity_TimeGenerated < ExpirationDateTime\n| summarize AzureActivity_TimeGenerated = arg_max(AzureActivity_TimeGenerated, *) by IndicatorId, CallerIpAddress\n| project AzureActivity_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, TI_ipEntity, CallerIpAddress, \nCaller, OperationNameValue, ActivityStatusValue, CategoryValue, ResourceId, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type\n| extend timestamp = AzureActivity_TimeGenerated\n| extend Name = iif(Caller has '@', tostring(split(Caller,'@',0)[0]), \"\")\n| extend UPNSuffix = iif(Caller has '@', tostring(split(Caller,'@',1)[0]), \"\")\n| extend AadUserId = iif(Caller !has '@', tostring(Caller), \"\")\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -3957,48 +3206,48 @@ ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "identifier": "Name", - "columnName": "Name" + "columnName": "Name", + "identifier": "Name" }, { - "identifier": "UPNSuffix", - "columnName": "UPNSuffix" + "columnName": "UPNSuffix", + "identifier": "UPNSuffix" }, { - "identifier": "AadUserId", - "columnName": "AadUserId" + "columnName": "AadUserId", + "identifier": "AadUserId" } - ] + ], + "entityType": "Account" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "CallerIpAddress" + "columnName": "CallerIpAddress", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" }, { - "entityType": "AzureResource", "fieldMappings": [ { - "identifier": "ResourceId", - "columnName": "ResourceId" + "columnName": "ResourceId", + "identifier": "ResourceId" } - ] + ], + "entityType": "AzureResource" } ] } @@ -4054,7 +3303,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "IPEntity_AzureFirewall_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "IPEntity_AzureFirewall_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion18')]", @@ -4071,7 +3320,7 @@ "description": "Identifies a match in AzureFirewall (NetworkRule & ApplicationRule Logs) from any IP IOC from TI", "displayName": "TI map IP entity to AzureFirewall", "enabled": false, - "query": "let dt_lookBack = 1h; // Look back 1 hour for AzureDiagnostics logs\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n // Filter out indicators without relevant IP address fields\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n // Select the IP entity based on availability of different IP fields\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n // Exclude local addresses using the ipv4_is_private operator and filtering out specific address prefixes\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\";\n// Perform a join between IP indicators and AzureDiagnostics logs to identify potential malicious activity\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n AzureDiagnostics\n | where TimeGenerated >= ago(dt_lookBack)\n | where OperationName in (\"AzureFirewallApplicationRuleLog\", \"AzureFirewallNetworkRuleLog\")\n | parse kind=regex flags=U msg_s with Protocol 'request from ' SourceHost 'to ' DestinationHost @'\\.? Action: ' Firewall_Action @'\\.' Rest_msg\n | extend SourceAddress = extract(@'([\\.0-9]+)(:[\\.0-9]+)?', 1, SourceHost)\n | extend DestinationAddress = extract(@'([\\.0-9]+)(:[\\.0-9]+)?', 1, DestinationHost)\n | extend RemoteIP = case(not(ipv4_is_private(DestinationAddress)), DestinationAddress, not(ipv4_is_private(SourceAddress)), SourceAddress, \"\")\n | where isnotempty(RemoteIP) // Filter out traffic involving public addresses only\n | project-rename AzureFirewall_TimeGenerated = TimeGenerated\n )\n on $left.TI_ipEntity == $right.RemoteIP\n // Filter out logs that occurred after the expiration of the corresponding indicator\n | where AzureFirewall_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and RemoteIP, and keep the log entry with the latest timestamp\n | summarize AzureFirewall_TimeGenerated = arg_max(AzureFirewall_TimeGenerated, *) by IndicatorId, RemoteIP\n // Select the desired output fields\n | project LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, DomainName, ExpirationDateTime, ConfidenceScore,\n AzureFirewall_TimeGenerated, TI_ipEntity, Resource, Category, msg_s, SourceAddress, DestinationAddress, Firewall_Action, Protocol,\n NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type\n // Rename the timestamp field\n | extend timestamp = AzureFirewall_TimeGenerated\n", + "query": "let dt_lookBack = 1h; // Look back 1 hour for AzureDiagnostics logs\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | where Active == true and ExpirationDateTime > now()\n // Filter out indicators without relevant IP address fields\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n // Select the IP entity based on availability of different IP fields\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n // Exclude local addresses using the ipv4_is_private operator and filtering out specific address prefixes\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\"\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId;\n// Perform a join between IP indicators and AzureDiagnostics logs to identify potential malicious activity\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n AzureDiagnostics\n | where TimeGenerated >= ago(dt_lookBack)\n | where OperationName in (\"AzureFirewallApplicationRuleLog\", \"AzureFirewallNetworkRuleLog\")\n | parse kind=regex flags=U msg_s with Protocol 'request from ' SourceHost 'to ' DestinationHost @'\\.? Action: ' Firewall_Action @'\\.' Rest_msg\n | extend SourceAddress = extract(@'([\\.0-9]+)(:[\\.0-9]+)?', 1, SourceHost)\n | extend DestinationAddress = extract(@'([\\.0-9]+)(:[\\.0-9]+)?', 1, DestinationHost)\n | extend RemoteIP = case(not(ipv4_is_private(DestinationAddress)), DestinationAddress, not(ipv4_is_private(SourceAddress)), SourceAddress, \"\")\n | where isnotempty(RemoteIP) // Filter out traffic involving public addresses only\n | project-rename AzureFirewall_TimeGenerated = TimeGenerated\n )\n on $left.TI_ipEntity == $right.RemoteIP\n // Filter out logs that occurred after the expiration of the corresponding indicator\n | where AzureFirewall_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and RemoteIP, and keep the log entry with the latest timestamp\n | summarize AzureFirewall_TimeGenerated = arg_max(AzureFirewall_TimeGenerated, *) by IndicatorId, RemoteIP\n // Select the desired output fields\n | project LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, DomainName, ExpirationDateTime, ConfidenceScore,\n AzureFirewall_TimeGenerated, TI_ipEntity, Resource, Category, msg_s, SourceAddress, DestinationAddress, Firewall_Action, Protocol,\n NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type\n // Rename the timestamp field\n | extend timestamp = AzureFirewall_TimeGenerated\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -4111,22 +3360,22 @@ ], "entityMappings": [ { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "TI_ipEntity" + "columnName": "TI_ipEntity", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -4182,7 +3431,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "IPEntity_AzureKeyVault_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "IPEntity_AzureKeyVault_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion19')]", @@ -4199,7 +3448,7 @@ "description": "Identifies a match in Azure Key Vault logs from any IP IOC from TI", "displayName": "TI map IP entity to Azure Key Vault logs", "enabled": false, - "query": "let dt_lookBack = 1h; // Look back 1 hour for AzureDiagnostics logs\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n | where LatestIndicatorTime >= ago(ioc_lookBack) and ExpirationDateTime > now()\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\";\n// Perform a join between IP indicators and AzureDiagnostics logs for Key Vault events\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n AzureDiagnostics\n | where ResourceType =~ \"VAULTS\"\n | where TimeGenerated >= ago(dt_lookBack)\n | extend KeyVaultEvents_TimeGenerated = TimeGenerated, ClientIP = CallerIPAddress\n )\n on $left.TI_ipEntity == $right.ClientIP\n // Filter out logs that occurred after the expiration of the corresponding indicator\n | where KeyVaultEvents_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and ClientIP, and keep the log entry with the latest timestamp\n | summarize KeyVaultEvents_TimeGenerated = arg_max(KeyVaultEvents_TimeGenerated, *) by IndicatorId, ClientIP\n // Select the desired output fields\n | project KeyVaultEvents_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\n TI_ipEntity, ClientIP, ResourceId, SubscriptionId, OperationName, ResultType, CorrelationId, id_s, clientInfo_s, httpStatusCode_d,\n identity_claim_appid_g, identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g, Type\n // Rename the timestamp field\n | extend timestamp = KeyVaultEvents_TimeGenerated\n", + "query": "let dt_lookBack = 1h; // Look back 1 hour for AzureDiagnostics logs\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where Active == true\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n | where LatestIndicatorTime >= ago(ioc_lookBack) and ExpirationDateTime > now()\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\"\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId;\n// Perform a join between IP indicators and AzureDiagnostics logs for Key Vault events\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n AzureDiagnostics\n | where ResourceType =~ \"VAULTS\"\n | where TimeGenerated >= ago(dt_lookBack)\n | extend KeyVaultEvents_TimeGenerated = TimeGenerated, ClientIP = CallerIPAddress\n )\n on $left.TI_ipEntity == $right.ClientIP\n // Filter out logs that occurred after the expiration of the corresponding indicator\n | where KeyVaultEvents_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and ClientIP, and keep the log entry with the latest timestamp\n | summarize KeyVaultEvents_TimeGenerated = arg_max(KeyVaultEvents_TimeGenerated, *) by IndicatorId, ClientIP\n // Select the desired output fields\n | project KeyVaultEvents_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\n TI_ipEntity, ClientIP, ResourceId, SubscriptionId, OperationName, ResultType, CorrelationId, id_s, clientInfo_s, httpStatusCode_d,\n identity_claim_appid_g, identity_claim_http_schemas_microsoft_com_identity_claims_objectidentifier_g, Type\n // Rename the timestamp field\n | extend timestamp = KeyVaultEvents_TimeGenerated\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -4239,22 +3488,22 @@ ], "entityMappings": [ { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "ClientIP" + "columnName": "ClientIP", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "AzureResource", "fieldMappings": [ { - "identifier": "ResourceId", - "columnName": "ResourceId" + "columnName": "ResourceId", + "identifier": "ResourceId" } - ] + ], + "entityType": "AzureResource" } ] } @@ -4310,7 +3559,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "IPEntity_AzureNetworkAnalytics_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "IPEntity_AzureNetworkAnalytics_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion20')]", @@ -4327,7 +3576,7 @@ "description": "Identifies a match in AzureNetworkAnalytics_CL (NSG Flow Logs) from any IP IOC from TI that was Allowed", "displayName": "TI map IP entity to AzureNetworkAnalytics_CL (NSG Flow Logs)", "enabled": false, - "query": "let dt_lookBack = 1h; // Look back 1 hour for AzureNetworkAnalytics_CL logs\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\";\n// Perform a join between IP indicators and AzureNetworkAnalytics_CL logs for NSG Flow information\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n AzureNetworkAnalytics_CL\n | where TimeGenerated >= ago(dt_lookBack)\n | extend AzureNetworkAnalytics_CL_TimeGenerated = TimeGenerated\n | extend PIPs = split(PublicIPs_s, '|', 0)\n | extend PIP = tostring(PIPs[0])\n )\n on $left.TI_ipEntity == $right.PIP\n // Filter out logs that occurred after the expiration of the corresponding indicator\n | where AzureNetworkAnalytics_CL_TimeGenerated < ExpirationDateTime\n // Filter out NSG Flow logs that are not allowed (FlowStatus_s == \"A\")\n | where FlowStatus_s == \"A\"\n // Group the results by IndicatorId and PIP (Public IP), and keep the log entry with the latest timestamp\n | summarize AzureNetworkAnalytics_CL_TimeGenerated = arg_max(AzureNetworkAnalytics_CL_TimeGenerated, *) by IndicatorId, PIP\n // Select the desired output fields\n | project AzureNetworkAnalytics_CL_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\n TI_ipEntity, Computer, FlowDirection_s, FlowStatus_s, FlowType_s, SrcPublicIPs_s, DestPublicIPs_s, PublicIPs_s, L7Protocol_s, DestPort_d, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type\n // Extract hostname and DNS domain from the Computer field\n | extend HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.'))\n // Rename the timestamp field\n | extend timestamp = AzureNetworkAnalytics_CL_TimeGenerated\n", + "query": "let dt_lookBack = 1h; // Look back 1 hour for AzureNetworkAnalytics_CL logs\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\"\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId;\n// Perform a join between IP indicators and AzureNetworkAnalytics_CL logs for NSG Flow information\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n AzureNetworkAnalytics_CL\n | where TimeGenerated >= ago(dt_lookBack)\n | extend AzureNetworkAnalytics_CL_TimeGenerated = TimeGenerated\n | extend PIPs = split(PublicIPs_s, '|', 0)\n | extend PIP = tostring(PIPs[0])\n )\n on $left.TI_ipEntity == $right.PIP\n // Filter out logs that occurred after the expiration of the corresponding indicator\n | where AzureNetworkAnalytics_CL_TimeGenerated < ExpirationDateTime\n // Filter out NSG Flow logs that are not allowed (FlowStatus_s == \"A\")\n | where FlowStatus_s == \"A\"\n // Group the results by IndicatorId and PIP (Public IP), and keep the log entry with the latest timestamp\n | summarize AzureNetworkAnalytics_CL_TimeGenerated = arg_max(AzureNetworkAnalytics_CL_TimeGenerated, *) by IndicatorId, PIP\n // Select the desired output fields\n | project AzureNetworkAnalytics_CL_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\n TI_ipEntity, Computer, FlowDirection_s, FlowStatus_s, FlowType_s, SrcPublicIPs_s, DestPublicIPs_s, PublicIPs_s, L7Protocol_s, DestPort_d, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type\n // Extract hostname and DNS domain from the Computer field\n | extend HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.'))\n // Rename the timestamp field\n | extend timestamp = AzureNetworkAnalytics_CL_TimeGenerated\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -4361,35 +3610,35 @@ ], "entityMappings": [ { - "entityType": "Host", "fieldMappings": [ { - "identifier": "HostName", - "columnName": "HostName" + "columnName": "HostName", + "identifier": "HostName" }, { - "identifier": "DnsDomain", - "columnName": "DnsDomain" + "columnName": "DnsDomain", + "identifier": "DnsDomain" } - ] + ], + "entityType": "Host" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "TI_ipEntity" + "columnName": "TI_ipEntity", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -4445,7 +3694,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "IPEntity_AzureSQL_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "IPEntity_AzureSQL_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion21')]", @@ -4462,7 +3711,7 @@ "description": "This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in SQL Security Audit Events.", "displayName": "TI Map IP Entity to Azure SQL Security Audit Events", "enabled": false, - "query": "let dt_lookBack = 1h; // Look back 1 hour for AzureDiagnostics logs\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\";\n// Perform a join between IP indicators and AzureDiagnostics logs for SQL Security Audit events\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n AzureDiagnostics\n | where TimeGenerated >= ago(dt_lookBack)\n | where ResourceProvider == 'MICROSOFT.SQL'\n | where Category == 'SQLSecurityAuditEvents'\n | extend SQLSecurityAuditEvents_TimeGenerated = TimeGenerated\n | extend ClientIP = column_ifexists(\"client_ip_s\", \"Not Available\")\n | extend Action = column_ifexists(\"action_name_s\", \"Not Available\")\n | extend Application = column_ifexists(\"application_name_s\", \"Not Available\")\n | extend HostName = column_ifexists(\"host_name_s\", \"Not Available\")\n )\n on $left.TI_ipEntity == $right.ClientIP\n // Filter out logs that occurred after the expiration of the corresponding indicator\n | where SQLSecurityAuditEvents_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and ClientIP, and keep the log entry with the latest timestamp\n | summarize SQLSecurityAuditEvents_TimeGenerated = arg_max(SQLSecurityAuditEvents_TimeGenerated, *) by IndicatorId, ClientIP\n // Select the desired output fields\n | project SQLSecurityAuditEvents_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\n TI_ipEntity, ResourceId, ClientIP, Action, Application, HostName, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type\n // Rename the timestamp field\n | extend timestamp = SQLSecurityAuditEvents_TimeGenerated\n", + "query": "let dt_lookBack = 1h; // Look back 1 hour for AzureDiagnostics logs\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\"\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId;\n// Perform a join between IP indicators and AzureDiagnostics logs for SQL Security Audit events\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n AzureDiagnostics\n | where TimeGenerated >= ago(dt_lookBack)\n | where ResourceProvider == 'MICROSOFT.SQL'\n | where Category == 'SQLSecurityAuditEvents'\n | extend SQLSecurityAuditEvents_TimeGenerated = TimeGenerated\n | extend ClientIP = column_ifexists(\"client_ip_s\", \"Not Available\")\n | extend Action = column_ifexists(\"action_name_s\", \"Not Available\")\n | extend Application = column_ifexists(\"application_name_s\", \"Not Available\")\n | extend HostName = column_ifexists(\"host_name_s\", \"Not Available\")\n )\n on $left.TI_ipEntity == $right.ClientIP\n // Filter out logs that occurred after the expiration of the corresponding indicator\n | where SQLSecurityAuditEvents_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and ClientIP, and keep the log entry with the latest timestamp\n | summarize SQLSecurityAuditEvents_TimeGenerated = arg_max(SQLSecurityAuditEvents_TimeGenerated, *) by IndicatorId, ClientIP\n // Select the desired output fields\n | project SQLSecurityAuditEvents_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\n TI_ipEntity, ResourceId, ClientIP, Action, Application, HostName, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type\n // Rename the timestamp field\n | extend timestamp = SQLSecurityAuditEvents_TimeGenerated\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -4502,13 +3751,13 @@ ], "entityMappings": [ { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "ClientIP" + "columnName": "ClientIP", + "identifier": "Address" } - ] + ], + "entityType": "IP" } ] } @@ -4564,7 +3813,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "IPEntity_CustomSecurityLog_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "IPEntity_CustomSecurityLog_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion22')]", @@ -4581,7 +3830,7 @@ "description": "This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in CommonSecurityLog.", "displayName": "TI Map IP Entity to CommonSecurityLog", "enabled": false, - "query": "let IPRegex = '[0-9]{1,3}\\\\.[0-9]{1,3}\\\\.[0-9]{1,3}\\\\.[0-9]{1,3}';\nlet dt_lookBack = 1h; // Look back 1 hour for CommonSecurityLog events\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\";\n// Perform a join between IP indicators and CommonSecurityLog events\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n CommonSecurityLog\n | where TimeGenerated >= ago(dt_lookBack)\n | extend MessageIP = extract(IPRegex, 0, Message)\n | extend CS_ipEntity = iff(isnotempty(SourceIP), SourceIP, DestinationIP)\n | extend CS_ipEntity = iff(isempty(CS_ipEntity) and isnotempty(MessageIP), MessageIP, CS_ipEntity)\n | extend CommonSecurityLog_TimeGenerated = TimeGenerated\n )\n on $left.TI_ipEntity == $right.CS_ipEntity\n // Filter out logs that occurred after the expiration of the corresponding indicator\n | where CommonSecurityLog_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and CS_ipEntity, and keep the log entry with the latest timestamp\n | summarize CommonSecurityLog_TimeGenerated = arg_max(CommonSecurityLog_TimeGenerated, *) by IndicatorId, CS_ipEntity\n // Select the desired output fields\n | project timestamp = CommonSecurityLog_TimeGenerated, SourceIP, DestinationIP, MessageIP, Message, DeviceVendor, DeviceProduct, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, TI_ipEntity, CS_ipEntity, LogSeverity, DeviceAction, Type\n", + "query": "let IPRegex = '[0-9]{1,3}\\\\.[0-9]{1,3}\\\\.[0-9]{1,3}\\\\.[0-9]{1,3}';\nlet dt_lookBack = 1h; // Look back 1 hour for CommonSecurityLog events\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\"\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId;\n// Perform a join between IP indicators and CommonSecurityLog events\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n CommonSecurityLog\n | where TimeGenerated >= ago(dt_lookBack)\n | extend MessageIP = extract(IPRegex, 0, Message)\n | extend CS_ipEntity = iff(isnotempty(SourceIP), SourceIP, DestinationIP)\n | extend CS_ipEntity = iff(isempty(CS_ipEntity) and isnotempty(MessageIP), MessageIP, CS_ipEntity)\n | extend CommonSecurityLog_TimeGenerated = TimeGenerated\n )\n on $left.TI_ipEntity == $right.CS_ipEntity\n // Filter out logs that occurred after the expiration of the corresponding indicator\n | where CommonSecurityLog_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and CS_ipEntity, and keep the log entry with the latest timestamp\n | summarize CommonSecurityLog_TimeGenerated = arg_max(CommonSecurityLog_TimeGenerated, *) by IndicatorId, CS_ipEntity\n // Select the desired output fields\n | project timestamp = CommonSecurityLog_TimeGenerated, SourceIP, DestinationIP, MessageIP, Message, DeviceVendor, DeviceProduct, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, TI_ipEntity, CS_ipEntity, LogSeverity, DeviceAction, Type\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -4621,13 +3870,13 @@ ], "entityMappings": [ { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "CS_ipEntity" + "columnName": "CS_ipEntity", + "identifier": "Address" } - ] + ], + "entityType": "IP" } ] } @@ -4683,7 +3932,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "IPEntity_DnsEvents_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "IPEntity_DnsEvents_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion23')]", @@ -4700,7 +3949,7 @@ "description": "This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in DnsEvents.", "displayName": "TI Map IP Entity to DnsEvents", "enabled": false, - "query": "let dt_lookBack = 1h; // Look back 1 hour for DNS events\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\";\n// Perform a join between IP indicators and DNS events\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n DnsEvents\n | where TimeGenerated >= ago(dt_lookBack)\n | where SubType =~ \"LookupQuery\" and isnotempty(IPAddresses)\n | mv-expand SingleIP = split(IPAddresses, \", \") to typeof(string)\n | extend DNS_TimeGenerated = TimeGenerated\n )\n on $left.TI_ipEntity == $right.SingleIP\n // Filter out DNS events that occurred after the expiration of the corresponding indicator\n | where DNS_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and SingleIP, and keep the DNS event with the latest timestamp\n | summarize DNS_TimeGenerated = arg_max(DNS_TimeGenerated, *) by IndicatorId, SingleIP\n // Select the desired output fields\n | project DNS_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, DomainName, ExpirationDateTime, ConfidenceScore,\n TI_ipEntity, Computer, EventId, SubType, ClientIP, Name, IPAddresses, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type\n | extend timestamp = DNS_TimeGenerated, HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.'))\n", + "query": "let dt_lookBack = 1h; // Look back 1 hour for DNS events\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\"\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId;\n// Perform a join between IP indicators and DNS events\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n DnsEvents\n | where TimeGenerated >= ago(dt_lookBack)\n | where SubType =~ \"LookupQuery\" and isnotempty(IPAddresses)\n | mv-expand SingleIP = split(IPAddresses, \", \") to typeof(string)\n | extend DNS_TimeGenerated = TimeGenerated\n )\n on $left.TI_ipEntity == $right.SingleIP\n // Filter out DNS events that occurred after the expiration of the corresponding indicator\n | where DNS_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and SingleIP, and keep the DNS event with the latest timestamp\n | summarize DNS_TimeGenerated = arg_max(DNS_TimeGenerated, *) by IndicatorId, SingleIP\n // Select the desired output fields\n | project DNS_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, DomainName, ExpirationDateTime, ConfidenceScore,\n TI_ipEntity, Computer, EventId, SubType, ClientIP, Name, IPAddresses, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type\n | extend timestamp = DNS_TimeGenerated, HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.'))\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -4740,35 +3989,35 @@ ], "entityMappings": [ { - "entityType": "Host", "fieldMappings": [ { - "identifier": "HostName", - "columnName": "HostName" + "columnName": "HostName", + "identifier": "HostName" }, { - "identifier": "DnsDomain", - "columnName": "DnsDomain" + "columnName": "DnsDomain", + "identifier": "DnsDomain" } - ] + ], + "entityType": "Host" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "ClientIP" + "columnName": "ClientIP", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -4824,7 +4073,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "IPEntity_imWebSession_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "IPEntity_imWebSession_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion24')]", @@ -4841,7 +4090,7 @@ "description": "This rule identifies Web Sessions for which the source IP address is a known IoC.

This rule uses the [Advanced Security Information Model (ASIM)](https://aka.ms/AboutASIM) and supports any web session source that complies with ASIM.", "displayName": "TI map IP entity to Web Session Events (ASIM Web Session schema)", "enabled": false, - "query": "let HAS_ANY_MAX = 10000;\nlet dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet IP_TI = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n // As there is potentially more than 1 indicator type for matching IP, taking NetworkIP first, then others if that is empty.\n // Taking the first non-empty value based on potential IOC match availability\n | extend TI_ipEntity = coalesce(NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, \"NO_IP\")\n // Picking up only IOC's that contain the entities we want\n | where TI_ipEntity != \"NO_IP\"\n // Exclude local addresses, using the ipv4_is_private operator\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\";\nlet IP_TI_list = toscalar(IP_TI\n | summarize NIoCs = dcount(TI_ipEntity), IoCs = make_set(TI_ipEntity)\n | project IoCs = iff(NIoCs > HAS_ANY_MAX, dynamic([]), IoCs));\nIP_TI\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind = innerunique (\n _Im_WebSession (starttime = ago(dt_lookBack), srcipaddr_has_any_prefix = IP_TI_list)\n | where isnotempty(SrcIpAddr)\n // renaming time column so it is clear the log this came from\n | extend imNWS_TimeGenerated = TimeGenerated\n )\n on $left.TI_ipEntity == $right.SrcIpAddr\n| where imNWS_TimeGenerated < ExpirationDateTime\n| summarize imNWS_TimeGenerated = arg_max(imNWS_TimeGenerated, *) by IndicatorId, DstIpAddr\n| project imNWS_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore,\n TI_ipEntity, Dvc, SrcIpAddr, DstIpAddr, Url, Type\n", + "query": "let HAS_ANY_MAX = 10000;\nlet dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet IP_TI = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | where Active == true and ExpirationDateTime > now()\n // As there is potentially more than 1 indicator type for matching IP, taking NetworkIP first, then others if that is empty.\n // Taking the first non-empty value based on potential IOC match availability\n | extend TI_ipEntity = coalesce(NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, \"NO_IP\")\n // Picking up only IOC's that contain the entities we want\n | where TI_ipEntity != \"NO_IP\"\n // Exclude local addresses, using the ipv4_is_private operator\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\"\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId;\nlet IP_TI_list = toscalar(IP_TI\n | summarize NIoCs = dcount(TI_ipEntity), IoCs = make_set(TI_ipEntity)\n | project IoCs = iff(NIoCs > HAS_ANY_MAX, dynamic([]), IoCs));\nIP_TI\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind = innerunique (\n _Im_WebSession (starttime = ago(dt_lookBack), srcipaddr_has_any_prefix = IP_TI_list)\n | where isnotempty(SrcIpAddr)\n // renaming time column so it is clear the log this came from\n | extend imNWS_TimeGenerated = TimeGenerated\n )\n on $left.TI_ipEntity == $right.SrcIpAddr\n| where imNWS_TimeGenerated < ExpirationDateTime\n| summarize imNWS_TimeGenerated = arg_max(imNWS_TimeGenerated, *) by IndicatorId, DstIpAddr\n| project imNWS_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore,\n TI_ipEntity, Dvc, SrcIpAddr, DstIpAddr, Url, Type\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -4887,23 +4136,23 @@ ], "entityMappings": [ { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "DstIpAddr" + "columnName": "DstIpAddr", + "identifier": "Address" } - ] + ], + "entityType": "IP" } ], "customDetails": { - "IoCExpirationTime": "ExpirationDateTime", - "IndicatorId": "IndicatorId", - "IoCConfidenceScore": "ConfidenceScore", "IoCDescription": "Description", - "EventTime": "imNWS_TimeGenerated", + "IoCConfidenceScore": "ConfidenceScore", + "ActivityGroupNames": "ActivityGroupNames", + "IndicatorId": "IndicatorId", "ThreatType": "ThreatType", - "ActivityGroupNames": "ActivityGroupNames" + "EventTime": "imNWS_TimeGenerated", + "IoCExpirationTime": "ExpirationDateTime" }, "alertDetailsOverride": { "alertDisplayNameFormat": "The IP {{SrcIpAddr}} of the web request matches an IP IoC", @@ -4962,7 +4211,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "IPEntity_OfficeActivity_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "IPEntity_OfficeActivity_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion25')]", @@ -4979,7 +4228,7 @@ "description": "This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in OfficeActivity.", "displayName": "TI map IP entity to OfficeActivity", "enabled": false, - "query": "let dt_lookBack = 1h; // Look back 1 hour for OfficeActivity events\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\";\n// Perform a join between IP indicators and OfficeActivity events\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n OfficeActivity\n | where TimeGenerated >= ago(dt_lookBack)\n | where isnotempty(ClientIP)\n | extend ClientIPValues = extract_all(@'\\[?(::ffff:)?(?P(\\d+\\.\\d+\\.\\d+\\.\\d+)|[^\\]%]+)(%\\d+)?\\]?([-:](?P\\d+))?', dynamic([\"IPAddress\", \"Port\"]), ClientIP)[0]\n | extend IPAddress = iff(array_length(ClientIPValues) > 0, tostring(ClientIPValues[0]), '')\n | extend OfficeActivity_TimeGenerated = TimeGenerated\n )\n on $left.TI_ipEntity == $right.IPAddress\n // Filter out OfficeActivity events that occurred after the expiration of the corresponding indicator\n | where OfficeActivity_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and keep the OfficeActivity event with the latest timestamp\n | summarize OfficeActivity_TimeGenerated = arg_max(OfficeActivity_TimeGenerated, *) by IndicatorId\n // Select the desired output fields\n | project OfficeActivity_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\n TI_ipEntity, ClientIP, UserId, Operation, ResultStatus, RecordType, OfficeObjectId, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type\n | extend timestamp = OfficeActivity_TimeGenerated, Name = tostring(split(UserId, '@', 0)[0]), UPNSuffix = tostring(split(UserId, '@', 1)[0])\n", + "query": "let dt_lookBack = 1h; // Look back 1 hour for OfficeActivity events\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\"\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId;\n// Perform a join between IP indicators and OfficeActivity events\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n OfficeActivity\n | where TimeGenerated >= ago(dt_lookBack)\n | where isnotempty(ClientIP)\n | extend ClientIPValues = extract_all(@'\\[?(::ffff:)?(?P(\\d+\\.\\d+\\.\\d+\\.\\d+)|[^\\]%]+)(%\\d+)?\\]?([-:](?P\\d+))?', dynamic([\"IPAddress\", \"Port\"]), ClientIP)[0]\n | extend IPAddress = iff(array_length(ClientIPValues) > 0, tostring(ClientIPValues[0]), '')\n | extend OfficeActivity_TimeGenerated = TimeGenerated\n )\n on $left.TI_ipEntity == $right.IPAddress\n // Filter out OfficeActivity events that occurred after the expiration of the corresponding indicator\n | where OfficeActivity_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and keep the OfficeActivity event with the latest timestamp\n | summarize OfficeActivity_TimeGenerated = arg_max(OfficeActivity_TimeGenerated, *) by IndicatorId\n // Select the desired output fields\n | project OfficeActivity_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\n TI_ipEntity, ClientIP, UserId, Operation, ResultStatus, RecordType, OfficeObjectId, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type\n | extend timestamp = OfficeActivity_TimeGenerated, Name = tostring(split(UserId, '@', 0)[0]), UPNSuffix = tostring(split(UserId, '@', 1)[0])\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -5019,35 +4268,35 @@ ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "identifier": "Name", - "columnName": "Name" + "columnName": "Name", + "identifier": "Name" }, { - "identifier": "UPNSuffix", - "columnName": "UPNSuffix" + "columnName": "UPNSuffix", + "identifier": "UPNSuffix" } - ] + ], + "entityType": "Account" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "TI_ipEntity" + "columnName": "TI_ipEntity", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -5103,7 +4352,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "IPEntity_SigninLogs_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "IPEntity_SigninLogs_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion26')]", @@ -5120,7 +4369,7 @@ "description": "This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in SigninLogs.", "displayName": "TI Map IP Entity to SigninLogs", "enabled": false, - "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet aadFunc = (tableName:string){\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n| where Active == true\n// Picking up only IOC's that contain the entities we want\n| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n// As there is potentially more than 1 indicator type for matching IP, taking NetworkIP first, then others if that is empty.\n// Taking the first non-empty value based on potential IOC match availability\n| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n table(tableName) | where TimeGenerated >= ago(dt_lookBack)\n | extend Status = todynamic(Status), LocationDetails = todynamic(LocationDetails)\n | extend StatusCode = tostring(Status.errorCode), StatusDetails = tostring(Status.additionalDetails), StatusReason = tostring(Status.failureReason)\n | extend State = tostring(LocationDetails.state), City = tostring(LocationDetails.city), Region = tostring(LocationDetails.countryOrRegion)\n // renaming time column so it is clear the log this came from\n | extend SigninLogs_TimeGenerated = TimeGenerated, Type = Type\n)\non $left.TI_ipEntity == $right.IPAddress\n| where SigninLogs_TimeGenerated < ExpirationDateTime\n| summarize SigninLogs_TimeGenerated = arg_max(SigninLogs_TimeGenerated, *) by IndicatorId, IPAddress\n| project SigninLogs_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\nTI_ipEntity, IPAddress, UserPrincipalName, AppDisplayName, StatusCode, StatusDetails, StatusReason, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type\n| extend timestamp = SigninLogs_TimeGenerated, Name = tostring(split(UserPrincipalName, '@', 0)[0]), UPNSuffix = tostring(split(UserPrincipalName, '@', 1)[0])\n};\nlet aadSignin = aadFunc(\"SigninLogs\");\nlet aadNonInt = aadFunc(\"AADNonInteractiveUserSignInLogs\");\nunion isfuzzy=true aadSignin, aadNonInt\n", + "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet aadFunc = (tableName:string){\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| where Active == true\n// Picking up only IOC's that contain the entities we want\n| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n// As there is potentially more than 1 indicator type for matching IP, taking NetworkIP first, then others if that is empty.\n// Taking the first non-empty value based on potential IOC match availability\n| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n table(tableName) | where TimeGenerated >= ago(dt_lookBack)\n | extend Status = todynamic(Status), LocationDetails = todynamic(LocationDetails)\n | extend StatusCode = tostring(Status.errorCode), StatusDetails = tostring(Status.additionalDetails), StatusReason = tostring(Status.failureReason)\n | extend State = tostring(LocationDetails.state), City = tostring(LocationDetails.city), Region = tostring(LocationDetails.countryOrRegion)\n // renaming time column so it is clear the log this came from\n | extend SigninLogs_TimeGenerated = TimeGenerated, Type = Type\n)\non $left.TI_ipEntity == $right.IPAddress\n| where SigninLogs_TimeGenerated < ExpirationDateTime\n| summarize SigninLogs_TimeGenerated = arg_max(SigninLogs_TimeGenerated, *) by IndicatorId, IPAddress\n| project SigninLogs_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\nTI_ipEntity, IPAddress, UserPrincipalName, AppDisplayName, StatusCode, StatusDetails, StatusReason, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type\n| extend timestamp = SigninLogs_TimeGenerated, Name = tostring(split(UserPrincipalName, '@', 0)[0]), UPNSuffix = tostring(split(UserPrincipalName, '@', 1)[0])\n};\nlet aadSignin = aadFunc(\"SigninLogs\");\nlet aadNonInt = aadFunc(\"AADNonInteractiveUserSignInLogs\");\nunion isfuzzy=true aadSignin, aadNonInt\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -5166,35 +4415,35 @@ ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "identifier": "Name", - "columnName": "Name" + "columnName": "Name", + "identifier": "Name" }, { - "identifier": "UPNSuffix", - "columnName": "UPNSuffix" + "columnName": "UPNSuffix", + "identifier": "UPNSuffix" } - ] + ], + "entityType": "Account" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "IPAddress" + "columnName": "IPAddress", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -5250,7 +4499,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "IPEntity_VMConnection_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "IPEntity_VMConnection_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion27')]", @@ -5267,7 +4516,7 @@ "description": "This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in VMConnection.", "displayName": "TI Map IP Entity to VMConnection", "enabled": false, - "query": "let dt_lookBack = 1h; // Look back 1 hour for VMConnection events\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\";\n// Perform a join between IP indicators and VMConnection events\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n VMConnection\n | where TimeGenerated >= ago(dt_lookBack)\n | extend VMConnection_TimeGenerated = TimeGenerated\n )\n on $left.TI_ipEntity == $right.RemoteIp\n // Filter out VMConnection events that occurred after the expiration of the corresponding indicator\n | where VMConnection_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and keep the VMConnection event with the latest timestamp\n | summarize VMConnection_TimeGenerated = arg_max(VMConnection_TimeGenerated, *) by IndicatorId, RemoteIp\n // Select the desired output fields\n | project VMConnection_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\n TI_ipEntity, Computer, Direction, ProcessName, SourceIp, DestinationIp, RemoteIp, Protocol, DestinationPort, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type\n | extend timestamp = VMConnection_TimeGenerated, HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.'))\n", + "query": "let dt_lookBack = 1h; // Look back 1 hour for VMConnection events\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\"\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId;\n// Perform a join between IP indicators and VMConnection events\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n VMConnection\n | where TimeGenerated >= ago(dt_lookBack)\n | extend VMConnection_TimeGenerated = TimeGenerated\n )\n on $left.TI_ipEntity == $right.RemoteIp\n // Filter out VMConnection events that occurred after the expiration of the corresponding indicator\n | where VMConnection_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and keep the VMConnection event with the latest timestamp\n | summarize VMConnection_TimeGenerated = arg_max(VMConnection_TimeGenerated, *) by IndicatorId, RemoteIp\n // Select the desired output fields\n | project VMConnection_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\n TI_ipEntity, Computer, Direction, ProcessName, SourceIp, DestinationIp, RemoteIp, Protocol, DestinationPort, NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type\n | extend timestamp = VMConnection_TimeGenerated, HostName = tostring(split(Computer, '.', 0)[0]), DnsDomain = tostring(strcat_array(array_slice(split(Computer, '.'), 1, -1), '.'))\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -5307,35 +4556,35 @@ ], "entityMappings": [ { - "entityType": "Host", "fieldMappings": [ { - "identifier": "HostName", - "columnName": "HostName" + "columnName": "HostName", + "identifier": "HostName" }, { - "identifier": "DnsDomain", - "columnName": "DnsDomain" + "columnName": "DnsDomain", + "identifier": "DnsDomain" } - ] + ], + "entityType": "Host" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "RemoteIp" + "columnName": "RemoteIp", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -5391,7 +4640,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "IPEntity_W3CIISLog_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "IPEntity_W3CIISLog_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion28')]", @@ -5408,7 +4657,7 @@ "description": "This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in W3CIISLog.", "displayName": "TI Map IP Entity to W3CIISLog", "enabled": false, - "query": "let dt_lookBack = 1h; // Look back 1 hour for W3CIISLog events\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\";\n// Perform a join between IP indicators and W3CIISLog events\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n W3CIISLog\n | where TimeGenerated >= ago(dt_lookBack)\n | where isnotempty(cIP)\n | where ipv4_is_private(cIP) == false and cIP !startswith \"fe80\" and cIP !startswith \"::\" and cIP !startswith \"127.\"\n | extend W3CIISLog_TimeGenerated = TimeGenerated\n )\n on $left.TI_ipEntity == $right.cIP\n // Filter out W3CIISLog events that occurred after the expiration of the corresponding indicator\n | where W3CIISLog_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and keep the W3CIISLog event with the latest timestamp\n | summarize W3CIISLog_TimeGenerated = arg_max(W3CIISLog_TimeGenerated, *) by IndicatorId, cIP\n // Select the desired output fields\n | project timestamp = W3CIISLog_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\n TI_ipEntity, Computer, sSiteName, cIP, sIP, sPort, csMethod, csUserName, scStatus, scSubStatus, scWin32Status,\n NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type\n", + "query": "let dt_lookBack = 1h; // Look back 1 hour for W3CIISLog events\nlet ioc_lookBack = 14d; // Look back 14 days for threat intelligence indicators\n// Fetch threat intelligence indicators related to IP addresses\nlet IP_Indicators = ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack)\n | where Active == true and ExpirationDateTime > now()\n | where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n | extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n | extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n | where ipv4_is_private(TI_ipEntity) == false and TI_ipEntity !startswith \"fe80\" and TI_ipEntity !startswith \"::\" and TI_ipEntity !startswith \"127.\"\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId;\n// Perform a join between IP indicators and W3CIISLog events\nIP_Indicators\n // Use innerunique to keep performance fast and result set low, as we only need one match to indicate potential malicious activity that needs investigation\n | join kind=innerunique (\n W3CIISLog\n | where TimeGenerated >= ago(dt_lookBack)\n | where isnotempty(cIP)\n | where ipv4_is_private(cIP) == false and cIP !startswith \"fe80\" and cIP !startswith \"::\" and cIP !startswith \"127.\"\n | extend W3CIISLog_TimeGenerated = TimeGenerated\n )\n on $left.TI_ipEntity == $right.cIP\n // Filter out W3CIISLog events that occurred after the expiration of the corresponding indicator\n | where W3CIISLog_TimeGenerated < ExpirationDateTime\n // Group the results by IndicatorId and keep the W3CIISLog event with the latest timestamp\n | summarize W3CIISLog_TimeGenerated = arg_max(W3CIISLog_TimeGenerated, *) by IndicatorId, cIP\n // Select the desired output fields\n | project timestamp = W3CIISLog_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore,\n TI_ipEntity, Computer, sSiteName, cIP, sIP, sPort, csMethod, csUserName, scStatus, scSubStatus, scWin32Status,\n NetworkIP, NetworkDestinationIP, NetworkSourceIP, EmailSourceIpAddress, Type\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -5448,40 +4697,40 @@ ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "identifier": "Name", - "columnName": "csUserName" + "columnName": "csUserName", + "identifier": "Name" } - ] + ], + "entityType": "Account" }, { - "entityType": "Host", "fieldMappings": [ { - "identifier": "HostName", - "columnName": "Computer" + "columnName": "Computer", + "identifier": "HostName" } - ] + ], + "entityType": "Host" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "cIP" + "columnName": "cIP", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -5537,7 +4786,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "URLEntity_AuditLogs_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "URLEntity_AuditLogs_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion29')]", @@ -5554,7 +4803,7 @@ "description": "This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in AuditLogs.", "displayName": "TI Map URL Entity to AuditLogs", "enabled": false, - "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n| where Active == true\n// Picking up only IOC's that contain the entities we want\n| where isnotempty(Url)\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n AuditLogs\n | where TimeGenerated >= ago(dt_lookBack)\n // Extract the URL that is contained within the JSON data\n | extend Url = extract(\"(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\\\(\\\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+);\", 1,tostring(TargetResources))\n | where isnotempty(Url)\n | extend userPrincipalName = tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)\n | extend TargetResourceDisplayName = tostring(TargetResources[0].displayName)\n | extend Audit_TimeGenerated = TimeGenerated\n) on Url\n| where Audit_TimeGenerated < ExpirationDateTime\n| summarize Audit_TimeGenerated = arg_max(Audit_TimeGenerated, *) by IndicatorId, Url\n| project Audit_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore,\nOperationName, Identity, userPrincipalName, TargetResourceDisplayName, Url\n| extend timestamp = Audit_TimeGenerated, AccountCustomEntity = userPrincipalName, HostCustomEntity = TargetResourceDisplayName, URLCustomEntity = Url\n", + "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| where Active == true\n// Picking up only IOC's that contain the entities we want\n| where isnotempty(Url)\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n AuditLogs\n | where TimeGenerated >= ago(dt_lookBack)\n // Extract the URL that is contained within the JSON data\n | extend Url = extract(\"(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\\\(\\\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+);\", 1,tostring(TargetResources))\n | where isnotempty(Url)\n | extend userPrincipalName = tostring(parse_json(tostring(InitiatedBy.user)).userPrincipalName)\n | extend TargetResourceDisplayName = tostring(TargetResources[0].displayName)\n | extend Audit_TimeGenerated = TimeGenerated\n) on Url\n| where Audit_TimeGenerated < ExpirationDateTime\n| summarize Audit_TimeGenerated = arg_max(Audit_TimeGenerated, *) by IndicatorId, Url\n| project Audit_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore,\nOperationName, Identity, userPrincipalName, TargetResourceDisplayName, Url\n| extend timestamp = Audit_TimeGenerated, AccountCustomEntity = userPrincipalName, HostCustomEntity = TargetResourceDisplayName, URLCustomEntity = Url\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -5594,31 +4843,31 @@ ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "identifier": "FullName", - "columnName": "AccountCustomEntity" + "columnName": "AccountCustomEntity", + "identifier": "FullName" } - ] + ], + "entityType": "Account" }, { - "entityType": "Host", "fieldMappings": [ { - "identifier": "FullName", - "columnName": "HostCustomEntity" + "columnName": "HostCustomEntity", + "identifier": "FullName" } - ] + ], + "entityType": "Host" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "URLCustomEntity" + "columnName": "URLCustomEntity", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -5674,7 +4923,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "URLEntity_OfficeActivity_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "URLEntity_OfficeActivity_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion30')]", @@ -5691,7 +4940,7 @@ "description": "This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in OfficeActivity data.", "displayName": "TI Map URL Entity to OfficeActivity Data", "enabled": false, - "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n| where Active == true\n// Picking up only IOC's that contain the entities we want\n| where isnotempty(Url)\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n OfficeActivity\n | where TimeGenerated >= ago(dt_lookBack)\n //Extract the Url from a number of potential fields\n | extend Url = iif(OfficeWorkload == \"AzureActiveDirectory\",extract(\"(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\\\(\\\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+);\", 1,ModifiedProperties),tostring(parse_json(ModifiedProperties)[12].NewValue))\n | where isnotempty(Url)\n // Ensure we get a clean URL\n | extend Url = tostring(split(Url, ';')[0])\n | extend OfficeActivity_TimeGenerated = TimeGenerated\n // Project a single user identity that we can use for entity mapping\n | extend User = iif(isnotempty(UserId), UserId, iif(isnotempty(Actor), tostring(parse_json(Actor)[0].ID), tostring(parse_json(Parameters)[0].Value)))\n) on Url\n| where OfficeActivity_TimeGenerated < ExpirationDateTime\n| summarize OfficeActivity_TimeGenerated = arg_max(OfficeActivity_TimeGenerated, *) by IndicatorId, Url\n| project OfficeActivity_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, Operation,\nUserType, OfficeWorkload, Parameters, Url, User\n| extend timestamp = OfficeActivity_TimeGenerated, Name = tostring(split(User, '@', 0)[0]), UPNSuffix = tostring(split(User, '@', 1)[0])\n", + "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| where Active == true\n// Picking up only IOC's that contain the entities we want\n| where isnotempty(Url)\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n OfficeActivity\n | where TimeGenerated >= ago(dt_lookBack)\n //Extract the Url from a number of potential fields\n | extend Url = iif(OfficeWorkload == \"AzureActiveDirectory\",extract(\"(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\\\(\\\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+);\", 1,ModifiedProperties),tostring(parse_json(ModifiedProperties)[12].NewValue))\n | where isnotempty(Url)\n // Ensure we get a clean URL\n | extend Url = tostring(split(Url, ';')[0])\n | extend OfficeActivity_TimeGenerated = TimeGenerated\n // Project a single user identity that we can use for entity mapping\n | extend User = iif(isnotempty(UserId), UserId, iif(isnotempty(Actor), tostring(parse_json(Actor)[0].ID), tostring(parse_json(Parameters)[0].Value)))\n) on Url\n| where OfficeActivity_TimeGenerated < ExpirationDateTime\n| summarize OfficeActivity_TimeGenerated = arg_max(OfficeActivity_TimeGenerated, *) by IndicatorId, Url\n| project OfficeActivity_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, Operation,\nUserType, OfficeWorkload, Parameters, Url, User\n| extend timestamp = OfficeActivity_TimeGenerated, Name = tostring(split(User, '@', 0)[0]), UPNSuffix = tostring(split(User, '@', 1)[0])\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -5718,6 +4967,12 @@ "dataTypes": [ "ThreatIntelligenceIndicator" ] + }, + { + "connectorId": "ThreatIntelligenceTaxii", + "dataTypes": [ + "ThreatIntelligenceIndicator" + ] } ], "tactics": [ @@ -5725,26 +4980,26 @@ ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "identifier": "Name", - "columnName": "Name" + "columnName": "Name", + "identifier": "Name" }, { - "identifier": "UPNSuffix", - "columnName": "UPNSuffix" + "columnName": "UPNSuffix", + "identifier": "UPNSuffix" } - ] + ], + "entityType": "Account" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -5800,7 +5055,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "URLEntity_PaloAlto_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "URLEntity_PaloAlto_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion31')]", @@ -5817,7 +5072,7 @@ "description": "This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in PaloAlto Data.", "displayName": "TI Map URL Entity to PaloAlto Data", "enabled": false, - "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n| where Active == true\n// Picking up only IOC's that contain the entities we want\n| where isnotempty(Url)\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n CommonSecurityLog\n | extend IngestionTime = ingestion_time()\n | where IngestionTime > ago(dt_lookBack)\n // Select on Palo Alto logs\n | where DeviceVendor =~ \"Palo Alto Networks\"\n | where DeviceEventClassID =~ 'url'\n //Uncomment the line below to only alert on allowed connections\n //| where DeviceAction !~ \"block-url\"\n //Select logs where URL data is populated\n | extend PA_Url = column_ifexists(\"RequestURL\", \"None\")\n | extend PA_Url = iif(isempty(PA_Url), extract(\"([^\\\"]+)\", 1, tolower(AdditionalExtensions)), trim('\"', PA_Url))\n | extend PA_Url = iif(PA_Url !startswith \"http://\" and ApplicationProtocol !~ \"ssl\", strcat('http://', PA_Url), iif(PA_Url !startswith \"https://\" and ApplicationProtocol =~ \"ssl\", strcat('https://', PA_Url), PA_Url))\n | where isnotempty(PA_Url)\n | extend CommonSecurityLog_TimeGenerated = TimeGenerated\n) on $left.Url == $right.PA_Url\n| where CommonSecurityLog_TimeGenerated < ExpirationDateTime\n| summarize CommonSecurityLog_TimeGenerated = arg_max(CommonSecurityLog_TimeGenerated, *) by IndicatorId, PA_Url\n| project timestamp = CommonSecurityLog_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, DeviceAction, SourceIP, PA_Url, DeviceName\n", + "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| where Active == true\n// Picking up only IOC's that contain the entities we want\n| where isnotempty(Url)\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n CommonSecurityLog\n | extend IngestionTime = ingestion_time()\n | where IngestionTime > ago(dt_lookBack)\n // Select on Palo Alto logs\n | where DeviceVendor =~ \"Palo Alto Networks\"\n | where DeviceEventClassID =~ 'url'\n //Uncomment the line below to only alert on allowed connections\n //| where DeviceAction !~ \"block-url\"\n //Select logs where URL data is populated\n | extend PA_Url = column_ifexists(\"RequestURL\", \"None\")\n | extend PA_Url = iif(isempty(PA_Url), extract(\"([^\\\"]+)\", 1, tolower(AdditionalExtensions)), trim('\"', PA_Url))\n | extend PA_Url = iif(PA_Url !startswith \"http://\" and ApplicationProtocol !~ \"ssl\", strcat('http://', PA_Url), iif(PA_Url !startswith \"https://\" and ApplicationProtocol =~ \"ssl\", strcat('https://', PA_Url), PA_Url))\n | where isnotempty(PA_Url)\n | extend CommonSecurityLog_TimeGenerated = TimeGenerated\n) on $left.Url == $right.PA_Url\n| where CommonSecurityLog_TimeGenerated < ExpirationDateTime\n| summarize CommonSecurityLog_TimeGenerated = arg_max(CommonSecurityLog_TimeGenerated, *) by IndicatorId, PA_Url\n| project timestamp = CommonSecurityLog_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, DeviceAction, SourceIP, PA_Url, DeviceName\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -5857,31 +5112,31 @@ ], "entityMappings": [ { - "entityType": "Host", "fieldMappings": [ { - "identifier": "HostName", - "columnName": "DeviceName" + "columnName": "DeviceName", + "identifier": "HostName" } - ] + ], + "entityType": "Host" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "SourceIP" + "columnName": "SourceIP", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "PA_Url" + "columnName": "PA_Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -5937,7 +5192,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "URLEntity_SecurityAlerts_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "URLEntity_SecurityAlerts_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion32')]", @@ -5954,7 +5209,7 @@ "description": "This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in SecurityAlert data.", "displayName": "TI Map URL Entity to SecurityAlert Data", "enabled": false, - "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet URLRegex = \"((https?|ftp|ldap|wss?|file):\\\\/\\\\/(([\\\\:\\\\%\\\\w\\\\_\\\\-]+(\\\\.|@))*((xn--)?[a-zA-Z0-9\\\\-]+\\\\.)+(xn--[a-z0-9]+|[A-Za-z]+)|\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{0,3})[.,:\\\\w@?^=%&\\\\/~+#-]*[\\\\w@?^=%&\\\\/~+#-])\";\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n| where Active == true\n// Picking up only IOC's that contain the entities we want\n| where isnotempty(Url)\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\nSecurityAlert\n| where TimeGenerated >= ago(dt_lookBack)\n| extend MSTI = case(AlertName has \"TI map\" and VendorName == \"Microsoft\" and ProductName == 'Azure Sentinel', true, false)\n| where MSTI == false\n// Extract URL from JSON data\n| extend Url = todynamic(dynamic_to_json(extract_all(URLRegex, dynamic([1]), Entities))) \n| mv-expand Url\n| extend Url = tostring(Url[0])\n// We only want alerts that actually contain URL data\n| where isnotempty(Url)\n// Extract hostname from JSON data for entity mapping\n| extend Compromised_Host = tostring(parse_json(ExtendedProperties).[\"Compromised Host\"])\n| extend Alert_TimeGenerated = TimeGenerated\n) on Url\n| where Alert_TimeGenerated < ExpirationDateTime\n| summarize Alert_TimeGenerated = arg_max(Alert_TimeGenerated, *) by IndicatorId, AlertName\n| project timestamp = Alert_TimeGenerated, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, AlertName, AlertSeverity, Description, Url, Compromised_Host\n", + "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet URLRegex = \"((https?|ftp|ldap|wss?|file):\\\\/\\\\/(([\\\\:\\\\%\\\\w\\\\_\\\\-]+(\\\\.|@))*((xn--)?[a-zA-Z0-9\\\\-]+\\\\.)+(xn--[a-z0-9]+|[A-Za-z]+)|\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{0,3})[.,:\\\\w@?^=%&\\\\/~+#-]*[\\\\w@?^=%&\\\\/~+#-])\";\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| where Active == true\n// Picking up only IOC's that contain the entities we want\n| where isnotempty(Url)\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\nSecurityAlert\n| where TimeGenerated >= ago(dt_lookBack)\n| extend MSTI = case(AlertName has \"TI map\" and VendorName == \"Microsoft\" and ProductName == 'Azure Sentinel', true, false)\n| where MSTI == false\n// Extract URL from JSON data\n| extend Url = todynamic(dynamic_to_json(extract_all(URLRegex, dynamic([1]), Entities))) \n| mv-expand Url\n| extend Url = tostring(Url[0])\n// We only want alerts that actually contain URL data\n| where isnotempty(Url)\n// Extract hostname from JSON data for entity mapping\n| extend Compromised_Host = tostring(parse_json(ExtendedProperties).[\"Compromised Host\"])\n| extend Alert_TimeGenerated = TimeGenerated\n) on Url\n| where Alert_TimeGenerated < ExpirationDateTime\n| summarize Alert_TimeGenerated = arg_max(Alert_TimeGenerated, *) by IndicatorId, AlertName\n| project timestamp = Alert_TimeGenerated, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, AlertName, AlertSeverity, Description, Url, Compromised_Host\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -6000,22 +5255,22 @@ ], "entityMappings": [ { - "entityType": "Host", "fieldMappings": [ { - "identifier": "HostName", - "columnName": "Compromised_Host" + "columnName": "Compromised_Host", + "identifier": "HostName" } - ] + ], + "entityType": "Host" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -6071,7 +5326,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "URLEntity_Syslog_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "URLEntity_Syslog_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion33')]", @@ -6088,7 +5343,7 @@ "description": "This query identifies any URL indicators of compromise (IOCs) from threat intelligence (TI) by searching for matches in Syslog data.", "displayName": "TI Map URL Entity to Syslog Data", "enabled": false, - "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n| where Active == true\n// Picking up only IOC's that contain the entities we want\n| where isnotempty(Url)\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n Syslog\n | where TimeGenerated >= ago(dt_lookBack)\n // Extract URL from the Syslog message but only take messages that include URLs\n | extend Url = extract(\"(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\\\(\\\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)\", 1,SyslogMessage)\n | where isnotempty(Url)\n | extend Syslog_TimeGenerated = TimeGenerated\n) on Url\n| where Syslog_TimeGenerated < ExpirationDateTime\n| summarize Syslog_TimeGenerated = arg_max(Syslog_TimeGenerated , *) by IndicatorId, Url\n| project timestamp = Syslog_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, SyslogMessage, Computer, ProcessName, Url, HostIP\n", + "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| where Active == true\n// Picking up only IOC's that contain the entities we want\n| where isnotempty(Url)\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n// using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique (\n Syslog\n | where TimeGenerated >= ago(dt_lookBack)\n // Extract URL from the Syslog message but only take messages that include URLs\n | extend Url = extract(\"(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\\\(\\\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)\", 1,SyslogMessage)\n | where isnotempty(Url)\n | extend Syslog_TimeGenerated = TimeGenerated\n) on Url\n| where Syslog_TimeGenerated < ExpirationDateTime\n| summarize Syslog_TimeGenerated = arg_max(Syslog_TimeGenerated , *) by IndicatorId, Url\n| project timestamp = Syslog_TimeGenerated, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, SyslogMessage, Computer, ProcessName, Url, HostIP\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -6128,31 +5383,31 @@ ], "entityMappings": [ { - "entityType": "Host", "fieldMappings": [ { - "identifier": "HostName", - "columnName": "Computer" + "columnName": "Computer", + "identifier": "HostName" } - ] + ], + "entityType": "Host" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "HostIP" + "columnName": "HostIP", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "Url" + "columnName": "Url", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ] } @@ -6208,7 +5463,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "IPEntity_DuoSecurity_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "IPEntity_DuoSecurity_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion34')]", @@ -6225,7 +5480,7 @@ "description": "This query maps any IP indicators of compromise (IOCs) from threat intelligence (TI), by searching for matches in DuoSecurity.", "displayName": "TI Map IP Entity to Duo Security", "enabled": false, - "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n| where Active == true\n// Picking up only IOC's that contain the entities we want\n| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n// As there is potentially more than 1 indicator type for matching IP, taking NetworkIP first, then others if that is empty.\n// Taking the first non-empty value based on potential IOC match availability\n| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n| join (\n DuoSecurityAuthentication_CL\n | where TimeGenerated >= ago(dt_lookBack)\n | where isnotempty(access_device_ip_s)\n // renaming time column so it is clear the log this came from\n | extend Duo_TimeGenerated = isotimestamp_t\n)\non $left.TI_ipEntity == $right.access_device_ip_s\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n| project LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, Duo_TimeGenerated,\nTI_ipEntity, user_name_s, factor_s, result_s, application_name_s, event_type_s, txid_g, user_key_s, access_device_ip_s, access_device_location_city_s, access_device_location_state_s, access_device_location_country_s\n| extend timestamp = Duo_TimeGenerated, Name = tostring(split(user_name_s, '@', 0)[0]), UPNSuffix = tostring(split(user_name_s, '@', 1)[0])\n", + "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| where Active == true\n// Picking up only IOC's that contain the entities we want\n| where isnotempty(NetworkIP) or isnotempty(EmailSourceIpAddress) or isnotempty(NetworkDestinationIP) or isnotempty(NetworkSourceIP)\n// As there is potentially more than 1 indicator type for matching IP, taking NetworkIP first, then others if that is empty.\n// Taking the first non-empty value based on potential IOC match availability\n| extend TI_ipEntity = iff(isnotempty(NetworkIP), NetworkIP, NetworkDestinationIP)\n| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(NetworkSourceIP), NetworkSourceIP, TI_ipEntity)\n| extend TI_ipEntity = iff(isempty(TI_ipEntity) and isnotempty(EmailSourceIpAddress), EmailSourceIpAddress, TI_ipEntity)\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n| join (\n DuoSecurityAuthentication_CL\n | where TimeGenerated >= ago(dt_lookBack)\n | where isnotempty(access_device_ip_s)\n // renaming time column so it is clear the log this came from\n | extend Duo_TimeGenerated = isotimestamp_t\n)\non $left.TI_ipEntity == $right.access_device_ip_s\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n| project LatestIndicatorTime, Description, ActivityGroupNames, IndicatorId, ThreatType, Url, ExpirationDateTime, ConfidenceScore, Duo_TimeGenerated,\nTI_ipEntity, user_name_s, factor_s, result_s, application_name_s, event_type_s, txid_g, user_key_s, access_device_ip_s, access_device_location_city_s, access_device_location_state_s, access_device_location_country_s\n| extend timestamp = Duo_TimeGenerated, Name = tostring(split(user_name_s, '@', 0)[0]), UPNSuffix = tostring(split(user_name_s, '@', 1)[0])\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -6265,26 +5520,26 @@ ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "identifier": "Name", - "columnName": "Name" + "columnName": "Name", + "identifier": "Name" }, { - "identifier": "UPNSuffix", - "columnName": "UPNSuffix" + "columnName": "UPNSuffix", + "identifier": "UPNSuffix" } - ] + ], + "entityType": "Account" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "access_device_ip_s" + "columnName": "access_device_ip_s", + "identifier": "Address" } - ] + ], + "entityType": "IP" } ] } @@ -6340,7 +5595,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "imDns_DomainEntity_DnsEvents_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "imDns_DomainEntity_DnsEvents_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion35')]", @@ -6439,45 +5694,45 @@ ], "entityMappings": [ { - "entityType": "Host", "fieldMappings": [ { - "identifier": "FullName", - "columnName": "HostCustomEntity" + "columnName": "HostCustomEntity", + "identifier": "FullName" } - ] + ], + "entityType": "Host" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "IPCustomEntity" + "columnName": "IPCustomEntity", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "URL", "fieldMappings": [ { - "identifier": "Url", - "columnName": "URLCustomEntity" + "columnName": "URLCustomEntity", + "identifier": "Url" } - ] + ], + "entityType": "URL" } ], "customDetails": { - "DnsQuery": "DnsQuery", - "IndicatorId": "IndicatorId", - "Description": "Description", - "ThreatType": "ThreatType", + "QueryType": "DnsQueryType", "ActivityGroupNames": "ActivityGroupNames", "DNSRequestTime": "DNS_TimeGenerated", - "QueryType": "DnsQueryType", - "SourceIPAddress": "SrcIpAddr", + "IndicatorId": "IndicatorId", + "ThreatType": "ThreatType", "ConfidenceScore": "ConfidenceScore", "LatestIndicatorTime": "LatestIndicatorTime", - "ExpirationDateTime": "ExpirationDateTime" + "Description": "Description", + "SourceIPAddress": "SrcIpAddr", + "ExpirationDateTime": "ExpirationDateTime", + "DnsQuery": "DnsQuery" } } }, @@ -6532,7 +5787,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "imDns_IPEntity_DnsEvents_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "imDns_IPEntity_DnsEvents_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion36')]", @@ -6549,7 +5804,7 @@ "description": "This rule identifies DNS requests for which response IP address is a known IoC.

\nThis analytic rule uses [ASIM](https://aka.ms/AboutASIM) and supports any built-in or custom source that supports the ASIM DNS schema.", "displayName": "TI map IP entity to DNS Events (ASIM DNS schema)", "enabled": false, - "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet IP_TI = \nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n| where Active == true\n| extend IoC = coalesce(NetworkIP, NetworkDestinationIP, NetworkSourceIP,EmailSourceIpAddress,\"NO_IP\")\n| where IoC != \"NO_IP\"\n;\nIP_TI\n| join kind=innerunique // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n(\n_Im_Dns(starttime=ago(dt_lookBack))\n| where isnotempty(DnsResponseName)\n| summarize imDns_mintime=min(TimeGenerated), imDns_maxtime=max(TimeGenerated) by SrcIpAddr, DnsQuery, DnsResponseName, Dvc, EventProduct, EventVendor\n| extend addresses = extract_all (@'(\\d+\\.\\d+\\.\\d+\\.\\d+)', DnsResponseName)\n| mv-expand IoC = addresses to typeof(string)\n)\non IoC\n| where imDns_mintime < ExpirationDateTime\n| project imDns_mintime, imDns_maxtime, Description, ActivityGroupNames, IndicatorId, ThreatType, LatestIndicatorTime, ExpirationDateTime, ConfidenceScore, SrcIpAddr, IoC, Dvc, EventVendor, EventProduct, DnsQuery, DnsResponseName\n", + "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet IP_TI = \nThreatIntelligenceIndicator\n| where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n| where Active == true\n| extend IoC = coalesce(NetworkIP, NetworkDestinationIP, NetworkSourceIP,EmailSourceIpAddress,\"NO_IP\")\n| where IoC != \"NO_IP\"\n| summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n;\nIP_TI\n| join kind=innerunique // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n(\n_Im_Dns(starttime=ago(dt_lookBack))\n| where isnotempty(DnsResponseName)\n| summarize imDns_mintime=min(TimeGenerated), imDns_maxtime=max(TimeGenerated) by SrcIpAddr, DnsQuery, DnsResponseName, Dvc, EventProduct, EventVendor\n| extend addresses = extract_all (@'(\\d+\\.\\d+\\.\\d+\\.\\d+)', DnsResponseName)\n| mv-expand IoC = addresses to typeof(string)\n)\non IoC\n| where imDns_mintime < ExpirationDateTime\n| project imDns_mintime, imDns_maxtime, Description, ActivityGroupNames, IndicatorId, ThreatType, LatestIndicatorTime, ExpirationDateTime, ConfidenceScore, SrcIpAddr, IoC, Dvc, EventVendor, EventProduct, DnsQuery, DnsResponseName\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -6631,44 +5886,44 @@ ], "entityMappings": [ { - "entityType": "Host", "fieldMappings": [ { - "identifier": "FullName", - "columnName": "Dvc" + "columnName": "Dvc", + "identifier": "FullName" } - ] + ], + "entityType": "Host" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "IoC" + "columnName": "IoC", + "identifier": "Address" } - ] + ], + "entityType": "IP" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "SrcIpAddr" + "columnName": "SrcIpAddr", + "identifier": "Address" } - ] + ], + "entityType": "IP" } ], "customDetails": { - "DnsQuery": "DnsQuery", - "IndicatorId": "IndicatorId", - "Description": "Description", - "ThreatType": "ThreatType", "ActivityGroupNames": "ActivityGroupNames", "DNSRequestTime": "imDns_mintime", - "SourceIPAddress": "SrcIpAddr", + "IndicatorId": "IndicatorId", + "ThreatType": "ThreatType", "ConfidenceScore": "ConfidenceScore", "LatestIndicatorTime": "LatestIndicatorTime", - "ExpirationDateTime": "ExpirationDateTime" + "Description": "Description", + "SourceIPAddress": "SrcIpAddr", + "ExpirationDateTime": "ExpirationDateTime", + "DnsQuery": "DnsQuery" }, "alertDetailsOverride": { "alertDisplayNameFormat": "The response {{IoC}} to DNS query matched an IoC", @@ -6727,7 +5982,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "IPEntity_imNetworkSession_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "IPEntity_imNetworkSession_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion37')]", @@ -6744,7 +5999,7 @@ "description": "This rule identifies a match Network Sessions for which the source or destination IP address is a known IoC.

\nThis analytic rule uses [ASIM](https://aka.ms/AboutASIM) and supports any built-in or custom source that supports the ASIM NetworkSession schema", "displayName": "TI map IP entity to Network Session Events (ASIM Network Session schema)", "enabled": false, - "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet IP_TI = materialize (\n ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n | where Active == true\n | extend TI_ipEntity = coalesce(NetworkIP, NetworkDestinationIP, NetworkSourceIP,EmailSourceIpAddress,\"NO_IP\")\n | where TI_ipEntity != \"NO_IP\"\n);\nIP_TI\n // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique \n(\n _Im_NetworkSession (starttime=ago(dt_lookBack))\n | where isnotempty(SrcIpAddr)\n | summarize imNWS_mintime=min(TimeGenerated), imNWS_maxtime=max(TimeGenerated) by SrcIpAddr, DstIpAddr, Dvc, EventProduct, EventVendor \n | lookup (IP_TI | project TI_ipEntity, Active) on $left.SrcIpAddr == $right.TI_ipEntity\n | project-rename SrcMatch = Active\n | lookup (IP_TI | project TI_ipEntity, Active) on $left.DstIpAddr == $right.TI_ipEntity\n | project-rename DstMatch = Active\n | where SrcMatch or DstMatch\n | extend \n IoCIP = iff(SrcMatch, SrcIpAddr, DstIpAddr),\n IoCDirection = iff(SrcMatch, \"Source\", \"Destination\")\n)on $left.TI_ipEntity == $right.IoCIP\n| where imNWS_mintime < ExpirationDateTime\n| project imNWS_mintime, imNWS_maxtime, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, SrcIpAddr, DstIpAddr, IoCDirection, IoCIP, Dvc, EventVendor, EventProduct\n", + "query": "let dt_lookBack = 1h;\nlet ioc_lookBack = 14d;\nlet IP_TI = materialize (\n ThreatIntelligenceIndicator\n | where TimeGenerated >= ago(ioc_lookBack) and ExpirationDateTime > now()\n | where Active == true\n | extend TI_ipEntity = coalesce(NetworkIP, NetworkDestinationIP, NetworkSourceIP,EmailSourceIpAddress,\"NO_IP\")\n | where TI_ipEntity != \"NO_IP\"\n | summarize LatestIndicatorTime = arg_max(TimeGenerated, *) by IndicatorId\n);\nIP_TI\n // using innerunique to keep perf fast and result set low, we only need one match to indicate potential malicious activity that needs to be investigated\n| join kind=innerunique \n(\n _Im_NetworkSession (starttime=ago(dt_lookBack))\n | where isnotempty(SrcIpAddr)\n | summarize imNWS_mintime=min(TimeGenerated), imNWS_maxtime=max(TimeGenerated) by SrcIpAddr, DstIpAddr, Dvc, EventProduct, EventVendor \n | lookup (IP_TI | project TI_ipEntity, Active) on $left.SrcIpAddr == $right.TI_ipEntity\n | project-rename SrcMatch = Active\n | lookup (IP_TI | project TI_ipEntity, Active) on $left.DstIpAddr == $right.TI_ipEntity\n | project-rename DstMatch = Active\n | where SrcMatch or DstMatch\n | extend \n IoCIP = iff(SrcMatch, SrcIpAddr, DstIpAddr),\n IoCDirection = iff(SrcMatch, \"Source\", \"Destination\")\n)on $left.TI_ipEntity == $right.IoCIP\n| where imNWS_mintime < ExpirationDateTime\n| project imNWS_mintime, imNWS_maxtime, Description, ActivityGroupNames, IndicatorId, ThreatType, ExpirationDateTime, ConfidenceScore, SrcIpAddr, DstIpAddr, IoCDirection, IoCIP, Dvc, EventVendor, EventProduct\n", "queryFrequency": "PT1H", "queryPeriod": "P14D", "severity": "Medium", @@ -6856,6 +6111,12 @@ "Syslog", "CiscoMerakiNativePoller" ] + }, + { + "connectorId": "ThreatIntelligenceTaxii", + "dataTypes": [ + "ThreatIntelligenceIndicator" + ] } ], "tactics": [ @@ -6863,25 +6124,25 @@ ], "entityMappings": [ { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "IoCIP" + "columnName": "IoCIP", + "identifier": "Address" } - ] + ], + "entityType": "IP" } ], "customDetails": { - "IndicatorId": "IndicatorId", - "IoCConfidenceScore": "ConfidenceScore", "IoCDescription": "Description", - "IoCExpirationTime": "ExpirationDateTime", - "EventEndTime": "imNWS_maxtime", + "IoCConfidenceScore": "ConfidenceScore", "ActivityGroupNames": "ActivityGroupNames", + "EventStartTime": "imNWS_mintime", + "IndicatorId": "IndicatorId", "ThreatType": "ThreatType", "IoCIPDirection": "IoCDirection", - "EventStartTime": "imNWS_mintime" + "EventEndTime": "imNWS_maxtime", + "IoCExpirationTime": "ExpirationDateTime" }, "alertDetailsOverride": { "alertDisplayNameFormat": "A network session {{IoCDirection}} address {{IoCIP}} matched an IoC.", @@ -6940,7 +6201,7 @@ "[extensionResourceId(resourceId('Microsoft.OperationalInsights/workspaces', parameters('workspace')), 'Microsoft.SecurityInsights/contentPackages', variables('_solutionId'))]" ], "properties": { - "description": "Threat Intel Matches to GitHub Audit Logs_AnalyticalRules Analytics Rule with template version 3.0.1", + "description": "Threat Intel Matches to GitHub Audit Logs_AnalyticalRules Analytics Rule with template version 3.0.2", "mainTemplate": { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", "contentVersion": "[variables('analyticRuleVersion38')]", @@ -6991,22 +6252,22 @@ ], "entityMappings": [ { - "entityType": "Account", "fieldMappings": [ { - "identifier": "FullName", - "columnName": "AccountCustomEntity" + "columnName": "AccountCustomEntity", + "identifier": "FullName" } - ] + ], + "entityType": "Account" }, { - "entityType": "IP", "fieldMappings": [ { - "identifier": "Address", - "columnName": "IPCustomEntity" + "columnName": "IPCustomEntity", + "identifier": "Address" } - ] + ], + "entityType": "IP" } ] } @@ -7058,12 +6319,12 @@ "apiVersion": "2023-04-01-preview", "location": "[parameters('workspace-location')]", "properties": { - "version": "3.0.1", + "version": "3.0.2", "kind": "Solution", "contentSchemaVersion": "3.0.0", "displayName": "Threat Intelligence", "publisherDisplayName": "Microsoft Sentinel, Microsoft Corporation", - "descriptionHtml": "

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

\n

The Threat Intelligence solution contains data connectors for import of threat indicators into Microsoft Sentinel, analytic rules for matching TI data with event data, workbook, and hunting queries. Threat indicators can be malicious IP's, URL's, filehashes, domains, email addresses etc.

\n

Data Connectors: 4, Workbooks: 1, Analytic Rules: 38, Hunting Queries: 5

\n

Learn more about Microsoft Sentinel | Learn more about Solutions

\n", + "descriptionHtml": "

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

\n

The Threat Intelligence solution contains data connectors for import of threat indicators into Microsoft Sentinel, analytic rules for matching TI data with event data, workbook, and hunting queries. Threat indicators can be malicious IP's, URL's, filehashes, domains, email addresses etc.

\n

Workbooks: 1, Analytic Rules: 38, Hunting Queries: 5

\n

Learn more about Microsoft Sentinel | Learn more about Solutions

\n", "contentKind": "Solution", "contentProductId": "[variables('_solutioncontentProductId')]", "id": "[variables('_solutioncontentProductId')]", @@ -7088,26 +6349,6 @@ "dependencies": { "operator": "AND", "criteria": [ - { - "kind": "DataConnector", - "contentId": "[variables('_dataConnectorContentId1')]", - "version": "[variables('dataConnectorVersion1')]" - }, - { - "kind": "DataConnector", - "contentId": "[variables('_dataConnectorContentId2')]", - "version": "[variables('dataConnectorVersion2')]" - }, - { - "kind": "DataConnector", - "contentId": "[variables('_dataConnectorContentId3')]", - "version": "[variables('dataConnectorVersion3')]" - }, - { - "kind": "DataConnector", - "contentId": "[variables('_dataConnectorContentId4')]", - "version": "[variables('dataConnectorVersion4')]" - }, { "kind": "Workbook", "contentId": "[variables('_workbookContentId1')]", diff --git a/Solutions/Threat Intelligence/ReleaseNotes.md b/Solutions/Threat Intelligence/ReleaseNotes.md index c024a79d3fd..5f51f0c86d2 100644 --- a/Solutions/Threat Intelligence/ReleaseNotes.md +++ b/Solutions/Threat Intelligence/ReleaseNotes.md @@ -1,5 +1,6 @@ | **Version** | **Date Modified (DD-MM-YYYY)** | **Change History** | -|-------------|--------------------------------|---------------------------------------------| +|-------------|--------------------------------|---------------------------------------------|] +| 3.0.2 | 23-10-2023 | Updated KQL of analytic rules to improve performance in large datasets | | 3.0.1 | 22-08-2023 | Removed (Preview) from Name field in **Analytical Rules** | | 3.0.0 | 14-08-2023 | Modified **Analytical Rule** (TI map Domain entity to SecurityAlert). Updated dynamic([1]) to dynamic([1,1]) so as to make result array of array consistent. | | | | Updated **Hunting Queries** to have descriptions that meet the 255 characters limit. |